diff --git a/README.md b/README.md index acad7d2..d0fa325 100644 --- a/README.md +++ b/README.md @@ -22,14 +22,16 @@ This makes it easy to see how our fork differs from the official release. The current sources are based on the following version of ASM ([browse tags here](http://websvn.ow2.org/listing.php?repname=asm&path=%2Ftags%2F&peg=1748)): ``` -Version 5.0.3, SVN r1748, tags/ASM_5_0_3 +Version 5.0.4, SVN r1779, tags/ASM_5_0_4 ``` +Previous ASM Upgrade PR: https://github.com/scala/scala-asm/pull/5 + ## Upgrading ASM Start by deleting all source files and copy the ones from the latest ASM release. -The original ASM sources are in an SVN repository, which is mirrored here: https://github.com/lrytz/asm. +The original ASM sources are in an [SVN repository](http://forge.ow2.org/plugins/scmsvn/index.php?group_id=23), which is mirrored here: https://github.com/lrytz/asm. You can use this mirror, your own git-svn mirror, or the original SVN repository to grab the sources of a new ASM version. A description how to work with the git-svn clone is here: https://github.com/lrytz/asm/issues/1. @@ -39,27 +41,24 @@ Excluded Files (don't copy): * `org/objectweb/asm/optimizer` * `org/objectweb/asm/xml` -*The below will change once a first is done in the new `scala/scala-asm` repository.* -*In the new repository, it probably makes sense to only squash the "Re-packaging and cosmetic changes".* -*The "actual changes" can then stay in the commit history.* - -Check the commit history of `src/asm`: https://github.com/scala/scala/commits/2.11.x/src/asm. -Find the previous commit that upgraded ASM and take a look at its commit message. -It should be a squashed version of a pull request that shows the precise procedure how the last upgrade was made. +Take a look at the previous PR that upgraded ASM [(see above)](#current-version). +Follow the upgrade procedure in the same way. -Re-packaging and cosmetic changes: +The re-packaging and cleanup commits can be applied using the following commands: * convert line endings (there are some `CRLF`) - `find src/asm/scala/tools/asm -name '*.java' | xargs dos2unix` + `find src -name '*.java' | xargs dos2unix` * change package clauses - `find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/package org\.objectweb\.asm/package scala.tools.asm/'` + `find src -name '*.java' | xargs sed -i '' -e 's/package org\.objectweb\.asm/package scala.tools.asm/'` * update imports - `find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/import org\.objectweb\.asm/import scala.tools.asm/'` + `find src -name '*.java' | xargs sed -i '' -e 's/import org\.objectweb\.asm/import scala.tools.asm/'` * update `@links`, `@associates` - `find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/@link org\.objectweb\.asm/@link scala.tools.asm/'` - `find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/@associates org\.objectweb\.asm/@associates scala.tools.asm/'` + `find src -name '*.java' | xargs sed -i '' -e 's/@link org\.objectweb\.asm/@link scala.tools.asm/'` + `find src -name '*.java' | xargs sed -i '' -e 's/@associates org\.objectweb\.asm/@associates scala.tools.asm/'` * remove trailing whitespace - `find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/[ ]*$//'` + `find src -name '*.java' | xargs sed -i '' -e 's/[ ]*$//'` + +Cherry-pick the actual changes that we have in our fork: + * Include the commits labelled `[asm-cherry-pick]` in the previous upgrade PR + * Include the changes to `src` that were added since the last upgrade, and label them `[asm-cherry-pick]` -Include the actual changes that we have in our repostiory - * Include the commits labelled `[asm-cherry-pick]` in the non-squashed PR of the previous upgrade - * Include the changes that were added to src/asm since the last upgrade and label them `[asm-cherry-pick]` +Update the ["Current Version"](#current-version) section of this README. diff --git a/src/main/java/scala/tools/asm/ClassReader.java b/src/main/java/scala/tools/asm/ClassReader.java index 8b0e12c..47039b0 100644 --- a/src/main/java/scala/tools/asm/ClassReader.java +++ b/src/main/java/scala/tools/asm/ClassReader.java @@ -1170,7 +1170,14 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { if (labels[label] == null) { readLabel(label, labels).status |= Label.DEBUG; } - labels[label].line = readUnsignedShort(v + 12); + Label l = labels[label]; + while (l.line > 0) { + if (l.next == null) { + l.next = new Label(); + } + l = l.next; + } + l.line = readUnsignedShort(v + 12); v += 4; } } @@ -1285,9 +1292,15 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { // visits the label and line number for this offset, if any Label l = labels[offset]; if (l != null) { + Label next = l.next; + l.next = null; mv.visitLabel(l); if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { mv.visitLineNumber(l.line, l); + while (next != null) { + mv.visitLineNumber(next.line, l); + next = next.next; + } } } @@ -1828,8 +1841,7 @@ private int readAnnotationValue(int v, final char[] buf, final String name, v += 2; break; case 'B': // pointer to CONSTANT_Byte - av.visit(name, - new Byte((byte) readInt(items[readUnsignedShort(v)]))); + av.visit(name, (byte) readInt(items[readUnsignedShort(v)])); v += 2; break; case 'Z': // pointer to CONSTANT_Boolean @@ -1839,13 +1851,11 @@ private int readAnnotationValue(int v, final char[] buf, final String name, v += 2; break; case 'S': // pointer to CONSTANT_Short - av.visit(name, new Short( - (short) readInt(items[readUnsignedShort(v)]))); + av.visit(name, (short) readInt(items[readUnsignedShort(v)])); v += 2; break; case 'C': // pointer to CONSTANT_Char - av.visit(name, new Character( - (char) readInt(items[readUnsignedShort(v)]))); + av.visit(name, (char) readInt(items[readUnsignedShort(v)])); v += 2; break; case 's': // pointer to CONSTANT_Utf8 @@ -2469,13 +2479,13 @@ public Object readConst(final int item, final char[] buf) { int index = items[item]; switch (b[index - 1]) { case ClassWriter.INT: - return new Integer(readInt(index)); + return readInt(index); case ClassWriter.FLOAT: - return new Float(Float.intBitsToFloat(readInt(index))); + return Float.intBitsToFloat(readInt(index)); case ClassWriter.LONG: - return new Long(readLong(index)); + return readLong(index); case ClassWriter.DOUBLE: - return new Double(Double.longBitsToDouble(readLong(index))); + return Double.longBitsToDouble(readLong(index)); case ClassWriter.CLASS: return Type.getObjectType(readUTF8(index, buf)); case ClassWriter.STR: diff --git a/src/main/java/scala/tools/asm/Item.java b/src/main/java/scala/tools/asm/Item.java index 4693f5a..4cf78bf 100644 --- a/src/main/java/scala/tools/asm/Item.java +++ b/src/main/java/scala/tools/asm/Item.java @@ -201,6 +201,7 @@ void set(final double doubleVal) { * @param strVal3 * third part of the value of this item. */ + @SuppressWarnings("fallthrough") void set(final int type, final String strVal1, final String strVal2, final String strVal3) { this.type = type; diff --git a/src/main/java/scala/tools/asm/Label.java b/src/main/java/scala/tools/asm/Label.java index 22b6798..7c8fd9e 100644 --- a/src/main/java/scala/tools/asm/Label.java +++ b/src/main/java/scala/tools/asm/Label.java @@ -131,7 +131,11 @@ public class Label { int status; /** - * The line number corresponding to this label, if known. + * The line number corresponding to this label, if known. If there are + * several lines, each line is stored in a separate label, all linked via + * their next field (these links are created in ClassReader and removed just + * before visitLabel is called, so that this does not impact the rest of the + * code). */ int line; @@ -239,7 +243,8 @@ public class Label { * The next basic block in the basic block stack. This stack is used in the * main loop of the fix point algorithm used in the second step of the * control flow analysis algorithms. It is also used in - * {@link #visitSubroutine} to avoid using a recursive method. + * {@link #visitSubroutine} to avoid using a recursive method, and in + * ClassReader to temporarily store multiple source lines for a label. * * @see MethodWriter#visitMaxs */ diff --git a/src/main/java/scala/tools/asm/MethodVisitor.java b/src/main/java/scala/tools/asm/MethodVisitor.java index bddc325..fc1e1df 100644 --- a/src/main/java/scala/tools/asm/MethodVisitor.java +++ b/src/main/java/scala/tools/asm/MethodVisitor.java @@ -33,15 +33,16 @@ * A visitor to visit a Java method. The methods of this class must be called in * the following order: ( visitParameter )* [ * visitAnnotationDefault ] ( visitAnnotation | - * visitTypeAnnotation | visitAttribute )* [ - * visitCode ( visitFrame | visitXInsn | - * visitLabel | visitInsnAnnotation | - * visitTryCatchBlock | visitTryCatchBlockAnnotation | - * visitLocalVariable | visitLocalVariableAnnotation | - * visitLineNumber )* visitMaxs ] visitEnd. In - * addition, the visitXInsn and visitLabel methods must - * be called in the sequential order of the bytecode instructions of the visited - * code, visitInsnAnnotation must be called after the annotated + * visitParameterAnnotation visitTypeAnnotation | + * visitAttribute )* [ visitCode ( visitFrame | + * visitXInsn | visitLabel | + * visitInsnAnnotation | visitTryCatchBlock | + * visitTryCatchAnnotation | visitLocalVariable | + * visitLocalVariableAnnotation | visitLineNumber )* + * visitMaxs ] visitEnd. In addition, the + * visitXInsn and visitLabel methods must be called in + * the sequential order of the bytecode instructions of the visited code, + * visitInsnAnnotation must be called after the annotated * instruction, visitTryCatchBlock must be called before the * labels passed as arguments have been visited, * visitTryCatchBlockAnnotation must be called after the diff --git a/src/main/java/scala/tools/asm/MethodWriter.java b/src/main/java/scala/tools/asm/MethodWriter.java index 9c72ead..ee54c4c 100644 --- a/src/main/java/scala/tools/asm/MethodWriter.java +++ b/src/main/java/scala/tools/asm/MethodWriter.java @@ -2717,11 +2717,13 @@ private void resizeInstructions() { l = l.successor; } // Update the offsets in the uninitialized types - for (i = 0; i < cw.typeTable.length; ++i) { - Item item = cw.typeTable[i]; - if (item != null && item.type == ClassWriter.TYPE_UNINIT) { - item.intVal = getNewOffset(allIndexes, allSizes, 0, - item.intVal); + if (cw.typeTable != null) { + for (i = 0; i < cw.typeTable.length; ++i) { + Item item = cw.typeTable[i]; + if (item != null && item.type == ClassWriter.TYPE_UNINIT) { + item.intVal = getNewOffset(allIndexes, allSizes, 0, + item.intVal); + } } } // The stack map frames are not serialized yet, so we don't need diff --git a/src/main/java/scala/tools/asm/TypePath.java b/src/main/java/scala/tools/asm/TypePath.java index d4c6f0d..c5478ef 100644 --- a/src/main/java/scala/tools/asm/TypePath.java +++ b/src/main/java/scala/tools/asm/TypePath.java @@ -152,6 +152,9 @@ public static TypePath fromString(final String typePath) { typeArg = typeArg * 10 + c - '0'; i += 1; } + if (i < n && typePath.charAt(i) == ';') { + i += 1; + } out.put11(TYPE_ARGUMENT, typeArg); } } @@ -164,7 +167,7 @@ public static TypePath fromString(final String typePath) { * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type - * argument index in decimal form. + * argument index in decimal form followed by ';'. */ @Override public String toString() { @@ -182,7 +185,7 @@ public String toString() { result.append('*'); break; case TYPE_ARGUMENT: - result.append(getStepArgument(i)); + result.append(getStepArgument(i)).append(';'); break; default: result.append('_'); diff --git a/src/main/java/scala/tools/asm/signature/SignatureVisitor.java b/src/main/java/scala/tools/asm/signature/SignatureVisitor.java index 1e16bd3..557ff85 100644 --- a/src/main/java/scala/tools/asm/signature/SignatureVisitor.java +++ b/src/main/java/scala/tools/asm/signature/SignatureVisitor.java @@ -39,7 +39,7 @@ *