diff options
Diffstat (limited to 'src/asm')
73 files changed, 7410 insertions, 7417 deletions
diff --git a/src/asm/scala/tools/asm/AnnotationVisitor.java b/src/asm/scala/tools/asm/AnnotationVisitor.java index b96e730a73..c806ca71e8 100644 --- a/src/asm/scala/tools/asm/AnnotationVisitor.java +++ b/src/asm/scala/tools/asm/AnnotationVisitor.java @@ -54,8 +54,9 @@ public abstract class AnnotationVisitor { /** * Constructs a new {@link AnnotationVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. */ public AnnotationVisitor(final int api) { this(api, null); @@ -64,15 +65,17 @@ public abstract class AnnotationVisitor { /** * Constructs a new {@link AnnotationVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param av the annotation visitor to which this visitor must delegate - * method calls. May be null. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param av + * the annotation visitor to which this visitor must delegate + * method calls. May be null. */ public AnnotationVisitor(final int api, final AnnotationVisitor av) { - /*if (api != Opcodes.ASM4) { + if (api != Opcodes.ASM4) { throw new IllegalArgumentException(); - }*/ + } this.api = api; this.av = av; } @@ -80,14 +83,17 @@ public abstract class AnnotationVisitor { /** * Visits a primitive value of the annotation. * - * @param name the value name. - * @param value the actual value, whose type must be {@link Byte}, - * {@link Boolean}, {@link Character}, {@link Short}, {@link Integer} - * , {@link Long}, {@link Float}, {@link Double}, {@link String} or - * {@link Type} or OBJECT or ARRAY sort. This value can also be an - * array of byte, boolean, short, char, int, long, float or double - * values (this is equivalent to using {@link #visitArray visitArray} - * and visiting each array element in turn, but is more convenient). + * @param name + * the value name. + * @param value + * the actual value, whose type must be {@link Byte}, + * {@link Boolean}, {@link Character}, {@link Short}, + * {@link Integer} , {@link Long}, {@link Float}, {@link Double}, + * {@link String} or {@link Type} or OBJECT or ARRAY sort. This + * value can also be an array of byte, boolean, short, char, int, + * long, float or double values (this is equivalent to using + * {@link #visitArray visitArray} and visiting each array element + * in turn, but is more convenient). */ public void visit(String name, Object value) { if (av != null) { @@ -98,9 +104,12 @@ public abstract class AnnotationVisitor { /** * Visits an enumeration value of the annotation. * - * @param name the value name. - * @param desc the class descriptor of the enumeration class. - * @param value the actual enumeration value. + * @param name + * the value name. + * @param desc + * the class descriptor of the enumeration class. + * @param value + * the actual enumeration value. */ public void visitEnum(String name, String desc, String value) { if (av != null) { @@ -111,12 +120,14 @@ public abstract class AnnotationVisitor { /** * Visits a nested annotation value of the annotation. * - * @param name the value name. - * @param desc the class descriptor of the nested annotation class. + * @param name + * the value name. + * @param desc + * the class descriptor of the nested annotation class. * @return a visitor to visit the actual nested annotation value, or - * <tt>null</tt> if this visitor is not interested in visiting - * this nested annotation. <i>The nested annotation value must be - * fully visited before calling other methods on this annotation + * <tt>null</tt> if this visitor is not interested in visiting this + * nested annotation. <i>The nested annotation value must be fully + * visited before calling other methods on this annotation * visitor</i>. */ public AnnotationVisitor visitAnnotation(String name, String desc) { @@ -132,10 +143,11 @@ public abstract class AnnotationVisitor { * can be passed as value to {@link #visit visit}. This is what * {@link ClassReader} does. * - * @param name the value name. + * @param name + * the value name. * @return a visitor to visit the actual array value elements, or - * <tt>null</tt> if this visitor is not interested in visiting - * these values. The 'name' parameters passed to the methods of this + * <tt>null</tt> if this visitor is not interested in visiting these + * values. The 'name' parameters passed to the methods of this * visitor are ignored. <i>All the array values must be visited * before calling other methods on this annotation visitor</i>. */ diff --git a/src/asm/scala/tools/asm/AnnotationWriter.java b/src/asm/scala/tools/asm/AnnotationWriter.java index e530780249..8eb5b2ef48 100644 --- a/src/asm/scala/tools/asm/AnnotationWriter.java +++ b/src/asm/scala/tools/asm/AnnotationWriter.java @@ -90,20 +90,20 @@ final class AnnotationWriter extends AnnotationVisitor { /** * Constructs a new {@link AnnotationWriter}. * - * @param cw the class writer to which this annotation must be added. - * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise. - * @param bv where the annotation values must be stored. - * @param parent where the number of annotation values must be stored. - * @param offset where in <tt>parent</tt> the number of annotation values must - * be stored. + * @param cw + * the class writer to which this annotation must be added. + * @param named + * <tt>true<tt> if values are named, <tt>false</tt> otherwise. + * @param bv + * where the annotation values must be stored. + * @param parent + * where the number of annotation values must be stored. + * @param offset + * where in <tt>parent</tt> the number of annotation values must + * be stored. */ - AnnotationWriter( - final ClassWriter cw, - final boolean named, - final ByteVector bv, - final ByteVector parent, - final int offset) - { + AnnotationWriter(final ClassWriter cw, final boolean named, + final ByteVector bv, final ByteVector parent, final int offset) { super(Opcodes.ASM4); this.cw = cw; this.named = named; @@ -190,11 +190,8 @@ final class AnnotationWriter extends AnnotationVisitor { } @Override - public void visitEnum( - final String name, - final String desc, - final String value) - { + public void visitEnum(final String name, final String desc, + final String value) { ++size; if (named) { bv.putShort(cw.newUTF8(name)); @@ -203,10 +200,8 @@ final class AnnotationWriter extends AnnotationVisitor { } @Override - public AnnotationVisitor visitAnnotation( - final String name, - final String desc) - { + public AnnotationVisitor visitAnnotation(final String name, + final String desc) { ++size; if (named) { bv.putShort(cw.newUTF8(name)); @@ -259,7 +254,8 @@ final class AnnotationWriter extends AnnotationVisitor { * Puts the annotations of this annotation writer list into the given byte * vector. * - * @param out where the annotations must be put. + * @param out + * where the annotations must be put. */ void put(final ByteVector out) { int n = 0; @@ -286,15 +282,15 @@ final class AnnotationWriter extends AnnotationVisitor { /** * Puts the given annotation lists into the given byte vector. * - * @param panns an array of annotation writer lists. - * @param off index of the first annotation to be written. - * @param out where the annotations must be put. + * @param panns + * an array of annotation writer lists. + * @param off + * index of the first annotation to be written. + * @param out + * where the annotations must be put. */ - static void put( - final AnnotationWriter[] panns, - final int off, - final ByteVector out) - { + static void put(final AnnotationWriter[] panns, final int off, + final ByteVector out) { int size = 1 + 2 * (panns.length - off); for (int i = off; i < panns.length; ++i) { size += panns[i] == null ? 0 : panns[i].getSize(); diff --git a/src/asm/scala/tools/asm/Attribute.java b/src/asm/scala/tools/asm/Attribute.java index 408f21ce1e..ac40a758a2 100644 --- a/src/asm/scala/tools/asm/Attribute.java +++ b/src/asm/scala/tools/asm/Attribute.java @@ -55,7 +55,8 @@ public class Attribute { /** * Constructs a new empty attribute. * - * @param type the type of the attribute. + * @param type + * the type of the attribute. */ protected Attribute(final String type) { this.type = type; @@ -91,39 +92,39 @@ public class Attribute { } /** - * Reads a {@link #type type} attribute. This method must return a <i>new</i> - * {@link Attribute} object, of type {@link #type type}, corresponding to - * the <tt>len</tt> bytes starting at the given offset, in the given class - * reader. + * Reads a {@link #type type} attribute. This method must return a + * <i>new</i> {@link Attribute} object, of type {@link #type type}, + * corresponding to the <tt>len</tt> bytes starting at the given offset, in + * the given class reader. * - * @param cr the class that contains the attribute to be read. - * @param off index of the first byte of the attribute's content in {@link - * ClassReader#b cr.b}. The 6 attribute header bytes, containing the - * type and the length of the attribute, are not taken into account - * here. - * @param len the length of the attribute's content. - * @param buf buffer to be used to call - * {@link ClassReader#readUTF8 readUTF8}, - * {@link ClassReader#readClass(int,char[]) readClass} or - * {@link ClassReader#readConst readConst}. - * @param codeOff index of the first byte of code's attribute content in - * {@link ClassReader#b cr.b}, or -1 if the attribute to be read is - * not a code attribute. The 6 attribute header bytes, containing the - * type and the length of the attribute, are not taken into account - * here. - * @param labels the labels of the method's code, or <tt>null</tt> if the - * attribute to be read is not a code attribute. + * @param cr + * the class that contains the attribute to be read. + * @param off + * index of the first byte of the attribute's content in + * {@link ClassReader#b cr.b}. The 6 attribute header bytes, + * containing the type and the length of the attribute, are not + * taken into account here. + * @param len + * the length of the attribute's content. + * @param buf + * buffer to be used to call {@link ClassReader#readUTF8 + * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass} + * or {@link ClassReader#readConst readConst}. + * @param codeOff + * index of the first byte of code's attribute content in + * {@link ClassReader#b cr.b}, or -1 if the attribute to be read + * is not a code attribute. The 6 attribute header bytes, + * containing the type and the length of the attribute, are not + * taken into account here. + * @param labels + * the labels of the method's code, or <tt>null</tt> if the + * attribute to be read is not a code attribute. * @return a <i>new</i> {@link Attribute} object corresponding to the given * bytes. */ - protected Attribute read( - final ClassReader cr, - final int off, - final int len, - final char[] buf, - final int codeOff, - final Label[] labels) - { + protected Attribute read(final ClassReader cr, final int off, + final int len, final char[] buf, final int codeOff, + final Label[] labels) { Attribute attr = new Attribute(type); attr.value = new byte[len]; System.arraycopy(cr.b, off, attr.value, 0, len); @@ -133,30 +134,30 @@ public class Attribute { /** * Returns the byte array form of this attribute. * - * @param cw the class to which this attribute must be added. This parameter - * can be used to add to the constant pool of this class the items - * that corresponds to this attribute. - * @param code the bytecode of the method corresponding to this code - * attribute, or <tt>null</tt> if this attribute is not a code - * attributes. - * @param len the length of the bytecode of the method corresponding to this - * code attribute, or <tt>null</tt> if this attribute is not a code - * attribute. - * @param maxStack the maximum stack size of the method corresponding to - * this code attribute, or -1 if this attribute is not a code - * attribute. - * @param maxLocals the maximum number of local variables of the method - * corresponding to this code attribute, or -1 if this attribute is - * not a code attribute. + * @param cw + * the class to which this attribute must be added. This + * parameter can be used to add to the constant pool of this + * class the items that corresponds to this attribute. + * @param code + * the bytecode of the method corresponding to this code + * attribute, or <tt>null</tt> if this attribute is not a code + * attributes. + * @param len + * the length of the bytecode of the method corresponding to this + * code attribute, or <tt>null</tt> if this attribute is not a + * code attribute. + * @param maxStack + * the maximum stack size of the method corresponding to this + * code attribute, or -1 if this attribute is not a code + * attribute. + * @param maxLocals + * the maximum number of local variables of the method + * corresponding to this code attribute, or -1 if this attribute + * is not a code attribute. * @return the byte array form of this attribute. */ - protected ByteVector write( - final ClassWriter cw, - final byte[] code, - final int len, - final int maxStack, - final int maxLocals) - { + protected ByteVector write(final ClassWriter cw, final byte[] code, + final int len, final int maxStack, final int maxLocals) { ByteVector v = new ByteVector(); v.data = value; v.length = value.length; @@ -181,30 +182,30 @@ public class Attribute { /** * Returns the size of all the attributes in this attribute list. * - * @param cw the class writer to be used to convert the attributes into byte - * arrays, with the {@link #write write} method. - * @param code the bytecode of the method corresponding to these code - * attributes, or <tt>null</tt> if these attributes are not code - * attributes. - * @param len the length of the bytecode of the method corresponding to - * these code attributes, or <tt>null</tt> if these attributes are - * not code attributes. - * @param maxStack the maximum stack size of the method corresponding to - * these code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these attributes - * are not code attributes. + * @param cw + * the class writer to be used to convert the attributes into + * byte arrays, with the {@link #write write} method. + * @param code + * the bytecode of the method corresponding to these code + * attributes, or <tt>null</tt> if these attributes are not code + * attributes. + * @param len + * the length of the bytecode of the method corresponding to + * these code attributes, or <tt>null</tt> if these attributes + * are not code attributes. + * @param maxStack + * the maximum stack size of the method corresponding to these + * code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals + * the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these + * attributes are not code attributes. * @return the size of all the attributes in this attribute list. This size * includes the size of the attribute headers. */ - final int getSize( - final ClassWriter cw, - final byte[] code, - final int len, - final int maxStack, - final int maxLocals) - { + final int getSize(final ClassWriter cw, final byte[] code, final int len, + final int maxStack, final int maxLocals) { Attribute attr = this; int size = 0; while (attr != null) { @@ -219,30 +220,30 @@ public class Attribute { * Writes all the attributes of this attribute list in the given byte * vector. * - * @param cw the class writer to be used to convert the attributes into byte - * arrays, with the {@link #write write} method. - * @param code the bytecode of the method corresponding to these code - * attributes, or <tt>null</tt> if these attributes are not code - * attributes. - * @param len the length of the bytecode of the method corresponding to - * these code attributes, or <tt>null</tt> if these attributes are - * not code attributes. - * @param maxStack the maximum stack size of the method corresponding to - * these code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these attributes - * are not code attributes. - * @param out where the attributes must be written. + * @param cw + * the class writer to be used to convert the attributes into + * byte arrays, with the {@link #write write} method. + * @param code + * the bytecode of the method corresponding to these code + * attributes, or <tt>null</tt> if these attributes are not code + * attributes. + * @param len + * the length of the bytecode of the method corresponding to + * these code attributes, or <tt>null</tt> if these attributes + * are not code attributes. + * @param maxStack + * the maximum stack size of the method corresponding to these + * code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals + * the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these + * attributes are not code attributes. + * @param out + * where the attributes must be written. */ - final void put( - final ClassWriter cw, - final byte[] code, - final int len, - final int maxStack, - final int maxLocals, - final ByteVector out) - { + final void put(final ClassWriter cw, final byte[] code, final int len, + final int maxStack, final int maxLocals, final ByteVector out) { Attribute attr = this; while (attr != null) { ByteVector b = attr.write(cw, code, len, maxStack, maxLocals); diff --git a/src/asm/scala/tools/asm/ByteVector.java b/src/asm/scala/tools/asm/ByteVector.java index 5081f0184b..2bc63eb384 100644 --- a/src/asm/scala/tools/asm/ByteVector.java +++ b/src/asm/scala/tools/asm/ByteVector.java @@ -59,7 +59,8 @@ public class ByteVector { * Constructs a new {@link ByteVector ByteVector} with the given initial * size. * - * @param initialSize the initial size of the byte vector to be constructed. + * @param initialSize + * the initial size of the byte vector to be constructed. */ public ByteVector(final int initialSize) { data = new byte[initialSize]; @@ -69,7 +70,8 @@ public class ByteVector { * Puts a byte into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param b a byte. + * @param b + * a byte. * @return this byte vector. */ public ByteVector putByte(final int b) { @@ -86,8 +88,10 @@ public class ByteVector { * Puts two bytes into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param b1 a byte. - * @param b2 another byte. + * @param b1 + * a byte. + * @param b2 + * another byte. * @return this byte vector. */ ByteVector put11(final int b1, final int b2) { @@ -106,7 +110,8 @@ public class ByteVector { * Puts a short into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param s a short. + * @param s + * a short. * @return this byte vector. */ public ByteVector putShort(final int s) { @@ -125,8 +130,10 @@ public class ByteVector { * Puts a byte and a short into this byte vector. The byte vector is * automatically enlarged if necessary. * - * @param b a byte. - * @param s a short. + * @param b + * a byte. + * @param s + * a short. * @return this byte vector. */ ByteVector put12(final int b, final int s) { @@ -146,7 +153,8 @@ public class ByteVector { * Puts an int into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param i an int. + * @param i + * an int. * @return this byte vector. */ public ByteVector putInt(final int i) { @@ -167,7 +175,8 @@ public class ByteVector { * Puts a long into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param l a long. + * @param l + * a long. * @return this byte vector. */ public ByteVector putLong(final long l) { @@ -194,7 +203,8 @@ public class ByteVector { * Puts an UTF8 string into this byte vector. The byte vector is * automatically enlarged if necessary. * - * @param s a String. + * @param s + * a String. * @return this byte vector. */ public ByteVector putUTF8(final String s) { @@ -259,14 +269,16 @@ public class ByteVector { * Puts an array of bytes into this byte vector. The byte vector is * automatically enlarged if necessary. * - * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt> - * null bytes into this byte vector. - * @param off index of the fist byte of b that must be copied. - * @param len number of bytes of b that must be copied. + * @param b + * an array of bytes. May be <tt>null</tt> to put <tt>len</tt> + * null bytes into this byte vector. + * @param off + * index of the fist byte of b that must be copied. + * @param len + * number of bytes of b that must be copied. * @return this byte vector. */ - public ByteVector putByteArray(final byte[] b, final int off, final int len) - { + public ByteVector putByteArray(final byte[] b, final int off, final int len) { if (length + len > data.length) { enlarge(len); } @@ -280,8 +292,9 @@ public class ByteVector { /** * Enlarge this byte vector so that it can receive n more bytes. * - * @param size number of additional bytes that this byte vector should be - * able to receive. + * @param size + * number of additional bytes that this byte vector should be + * able to receive. */ private void enlarge(final int size) { int length1 = 2 * data.length; diff --git a/src/asm/scala/tools/asm/ClassReader.java b/src/asm/scala/tools/asm/ClassReader.java index f3287d41ae..cc655c1b62 100644 --- a/src/asm/scala/tools/asm/ClassReader.java +++ b/src/asm/scala/tools/asm/ClassReader.java @@ -112,9 +112,8 @@ public class ClassReader { public final byte[] b; /** - * The start index of each constant pool item in {@link #b b}, plus one. - * The one byte offset skips the constant pool item tag that indicates its - * type. + * The start index of each constant pool item in {@link #b b}, plus one. The + * one byte offset skips the constant pool item tag that indicates its type. */ private final int[] items; @@ -147,7 +146,8 @@ public class ClassReader { /** * Constructs a new {@link ClassReader} object. * - * @param b the bytecode of the class to be read. + * @param b + * the bytecode of the class to be read. */ public ClassReader(final byte[] b) { this(b, 0, b.length); @@ -156,14 +156,17 @@ public class ClassReader { /** * Constructs a new {@link ClassReader} object. * - * @param b the bytecode of the class to be read. - * @param off the start offset of the class data. - * @param len the length of the class data. + * @param b + * the bytecode of the class to be read. + * @param off + * the start offset of the class data. + * @param len + * the length of the class data. */ public ClassReader(final byte[] b, final int off, final int len) { this.b = b; // checks the class version - if (readShort(6) > Opcodes.V1_7) { + if (readShort(off + 6) > Opcodes.V1_7) { throw new IllegalArgumentException(); } // parses the constant pool @@ -176,35 +179,35 @@ public class ClassReader { items[i] = index + 1; int size; switch (b[index]) { - case ClassWriter.FIELD: - case ClassWriter.METH: - case ClassWriter.IMETH: - case ClassWriter.INT: - case ClassWriter.FLOAT: - case ClassWriter.NAME_TYPE: - case ClassWriter.INDY: - size = 5; - break; - case ClassWriter.LONG: - case ClassWriter.DOUBLE: - size = 9; - ++i; - break; - case ClassWriter.UTF8: - size = 3 + readUnsignedShort(index + 1); - if (size > max) { - max = size; - } - break; - case ClassWriter.HANDLE: - size = 4; - break; - // case ClassWriter.CLASS: - // case ClassWriter.STR: - // case ClassWriter.MTYPE - default: - size = 3; - break; + case ClassWriter.FIELD: + case ClassWriter.METH: + case ClassWriter.IMETH: + case ClassWriter.INT: + case ClassWriter.FLOAT: + case ClassWriter.NAME_TYPE: + case ClassWriter.INDY: + size = 5; + break; + case ClassWriter.LONG: + case ClassWriter.DOUBLE: + size = 9; + ++i; + break; + case ClassWriter.UTF8: + size = 3 + readUnsignedShort(index + 1); + if (size > max) { + max = size; + } + break; + case ClassWriter.HANDLE: + size = 4; + break; + // case ClassWriter.CLASS: + // case ClassWriter.STR: + // case ClassWriter.MTYPE + default: + size = 3; + break; } index += size; } @@ -249,8 +252,7 @@ public class ClassReader { * @see ClassVisitor#visit(int, int, String, String, String, String[]) */ public String getSuperName() { - int n = items[readUnsignedShort(header + 4)]; - return n == 0 ? null : readUTF8(n, new char[maxStringLength]); + return readClass(header + 4, new char[maxStringLength]); } /** @@ -280,7 +282,8 @@ public class ClassReader { * Copies the constant pool data into the given {@link ClassWriter}. Should * be called before the {@link #accept(ClassVisitor,int)} method. * - * @param classWriter the {@link ClassWriter} to copy constant pool into. + * @param classWriter + * the {@link ClassWriter} to copy constant pool into. */ void copyPool(final ClassWriter classWriter) { char[] buf = new char[maxStringLength]; @@ -292,82 +295,63 @@ public class ClassReader { Item item = new Item(i); int nameType; switch (tag) { - case ClassWriter.FIELD: - case ClassWriter.METH: - case ClassWriter.IMETH: - nameType = items[readUnsignedShort(index + 2)]; - item.set(tag, - readClass(index, buf), - readUTF8(nameType, buf), - readUTF8(nameType + 2, buf)); - break; - - case ClassWriter.INT: - item.set(readInt(index)); - break; - - case ClassWriter.FLOAT: - item.set(Float.intBitsToFloat(readInt(index))); - break; - - case ClassWriter.NAME_TYPE: - item.set(tag, - readUTF8(index, buf), - readUTF8(index + 2, buf), - null); - break; - - case ClassWriter.LONG: - item.set(readLong(index)); - ++i; - break; - - case ClassWriter.DOUBLE: - item.set(Double.longBitsToDouble(readLong(index))); - ++i; - break; - - case ClassWriter.UTF8: { - String s = strings[i]; - if (s == null) { - index = items[i]; - s = strings[i] = readUTF(index + 2, - readUnsignedShort(index), - buf); - } - item.set(tag, s, null, null); + case ClassWriter.FIELD: + case ClassWriter.METH: + case ClassWriter.IMETH: + nameType = items[readUnsignedShort(index + 2)]; + item.set(tag, readClass(index, buf), readUTF8(nameType, buf), + readUTF8(nameType + 2, buf)); + break; + case ClassWriter.INT: + item.set(readInt(index)); + break; + case ClassWriter.FLOAT: + item.set(Float.intBitsToFloat(readInt(index))); + break; + case ClassWriter.NAME_TYPE: + item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf), + null); + break; + case ClassWriter.LONG: + item.set(readLong(index)); + ++i; + break; + case ClassWriter.DOUBLE: + item.set(Double.longBitsToDouble(readLong(index))); + ++i; + break; + case ClassWriter.UTF8: { + String s = strings[i]; + if (s == null) { + index = items[i]; + s = strings[i] = readUTF(index + 2, + readUnsignedShort(index), buf); } - break; - - case ClassWriter.HANDLE: { - int fieldOrMethodRef = items[readUnsignedShort(index + 1)]; - nameType = items[readUnsignedShort(fieldOrMethodRef + 2)]; - item.set(ClassWriter.HANDLE_BASE + readByte(index), - readClass(fieldOrMethodRef, buf), - readUTF8(nameType, buf), - readUTF8(nameType + 2, buf)); - + item.set(tag, s, null, null); + break; + } + case ClassWriter.HANDLE: { + int fieldOrMethodRef = items[readUnsignedShort(index + 1)]; + nameType = items[readUnsignedShort(fieldOrMethodRef + 2)]; + item.set(ClassWriter.HANDLE_BASE + readByte(index), + readClass(fieldOrMethodRef, buf), + readUTF8(nameType, buf), readUTF8(nameType + 2, buf)); + break; + } + case ClassWriter.INDY: + if (classWriter.bootstrapMethods == null) { + copyBootstrapMethods(classWriter, items2, buf); } - break; - - - case ClassWriter.INDY: - if (classWriter.bootstrapMethods == null) { - copyBootstrapMethods(classWriter, items2, buf); - } - nameType = items[readUnsignedShort(index + 2)]; - item.set(readUTF8(nameType, buf), - readUTF8(nameType + 2, buf), - readUnsignedShort(index)); - break; - - - // case ClassWriter.STR: - // case ClassWriter.CLASS: - // case ClassWriter.MTYPE - default: - item.set(tag, readUTF8(index, buf), null, null); - break; + nameType = items[readUnsignedShort(index + 2)]; + item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf), + readUnsignedShort(index)); + break; + // case ClassWriter.STR: + // case ClassWriter.CLASS: + // case ClassWriter.MTYPE + default: + item.set(tag, readUTF8(index, buf), null, null); + break; } int index2 = item.hashCode % items2.length; @@ -382,77 +366,59 @@ public class ClassReader { classWriter.index = ll; } - private void copyBootstrapMethods(ClassWriter classWriter, Item[] items2, char[] buf) { - int i, j, k, u, v; - - // skip class header - v = header; - v += 8 + (readUnsignedShort(v + 6) << 1); - - // skips fields and methods - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - j = readUnsignedShort(v + 6); - v += 8; - for (; j > 0; --j) { - v += 6 + readInt(v + 2); + /** + * Copies the bootstrap method data into the given {@link ClassWriter}. + * Should be called before the {@link #accept(ClassVisitor,int)} method. + * + * @param classWriter + * the {@link ClassWriter} to copy bootstrap methods into. + */ + private void copyBootstrapMethods(final ClassWriter classWriter, + final Item[] items, final char[] c) { + // finds the "BootstrapMethods" attribute + int u = getAttributes(); + boolean found = false; + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); + if ("BootstrapMethods".equals(attrName)) { + found = true; + break; } + u += 6 + readInt(u + 4); } - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - j = readUnsignedShort(v + 6); - v += 8; - for (; j > 0; --j) { - v += 6 + readInt(v + 2); - } + if (!found) { + return; } - - // read class attributes - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - String attrName = readUTF8(v, buf); - int size = readInt(v + 2); - if ("BootstrapMethods".equals(attrName)) { - int boostrapMethodCount = readUnsignedShort(v + 6); - int x = v + 8; - for (j = 0; j < boostrapMethodCount; j++) { - int hashCode = readConst(readUnsignedShort(x), buf).hashCode(); - k = readUnsignedShort(x + 2); - u = x + 4; - for(; k > 0; --k) { - hashCode ^= readConst(readUnsignedShort(u), buf).hashCode(); - u += 2; - } - Item item = new Item(j); - item.set(x - v - 8, hashCode & 0x7FFFFFFF); - - int index2 = item.hashCode % items2.length; - item.next = items2[index2]; - items2[index2] = item; - - x = u; - } - - classWriter.bootstrapMethodsCount = boostrapMethodCount; - ByteVector bootstrapMethods = new ByteVector(size + 62); - bootstrapMethods.putByteArray(b, v + 8, size - 2); - classWriter.bootstrapMethods = bootstrapMethods; - return; + // copies the bootstrap methods in the class writer + int boostrapMethodCount = readUnsignedShort(u + 8); + for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) { + int position = v - u - 10; + int hashCode = readConst(readUnsignedShort(v), c).hashCode(); + for (int k = readUnsignedShort(v + 2); k > 0; --k) { + hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode(); + v += 2; } - v += 6 + size; + v += 4; + Item item = new Item(j); + item.set(position, hashCode & 0x7FFFFFFF); + int index = item.hashCode % items.length; + item.next = items[index]; + items[index] = item; } - - // we are in trouble !!! + int attrSize = readInt(u + 4); + ByteVector bootstrapMethods = new ByteVector(attrSize + 62); + bootstrapMethods.putByteArray(b, u + 10, attrSize - 2); + classWriter.bootstrapMethodsCount = boostrapMethodCount; + classWriter.bootstrapMethods = bootstrapMethods; } /** * Constructs a new {@link ClassReader} object. * - * @param is an input stream from which to read the class. - * @throws IOException if a problem occurs during reading. + * @param is + * an input stream from which to read the class. + * @throws IOException + * if a problem occurs during reading. */ public ClassReader(final InputStream is) throws IOException { this(readClass(is, false)); @@ -461,25 +427,30 @@ public class ClassReader { /** * Constructs a new {@link ClassReader} object. * - * @param name the binary qualified name of the class to be read. - * @throws IOException if an exception occurs during reading. + * @param name + * the binary qualified name of the class to be read. + * @throws IOException + * if an exception occurs during reading. */ public ClassReader(final String name) throws IOException { - this(readClass(ClassLoader.getSystemResourceAsStream(name.replace('.', '/') - + ".class"), true)); + this(readClass( + ClassLoader.getSystemResourceAsStream(name.replace('.', '/') + + ".class"), true)); } /** * Reads the bytecode of a class. * - * @param is an input stream from which to read the class. - * @param close true to close the input stream after reading. + * @param is + * an input stream from which to read the class. + * @param close + * true to close the input stream after reading. * @return the bytecode read from the given input stream. - * @throws IOException if a problem occurs during reading. + * @throws IOException + * if a problem occurs during reading. */ private static byte[] readClass(final InputStream is, boolean close) - throws IOException - { + throws IOException { if (is == null) { throw new IOException("Class not found"); } @@ -520,14 +491,16 @@ public class ClassReader { // ------------------------------------------------------------------------ /** - * Makes the given visitor visit the Java class of this {@link ClassReader}. - * This class is the one specified in the constructor (see + * Makes the given visitor visit the Java class of this {@link ClassReader} + * . This class is the one specified in the constructor (see * {@link #ClassReader(byte[]) ClassReader}). * - * @param classVisitor the visitor that must visit this class. - * @param flags option flags that can be used to modify the default behavior - * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}, - * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. + * @param classVisitor + * the visitor that must visit this class. + * @param flags + * option flags that can be used to modify the default behavior + * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} + * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. */ public void accept(final ClassVisitor classVisitor, final int flags) { accept(classVisitor, new Attribute[0], flags); @@ -538,1117 +511,923 @@ public class ClassReader { * This class is the one specified in the constructor (see * {@link #ClassReader(byte[]) ClassReader}). * - * @param classVisitor the visitor that must visit this class. - * @param attrs prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to the - * type of one the prototypes will not be parsed: its byte array - * value will be passed unchanged to the ClassWriter. <i>This may - * corrupt it if this value contains references to the constant pool, - * or has syntactic or semantic links with a class element that has - * been transformed by a class adapter between the reader and the - * writer</i>. - * @param flags option flags that can be used to modify the default behavior - * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}, - * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. + * @param classVisitor + * the visitor that must visit this class. + * @param attrs + * prototypes of the attributes that must be parsed during the + * visit of the class. Any attribute whose type is not equal to + * the type of one the prototypes will not be parsed: its byte + * array value will be passed unchanged to the ClassWriter. + * <i>This may corrupt it if this value contains references to + * the constant pool, or has syntactic or semantic links with a + * class element that has been transformed by a class adapter + * between the reader and the writer</i>. + * @param flags + * option flags that can be used to modify the default behavior + * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} + * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. */ - public void accept( - final ClassVisitor classVisitor, - final Attribute[] attrs, - final int flags) - { - byte[] b = this.b; // the bytecode array + public void accept(final ClassVisitor classVisitor, + final Attribute[] attrs, final int flags) { + int u = header; // current offset in the class file char[] c = new char[maxStringLength]; // buffer used to read strings - int i, j, k; // loop variables - int u, v, w; // indexes in b - Attribute attr; - - int access; - String name; - String desc; - String attrName; - String signature; - int anns = 0; - int ianns = 0; - Attribute cattrs = null; - - // visits the header - u = header; - access = readUnsignedShort(u); - name = readClass(u + 2, c); - v = items[readUnsignedShort(u + 4)]; - String superClassName = v == 0 ? null : readUTF8(v, c); - String[] implementedItfs = new String[readUnsignedShort(u + 6)]; - w = 0; + + Context context = new Context(); + context.attrs = attrs; + context.flags = flags; + context.buffer = c; + + // reads the class declaration + int access = readUnsignedShort(u); + String name = readClass(u + 2, c); + String superClass = readClass(u + 4, c); + String[] interfaces = new String[readUnsignedShort(u + 6)]; u += 8; - for (i = 0; i < implementedItfs.length; ++i) { - implementedItfs[i] = readClass(u, c); + for (int i = 0; i < interfaces.length; ++i) { + interfaces[i] = readClass(u, c); u += 2; } - boolean skipCode = (flags & SKIP_CODE) != 0; - boolean skipDebug = (flags & SKIP_DEBUG) != 0; - boolean unzip = (flags & EXPAND_FRAMES) != 0; - - // skips fields and methods - v = u; - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - j = readUnsignedShort(v + 6); - v += 8; - for (; j > 0; --j) { - v += 6 + readInt(v + 2); - } - } - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - j = readUnsignedShort(v + 6); - v += 8; - for (; j > 0; --j) { - v += 6 + readInt(v + 2); - } - } - // reads the class's attributes - signature = null; + // reads the class attributes + String signature = null; String sourceFile = null; String sourceDebug = null; String enclosingOwner = null; String enclosingName = null; String enclosingDesc = null; - int[] bootstrapMethods = null; // start indexed of the bsms + int anns = 0; + int ianns = 0; + int innerClasses = 0; + Attribute attributes = null; - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - attrName = readUTF8(v, c); + u = getAttributes(); + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); // tests are sorted in decreasing frequency order // (based on frequencies observed on typical classes) if ("SourceFile".equals(attrName)) { - sourceFile = readUTF8(v + 6, c); + sourceFile = readUTF8(u + 8, c); } else if ("InnerClasses".equals(attrName)) { - w = v + 6; + innerClasses = u + 8; } else if ("EnclosingMethod".equals(attrName)) { - enclosingOwner = readClass(v + 6, c); - int item = readUnsignedShort(v + 8); + enclosingOwner = readClass(u + 8, c); + int item = readUnsignedShort(u + 10); if (item != 0) { enclosingName = readUTF8(items[item], c); enclosingDesc = readUTF8(items[item] + 2, c); } } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(v + 6, c); - } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = v + 6; + signature = readUTF8(u + 8, c); + } else if (ANNOTATIONS + && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = u + 8; } else if ("Deprecated".equals(attrName)) { access |= Opcodes.ACC_DEPRECATED; } else if ("Synthetic".equals(attrName)) { - access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; + access |= Opcodes.ACC_SYNTHETIC + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; } else if ("SourceDebugExtension".equals(attrName)) { - int len = readInt(v + 2); - sourceDebug = readUTF(v + 6, len, new char[len]); - } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = v + 6; + int len = readInt(u + 4); + sourceDebug = readUTF(u + 8, len, new char[len]); + } else if (ANNOTATIONS + && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u + 8; } else if ("BootstrapMethods".equals(attrName)) { - int boostrapMethodCount = readUnsignedShort(v + 6); - bootstrapMethods = new int[boostrapMethodCount]; - int x = v + 8; - for (j = 0; j < boostrapMethodCount; j++) { - bootstrapMethods[j] = x; - x += 2 + readUnsignedShort(x + 2) << 1; + int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; + for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { + bootstrapMethods[j] = v; + v += 2 + readUnsignedShort(v + 2) << 1; } + context.bootstrapMethods = bootstrapMethods; } else { - attr = readAttribute(attrs, - attrName, - v + 6, - readInt(v + 2), - c, - -1, - null); + Attribute attr = readAttribute(attrs, attrName, u + 8, + readInt(u + 4), c, -1, null); if (attr != null) { - attr.next = cattrs; - cattrs = attr; + attr.next = attributes; + attributes = attr; } } - v += 6 + readInt(v + 2); + u += 6 + readInt(u + 4); } - // calls the visit method - classVisitor.visit(readInt(4), - access, - name, - signature, - superClassName, - implementedItfs); - - // calls the visitSource method - if (!skipDebug && (sourceFile != null || sourceDebug != null)) { + + // visits the class declaration + classVisitor.visit(readInt(items[1] - 7), access, name, signature, + superClass, interfaces); + + // visits the source and debug info + if ((flags & SKIP_DEBUG) == 0 + && (sourceFile != null || sourceDebug != null)) { classVisitor.visitSource(sourceFile, sourceDebug); } - // calls the visitOuterClass method + // visits the outer class if (enclosingOwner != null) { - classVisitor.visitOuterClass(enclosingOwner, - enclosingName, + classVisitor.visitOuterClass(enclosingOwner, enclosingName, enclosingDesc); } // visits the class annotations - if (ANNOTATIONS) { - for (i = 1; i >= 0; --i) { - v = i == 0 ? ianns : anns; - if (v != 0) { - j = readUnsignedShort(v); - v += 2; - for (; j > 0; --j) { - v = readAnnotationValues(v + 2, - c, - true, - classVisitor.visitAnnotation(readUTF8(v, c), i != 0)); - } - } + if (ANNOTATIONS && anns != 0) { + for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + classVisitor.visitAnnotation(readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && ianns != 0) { + for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + classVisitor.visitAnnotation(readUTF8(v, c), false)); } } - // visits the class attributes - while (cattrs != null) { - attr = cattrs.next; - cattrs.next = null; - classVisitor.visitAttribute(cattrs); - cattrs = attr; + // visits the attributes + while (attributes != null) { + Attribute attr = attributes.next; + attributes.next = null; + classVisitor.visitAttribute(attributes); + attributes = attr; } - // calls the visitInnerClass method - if (w != 0) { - i = readUnsignedShort(w); - w += 2; - for (; i > 0; --i) { - classVisitor.visitInnerClass(readUnsignedShort(w) == 0 - ? null - : readClass(w, c), readUnsignedShort(w + 2) == 0 - ? null - : readClass(w + 2, c), readUnsignedShort(w + 4) == 0 - ? null - : readUTF8(w + 4, c), readUnsignedShort(w + 6)); - w += 8; + // visits the inner classes + if (innerClasses != 0) { + int v = innerClasses + 2; + for (int i = readUnsignedShort(innerClasses); i > 0; --i) { + classVisitor.visitInnerClass(readClass(v, c), + readClass(v + 2, c), readUTF8(v + 4, c), + readUnsignedShort(v + 6)); + v += 8; } } - // visits the fields - i = readUnsignedShort(u); + // visits the fields and methods + u = header + 10 + 2 * interfaces.length; + for (int i = readUnsignedShort(u - 2); i > 0; --i) { + u = readField(classVisitor, context, u); + } u += 2; - for (; i > 0; --i) { - access = readUnsignedShort(u); - name = readUTF8(u + 2, c); - desc = readUTF8(u + 4, c); - // visits the field's attributes and looks for a ConstantValue - // attribute - int fieldValueItem = 0; - signature = null; - anns = 0; - ianns = 0; - cattrs = null; - - j = readUnsignedShort(u + 6); - u += 8; - for (; j > 0; --j) { - attrName = readUTF8(u, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if ("ConstantValue".equals(attrName)) { - fieldValueItem = readUnsignedShort(u + 6); - } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(u + 6, c); - } else if ("Deprecated".equals(attrName)) { - access |= Opcodes.ACC_DEPRECATED; - } else if ("Synthetic".equals(attrName)) { - access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = u + 6; - } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = u + 6; - } else { - attr = readAttribute(attrs, - attrName, - u + 6, - readInt(u + 2), - c, - -1, - null); - if (attr != null) { - attr.next = cattrs; - cattrs = attr; - } + for (int i = readUnsignedShort(u - 2); i > 0; --i) { + u = readMethod(classVisitor, context, u); + } + + // visits the end of the class + classVisitor.visitEnd(); + } + + /** + * Reads a field and makes the given visitor visit it. + * + * @param classVisitor + * the visitor that must visit the field. + * @param context + * information about the class being parsed. + * @param u + * the start offset of the field in the class file. + * @return the offset of the first byte following the field in the class. + */ + private int readField(final ClassVisitor classVisitor, + final Context context, int u) { + // reads the field declaration + char[] c = context.buffer; + int access = readUnsignedShort(u); + String name = readUTF8(u + 2, c); + String desc = readUTF8(u + 4, c); + u += 6; + + // reads the field attributes + String signature = null; + int anns = 0; + int ianns = 0; + Object value = null; + Attribute attributes = null; + + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); + // tests are sorted in decreasing frequency order + // (based on frequencies observed on typical classes) + if ("ConstantValue".equals(attrName)) { + int item = readUnsignedShort(u + 8); + value = item == 0 ? null : readConst(item, c); + } else if (SIGNATURES && "Signature".equals(attrName)) { + signature = readUTF8(u + 8, c); + } else if ("Deprecated".equals(attrName)) { + access |= Opcodes.ACC_DEPRECATED; + } else if ("Synthetic".equals(attrName)) { + access |= Opcodes.ACC_SYNTHETIC + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; + } else if (ANNOTATIONS + && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u + 8; + } else { + Attribute attr = readAttribute(context.attrs, attrName, u + 8, + readInt(u + 4), c, -1, null); + if (attr != null) { + attr.next = attributes; + attributes = attr; } - u += 6 + readInt(u + 2); } - // visits the field - FieldVisitor fv = classVisitor.visitField(access, - name, - desc, - signature, - fieldValueItem == 0 ? null : readConst(fieldValueItem, c)); - // visits the field annotations and attributes - if (fv != null) { - if (ANNOTATIONS) { - for (j = 1; j >= 0; --j) { - v = j == 0 ? ianns : anns; - if (v != 0) { - k = readUnsignedShort(v); - v += 2; - for (; k > 0; --k) { - v = readAnnotationValues(v + 2, - c, - true, - fv.visitAnnotation(readUTF8(v, c), j != 0)); - } - } - } - } - while (cattrs != null) { - attr = cattrs.next; - cattrs.next = null; - fv.visitAttribute(cattrs); - cattrs = attr; - } - fv.visitEnd(); + u += 6 + readInt(u + 4); + } + u += 2; + + // visits the field declaration + FieldVisitor fv = classVisitor.visitField(access, name, desc, + signature, value); + if (fv == null) { + return u; + } + + // visits the field annotations + if (ANNOTATIONS && anns != 0) { + for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + fv.visitAnnotation(readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && ianns != 0) { + for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + fv.visitAnnotation(readUTF8(v, c), false)); } } - // visits the methods - i = readUnsignedShort(u); - u += 2; - for (; i > 0; --i) { - int u0 = u + 6; - access = readUnsignedShort(u); - name = readUTF8(u + 2, c); - desc = readUTF8(u + 4, c); - signature = null; - anns = 0; - ianns = 0; - int dann = 0; - int mpanns = 0; - int impanns = 0; - cattrs = null; - v = 0; - w = 0; - - // looks for Code and Exceptions attributes - j = readUnsignedShort(u + 6); - u += 8; - for (; j > 0; --j) { - attrName = readUTF8(u, c); - int attrSize = readInt(u + 2); - u += 6; - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if ("Code".equals(attrName)) { - if (!skipCode) { - v = u; - } - } else if ("Exceptions".equals(attrName)) { - w = u; - } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(u, c); - } else if ("Deprecated".equals(attrName)) { - access |= Opcodes.ACC_DEPRECATED; - } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = u; - } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { - dann = u; - } else if ("Synthetic".equals(attrName)) { - access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = u; - } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName)) - { - mpanns = u; - } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName)) - { - impanns = u; - } else { - attr = readAttribute(attrs, - attrName, - u, - attrSize, - c, - -1, - null); - if (attr != null) { - attr.next = cattrs; - cattrs = attr; - } + // visits the field attributes + while (attributes != null) { + Attribute attr = attributes.next; + attributes.next = null; + fv.visitAttribute(attributes); + attributes = attr; + } + + // visits the end of the field + fv.visitEnd(); + + return u; + } + + /** + * Reads a method and makes the given visitor visit it. + * + * @param classVisitor + * the visitor that must visit the method. + * @param context + * information about the class being parsed. + * @param u + * the start offset of the method in the class file. + * @return the offset of the first byte following the method in the class. + */ + private int readMethod(final ClassVisitor classVisitor, + final Context context, int u) { + // reads the method declaration + char[] c = context.buffer; + int access = readUnsignedShort(u); + String name = readUTF8(u + 2, c); + String desc = readUTF8(u + 4, c); + u += 6; + + // reads the method attributes + int code = 0; + int exception = 0; + String[] exceptions = null; + String signature = null; + int anns = 0; + int ianns = 0; + int dann = 0; + int mpanns = 0; + int impanns = 0; + int firstAttribute = u; + Attribute attributes = null; + + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); + // tests are sorted in decreasing frequency order + // (based on frequencies observed on typical classes) + if ("Code".equals(attrName)) { + if ((context.flags & SKIP_CODE) == 0) { + code = u + 8; } - u += attrSize; - } - // reads declared exceptions - String[] exceptions; - if (w == 0) { - exceptions = null; + } else if ("Exceptions".equals(attrName)) { + exceptions = new String[readUnsignedShort(u + 8)]; + exception = u + 10; + for (int j = 0; j < exceptions.length; ++j) { + exceptions[j] = readClass(exception, c); + exception += 2; + } + } else if (SIGNATURES && "Signature".equals(attrName)) { + signature = readUTF8(u + 8, c); + } else if ("Deprecated".equals(attrName)) { + access |= Opcodes.ACC_DEPRECATED; + } else if (ANNOTATIONS + && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = u + 8; + } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { + dann = u + 8; + } else if ("Synthetic".equals(attrName)) { + access |= Opcodes.ACC_SYNTHETIC + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; + } else if (ANNOTATIONS + && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u + 8; + } else if (ANNOTATIONS + && "RuntimeVisibleParameterAnnotations".equals(attrName)) { + mpanns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleParameterAnnotations".equals(attrName)) { + impanns = u + 8; } else { - exceptions = new String[readUnsignedShort(w)]; - w += 2; - for (j = 0; j < exceptions.length; ++j) { - exceptions[j] = readClass(w, c); - w += 2; + Attribute attr = readAttribute(context.attrs, attrName, u + 8, + readInt(u + 4), c, -1, null); + if (attr != null) { + attr.next = attributes; + attributes = attr; } } + u += 6 + readInt(u + 4); + } + u += 2; - // visits the method's code, if any - MethodVisitor mv = classVisitor.visitMethod(access, - name, - desc, - signature, - exceptions); + // visits the method declaration + MethodVisitor mv = classVisitor.visitMethod(access, name, desc, + signature, exceptions); + if (mv == null) { + return u; + } - if (mv != null) { - /* - * if the returned MethodVisitor is in fact a MethodWriter, it - * means there is no method adapter between the reader and the - * writer. If, in addition, the writer's constant pool was - * copied from this reader (mw.cw.cr == this), and the signature - * and exceptions of the method have not been changed, then it - * is possible to skip all visit events and just copy the - * original code of the method to the writer (the access, name - * and descriptor can have been changed, this is not important - * since they are not copied as is from the reader). - */ - if (WRITER && mv instanceof MethodWriter) { - MethodWriter mw = (MethodWriter) mv; - if (mw.cw.cr == this) { - if (signature == mw.signature) { - boolean sameExceptions = false; - if (exceptions == null) { - sameExceptions = mw.exceptionCount == 0; - } else { - if (exceptions.length == mw.exceptionCount) { - sameExceptions = true; - for (j = exceptions.length - 1; j >= 0; --j) - { - w -= 2; - if (mw.exceptions[j] != readUnsignedShort(w)) - { - sameExceptions = false; - break; - } - } - } - } - if (sameExceptions) { - /* - * we do not copy directly the code into - * MethodWriter to save a byte array copy - * operation. The real copy will be done in - * ClassWriter.toByteArray(). - */ - mw.classReaderOffset = u0; - mw.classReaderLength = u - u0; - continue; - } + /* + * if the returned MethodVisitor is in fact a MethodWriter, it means + * there is no method adapter between the reader and the writer. If, in + * addition, the writer's constant pool was copied from this reader + * (mw.cw.cr == this), and the signature and exceptions of the method + * have not been changed, then it is possible to skip all visit events + * and just copy the original code of the method to the writer (the + * access, name and descriptor can have been changed, this is not + * important since they are not copied as is from the reader). + */ + if (WRITER && mv instanceof MethodWriter) { + MethodWriter mw = (MethodWriter) mv; + if (mw.cw.cr == this && signature == mw.signature) { + boolean sameExceptions = false; + if (exceptions == null) { + sameExceptions = mw.exceptionCount == 0; + } else if (exceptions.length == mw.exceptionCount) { + sameExceptions = true; + for (int j = exceptions.length - 1; j >= 0; --j) { + exception -= 2; + if (mw.exceptions[j] != readUnsignedShort(exception)) { + sameExceptions = false; + break; } } } - - if (ANNOTATIONS && dann != 0) { - AnnotationVisitor dv = mv.visitAnnotationDefault(); - readAnnotationValue(dann, c, null, dv); - if (dv != null) { - dv.visitEnd(); - } - } - if (ANNOTATIONS) { - for (j = 1; j >= 0; --j) { - w = j == 0 ? ianns : anns; - if (w != 0) { - k = readUnsignedShort(w); - w += 2; - for (; k > 0; --k) { - w = readAnnotationValues(w + 2, - c, - true, - mv.visitAnnotation(readUTF8(w, c), j != 0)); - } - } - } + if (sameExceptions) { + /* + * we do not copy directly the code into MethodWriter to + * save a byte array copy operation. The real copy will be + * done in ClassWriter.toByteArray(). + */ + mw.classReaderOffset = firstAttribute; + mw.classReaderLength = u - firstAttribute; + return u; } - if (ANNOTATIONS && mpanns != 0) { - readParameterAnnotations(mpanns, desc, c, true, mv); + } + } + + // visits the method annotations + if (ANNOTATIONS && dann != 0) { + AnnotationVisitor dv = mv.visitAnnotationDefault(); + readAnnotationValue(dann, c, null, dv); + if (dv != null) { + dv.visitEnd(); + } + } + if (ANNOTATIONS && anns != 0) { + for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + mv.visitAnnotation(readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && ianns != 0) { + for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + mv.visitAnnotation(readUTF8(v, c), false)); + } + } + if (ANNOTATIONS && mpanns != 0) { + readParameterAnnotations(mpanns, desc, c, true, mv); + } + if (ANNOTATIONS && impanns != 0) { + readParameterAnnotations(impanns, desc, c, false, mv); + } + + // visits the method attributes + while (attributes != null) { + Attribute attr = attributes.next; + attributes.next = null; + mv.visitAttribute(attributes); + attributes = attr; + } + + // visits the method code + if (code != 0) { + context.access = access; + context.name = name; + context.desc = desc; + mv.visitCode(); + readCode(mv, context, code); + } + + // visits the end of the method + mv.visitEnd(); + + return u; + } + + /** + * Reads the bytecode of a method and makes the given visitor visit it. + * + * @param mv + * the visitor that must visit the method's code. + * @param context + * information about the class being parsed. + * @param u + * the start offset of the code attribute in the class file. + */ + private void readCode(final MethodVisitor mv, final Context context, int u) { + // reads the header + byte[] b = this.b; + char[] c = context.buffer; + int maxStack = readUnsignedShort(u); + int maxLocals = readUnsignedShort(u + 2); + int codeLength = readInt(u + 4); + u += 8; + + // reads the bytecode to find the labels + int codeStart = u; + int codeEnd = u + codeLength; + Label[] labels = new Label[codeLength + 2]; + readLabel(codeLength + 1, labels); + while (u < codeEnd) { + int offset = u - codeStart; + int opcode = b[u] & 0xFF; + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + case ClassWriter.IMPLVAR_INSN: + u += 1; + break; + case ClassWriter.LABEL_INSN: + readLabel(offset + readShort(u + 1), labels); + u += 3; + break; + case ClassWriter.LABELW_INSN: + readLabel(offset + readInt(u + 1), labels); + u += 5; + break; + case ClassWriter.WIDE_INSN: + opcode = b[u + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + u += 6; + } else { + u += 4; } - if (ANNOTATIONS && impanns != 0) { - readParameterAnnotations(impanns, desc, c, false, mv); + break; + case ClassWriter.TABL_INSN: + // skips 0 to 3 padding bytes + u = u + 4 - (offset & 3); + // reads instruction + readLabel(offset + readInt(u), labels); + for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { + readLabel(offset + readInt(u + 12), labels); + u += 4; } - while (cattrs != null) { - attr = cattrs.next; - cattrs.next = null; - mv.visitAttribute(cattrs); - cattrs = attr; + u += 12; + break; + case ClassWriter.LOOK_INSN: + // skips 0 to 3 padding bytes + u = u + 4 - (offset & 3); + // reads instruction + readLabel(offset + readInt(u), labels); + for (int i = readInt(u + 4); i > 0; --i) { + readLabel(offset + readInt(u + 12), labels); + u += 8; } + u += 8; + break; + case ClassWriter.VAR_INSN: + case ClassWriter.SBYTE_INSN: + case ClassWriter.LDC_INSN: + u += 2; + break; + case ClassWriter.SHORT_INSN: + case ClassWriter.LDCW_INSN: + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.TYPE_INSN: + case ClassWriter.IINC_INSN: + u += 3; + break; + case ClassWriter.ITFMETH_INSN: + case ClassWriter.INDYMETH_INSN: + u += 5; + break; + // case MANA_INSN: + default: + u += 4; + break; } + } - if (mv != null && v != 0) { - int maxStack = readUnsignedShort(v); - int maxLocals = readUnsignedShort(v + 2); - int codeLength = readInt(v + 4); - v += 8; + // reads the try catch entries to find the labels, and also visits them + for (int i = readUnsignedShort(u); i > 0; --i) { + Label start = readLabel(readUnsignedShort(u + 2), labels); + Label end = readLabel(readUnsignedShort(u + 4), labels); + Label handler = readLabel(readUnsignedShort(u + 6), labels); + String type = readUTF8(items[readUnsignedShort(u + 8)], c); + mv.visitTryCatchBlock(start, end, handler, type); + u += 8; + } + u += 2; - int codeStart = v; - int codeEnd = v + codeLength; - - mv.visitCode(); - - // 1st phase: finds the labels - int label; - Label[] labels = new Label[codeLength + 2]; - readLabel(codeLength + 1, labels); - while (v < codeEnd) { - w = v - codeStart; - int opcode = b[v] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - v += 1; - break; - case ClassWriter.LABEL_INSN: - readLabel(w + readShort(v + 1), labels); - v += 3; - break; - case ClassWriter.LABELW_INSN: - readLabel(w + readInt(v + 1), labels); - v += 5; - break; - case ClassWriter.WIDE_INSN: - opcode = b[v + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - v += 6; - } else { - v += 4; - } - break; - case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes* - v = v + 4 - (w & 3); - // reads instruction - readLabel(w + readInt(v), labels); - j = readInt(v + 8) - readInt(v + 4) + 1; - v += 12; - for (; j > 0; --j) { - readLabel(w + readInt(v), labels); - v += 4; - } - break; - case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes* - v = v + 4 - (w & 3); - // reads instruction - readLabel(w + readInt(v), labels); - j = readInt(v + 4); - v += 8; - for (; j > 0; --j) { - readLabel(w + readInt(v + 4), labels); - v += 8; - } - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - v += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - v += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - v += 5; - break; - // case MANA_INSN: - default: - v += 4; - break; - } - } - // parses the try catch entries - j = readUnsignedShort(v); - v += 2; - for (; j > 0; --j) { - Label start = readLabel(readUnsignedShort(v), labels); - Label end = readLabel(readUnsignedShort(v + 2), labels); - Label handler = readLabel(readUnsignedShort(v + 4), labels); - int type = readUnsignedShort(v + 6); - if (type == 0) { - mv.visitTryCatchBlock(start, end, handler, null); - } else { - mv.visitTryCatchBlock(start, - end, - handler, - readUTF8(items[type], c)); - } - v += 8; - } - // parses the local variable, line number tables, and code - // attributes - int varTable = 0; - int varTypeTable = 0; - int stackMap = 0; - int stackMapSize = 0; - int frameCount = 0; - int frameMode = 0; - int frameOffset = 0; - int frameLocalCount = 0; - int frameLocalDiff = 0; - int frameStackCount = 0; - Object[] frameLocal = null; - Object[] frameStack = null; - boolean zip = true; - cattrs = null; - j = readUnsignedShort(v); - v += 2; - for (; j > 0; --j) { - attrName = readUTF8(v, c); - if ("LocalVariableTable".equals(attrName)) { - if (!skipDebug) { - varTable = v + 6; - k = readUnsignedShort(v + 6); - w = v + 8; - for (; k > 0; --k) { - label = readUnsignedShort(w); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } - label += readUnsignedShort(w + 2); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } - w += 10; - } - } - } else if ("LocalVariableTypeTable".equals(attrName)) { - varTypeTable = v + 6; - } else if ("LineNumberTable".equals(attrName)) { - if (!skipDebug) { - k = readUnsignedShort(v + 6); - w = v + 8; - for (; k > 0; --k) { - label = readUnsignedShort(w); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } - labels[label].line = readUnsignedShort(w + 2); - w += 4; - } - } - } else if (FRAMES && "StackMapTable".equals(attrName)) { - if ((flags & SKIP_FRAMES) == 0) { - stackMap = v + 8; - stackMapSize = readInt(v + 2); - frameCount = readUnsignedShort(v + 6); + // reads the code attributes + int varTable = 0; + int varTypeTable = 0; + boolean zip = true; + boolean unzip = (context.flags & EXPAND_FRAMES) != 0; + int stackMap = 0; + int stackMapSize = 0; + int frameCount = 0; + Context frame = null; + Attribute attributes = null; + + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); + if ("LocalVariableTable".equals(attrName)) { + if ((context.flags & SKIP_DEBUG) == 0) { + varTable = u + 8; + for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { + int label = readUnsignedShort(v + 10); + if (labels[label] == null) { + readLabel(label, labels).status |= Label.DEBUG; } - /* - * here we do not extract the labels corresponding to - * the attribute content. This would require a full - * parsing of the attribute, which would need to be - * repeated in the second phase (see below). Instead the - * content of the attribute is read one frame at a time - * (i.e. after a frame has been visited, the next frame - * is read), and the labels it contains are also - * extracted one frame at a time. Thanks to the ordering - * of frames, having only a "one frame lookahead" is not - * a problem, i.e. it is not possible to see an offset - * smaller than the offset of the current insn and for - * which no Label exist. - */ - /* - * This is not true for UNINITIALIZED type offsets. We - * solve this by parsing the stack map table without a - * full decoding (see below). - */ - } else if (FRAMES && "StackMap".equals(attrName)) { - if ((flags & SKIP_FRAMES) == 0) { - stackMap = v + 8; - stackMapSize = readInt(v + 2); - frameCount = readUnsignedShort(v + 6); - zip = false; - } - /* - * IMPORTANT! here we assume that the frames are - * ordered, as in the StackMapTable attribute, although - * this is not guaranteed by the attribute format. - */ - } else { - for (k = 0; k < attrs.length; ++k) { - if (attrs[k].type.equals(attrName)) { - attr = attrs[k].read(this, - v + 6, - readInt(v + 2), - c, - codeStart - 8, - labels); - if (attr != null) { - attr.next = cattrs; - cattrs = attr; - } - } + label += readUnsignedShort(v + 12); + if (labels[label] == null) { + readLabel(label, labels).status |= Label.DEBUG; } + v += 10; } - v += 6 + readInt(v + 2); } - - // 2nd phase: visits each instruction - if (FRAMES && stackMap != 0) { - // creates the very first (implicit) frame from the method - // descriptor - frameLocal = new Object[maxLocals]; - frameStack = new Object[maxStack]; - if (unzip) { - int local = 0; - if ((access & Opcodes.ACC_STATIC) == 0) { - if ("<init>".equals(name)) { - frameLocal[local++] = Opcodes.UNINITIALIZED_THIS; - } else { - frameLocal[local++] = readClass(header + 2, c); - } - } - j = 1; - loop: while (true) { - k = j; - switch (desc.charAt(j++)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - frameLocal[local++] = Opcodes.INTEGER; - break; - case 'F': - frameLocal[local++] = Opcodes.FLOAT; - break; - case 'J': - frameLocal[local++] = Opcodes.LONG; - break; - case 'D': - frameLocal[local++] = Opcodes.DOUBLE; - break; - case '[': - while (desc.charAt(j) == '[') { - ++j; - } - if (desc.charAt(j) == 'L') { - ++j; - while (desc.charAt(j) != ';') { - ++j; - } - } - frameLocal[local++] = desc.substring(k, ++j); - break; - case 'L': - while (desc.charAt(j) != ';') { - ++j; - } - frameLocal[local++] = desc.substring(k + 1, - j++); - break; - default: - break loop; - } + } else if ("LocalVariableTypeTable".equals(attrName)) { + varTypeTable = u + 8; + } else if ("LineNumberTable".equals(attrName)) { + if ((context.flags & SKIP_DEBUG) == 0) { + for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { + int label = readUnsignedShort(v + 10); + if (labels[label] == null) { + readLabel(label, labels).status |= Label.DEBUG; } - frameLocalCount = local; + labels[label].line = readUnsignedShort(v + 12); + v += 4; } - /* - * for the first explicit frame the offset is not - * offset_delta + 1 but only offset_delta; setting the - * implicit frame offset to -1 allow the use of the - * "offset_delta + 1" rule in all cases - */ - frameOffset = -1; - /* - * Finds labels for UNINITIALIZED frame types. Instead of - * decoding each element of the stack map table, we look - * for 3 consecutive bytes that "look like" an UNINITIALIZED - * type (tag 8, offset within code bounds, NEW instruction - * at this offset). We may find false positives (i.e. not - * real UNINITIALIZED types), but this should be rare, and - * the only consequence will be the creation of an unneeded - * label. This is better than creating a label for each NEW - * instruction, and faster than fully decoding the whole - * stack map table. - */ - for (j = stackMap; j < stackMap + stackMapSize - 2; ++j) { - if (b[j] == 8) { // UNINITIALIZED FRAME TYPE - k = readUnsignedShort(j + 1); - if (k >= 0 && k < codeLength) { // potential offset - if ((b[codeStart + k] & 0xFF) == Opcodes.NEW) { // NEW at this offset - readLabel(k, labels); - } - } + } + } else if (FRAMES && "StackMapTable".equals(attrName)) { + if ((context.flags & SKIP_FRAMES) == 0) { + stackMap = u + 10; + stackMapSize = readInt(u + 4); + frameCount = readUnsignedShort(u + 8); + } + /* + * here we do not extract the labels corresponding to the + * attribute content. This would require a full parsing of the + * attribute, which would need to be repeated in the second + * phase (see below). Instead the content of the attribute is + * read one frame at a time (i.e. after a frame has been + * visited, the next frame is read), and the labels it contains + * are also extracted one frame at a time. Thanks to the + * ordering of frames, having only a "one frame lookahead" is + * not a problem, i.e. it is not possible to see an offset + * smaller than the offset of the current insn and for which no + * Label exist. + */ + /* + * This is not true for UNINITIALIZED type offsets. We solve + * this by parsing the stack map table without a full decoding + * (see below). + */ + } else if (FRAMES && "StackMap".equals(attrName)) { + if ((context.flags & SKIP_FRAMES) == 0) { + zip = false; + stackMap = u + 10; + stackMapSize = readInt(u + 4); + frameCount = readUnsignedShort(u + 8); + } + /* + * IMPORTANT! here we assume that the frames are ordered, as in + * the StackMapTable attribute, although this is not guaranteed + * by the attribute format. + */ + } else { + for (int j = 0; j < context.attrs.length; ++j) { + if (context.attrs[j].type.equals(attrName)) { + Attribute attr = context.attrs[j].read(this, u + 8, + readInt(u + 4), c, codeStart - 8, labels); + if (attr != null) { + attr.next = attributes; + attributes = attr; } } } - v = codeStart; - Label l; - while (v < codeEnd) { - w = v - codeStart; - - l = labels[w]; - if (l != null) { - mv.visitLabel(l); - if (!skipDebug && l.line > 0) { - mv.visitLineNumber(l.line, l); + } + u += 6 + readInt(u + 4); + } + u += 2; + + // generates the first (implicit) stack map frame + if (FRAMES && stackMap != 0) { + /* + * for the first explicit frame the offset is not offset_delta + 1 + * but only offset_delta; setting the implicit frame offset to -1 + * allow the use of the "offset_delta + 1" rule in all cases + */ + frame = context; + frame.offset = -1; + frame.mode = 0; + frame.localCount = 0; + frame.localDiff = 0; + frame.stackCount = 0; + frame.local = new Object[maxLocals]; + frame.stack = new Object[maxStack]; + if (unzip) { + getImplicitFrame(context); + } + /* + * Finds labels for UNINITIALIZED frame types. Instead of decoding + * each element of the stack map table, we look for 3 consecutive + * bytes that "look like" an UNINITIALIZED type (tag 8, offset + * within code bounds, NEW instruction at this offset). We may find + * false positives (i.e. not real UNINITIALIZED types), but this + * should be rare, and the only consequence will be the creation of + * an unneeded label. This is better than creating a label for each + * NEW instruction, and faster than fully decoding the whole stack + * map table. + */ + for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) { + if (b[i] == 8) { // UNINITIALIZED FRAME TYPE + int v = readUnsignedShort(i + 1); + if (v >= 0 && v < codeLength) { + if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { + readLabel(v, labels); } } + } + } + } - while (FRAMES && frameLocal != null - && (frameOffset == w || frameOffset == -1)) - { - // if there is a frame for this offset, - // makes the visitor visit it, - // and reads the next frame if there is one. - if (!zip || unzip) { - mv.visitFrame(Opcodes.F_NEW, - frameLocalCount, - frameLocal, - frameStackCount, - frameStack); - } else if (frameOffset != -1) { - mv.visitFrame(frameMode, - frameLocalDiff, - frameLocal, - frameStackCount, - frameStack); - } + // visits the instructions + u = codeStart; + while (u < codeEnd) { + int offset = u - codeStart; + + // visits the label and line number for this offset, if any + Label l = labels[offset]; + if (l != null) { + mv.visitLabel(l); + if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { + mv.visitLineNumber(l.line, l); + } + } - if (frameCount > 0) { - int tag, delta, n; - if (zip) { - tag = b[stackMap++] & 0xFF; - } else { - tag = MethodWriter.FULL_FRAME; - frameOffset = -1; - } - frameLocalDiff = 0; - if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) - { - delta = tag; - frameMode = Opcodes.F_SAME; - frameStackCount = 0; - } else if (tag < MethodWriter.RESERVED) { - delta = tag - - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME; - stackMap = readFrameType(frameStack, - 0, - stackMap, - c, - labels); - frameMode = Opcodes.F_SAME1; - frameStackCount = 1; - } else { - delta = readUnsignedShort(stackMap); - stackMap += 2; - if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) - { - stackMap = readFrameType(frameStack, - 0, - stackMap, - c, - labels); - frameMode = Opcodes.F_SAME1; - frameStackCount = 1; - } else if (tag >= MethodWriter.CHOP_FRAME - && tag < MethodWriter.SAME_FRAME_EXTENDED) - { - frameMode = Opcodes.F_CHOP; - frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED - - tag; - frameLocalCount -= frameLocalDiff; - frameStackCount = 0; - } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) - { - frameMode = Opcodes.F_SAME; - frameStackCount = 0; - } else if (tag < MethodWriter.FULL_FRAME) { - j = unzip ? frameLocalCount : 0; - for (k = tag - - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--) - { - stackMap = readFrameType(frameLocal, - j++, - stackMap, - c, - labels); - } - frameMode = Opcodes.F_APPEND; - frameLocalDiff = tag - - MethodWriter.SAME_FRAME_EXTENDED; - frameLocalCount += frameLocalDiff; - frameStackCount = 0; - } else { // if (tag == FULL_FRAME) { - frameMode = Opcodes.F_FULL; - n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap); - stackMap += 2; - for (j = 0; n > 0; n--) { - stackMap = readFrameType(frameLocal, - j++, - stackMap, - c, - labels); - } - n = frameStackCount = readUnsignedShort(stackMap); - stackMap += 2; - for (j = 0; n > 0; n--) { - stackMap = readFrameType(frameStack, - j++, - stackMap, - c, - labels); - } - } - } - frameOffset += delta + 1; - readLabel(frameOffset, labels); - - --frameCount; - } else { - frameLocal = null; - } + // visits the frame for this offset, if any + while (FRAMES && frame != null + && (frame.offset == offset || frame.offset == -1)) { + // if there is a frame for this offset, makes the visitor visit + // it, and reads the next frame if there is one. + if (frame.offset != -1) { + if (!zip || unzip) { + mv.visitFrame(Opcodes.F_NEW, frame.localCount, + frame.local, frame.stackCount, frame.stack); + } else { + mv.visitFrame(frame.mode, frame.localDiff, frame.local, + frame.stackCount, frame.stack); } + } + if (frameCount > 0) { + stackMap = readFrame(stackMap, zip, unzip, labels, frame); + --frameCount; + } else { + frame = null; + } + } - int opcode = b[v] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - mv.visitInsn(opcode); - v += 1; - break; - case ClassWriter.IMPLVAR_INSN: - if (opcode > Opcodes.ISTORE) { - opcode -= 59; // ISTORE_0 - mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), - opcode & 0x3); - } else { - opcode -= 26; // ILOAD_0 - mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), - opcode & 0x3); - } - v += 1; - break; - case ClassWriter.LABEL_INSN: - mv.visitJumpInsn(opcode, labels[w - + readShort(v + 1)]); - v += 3; - break; - case ClassWriter.LABELW_INSN: - mv.visitJumpInsn(opcode - 33, labels[w - + readInt(v + 1)]); - v += 5; - break; - case ClassWriter.WIDE_INSN: - opcode = b[v + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - mv.visitIincInsn(readUnsignedShort(v + 2), - readShort(v + 4)); - v += 6; - } else { - mv.visitVarInsn(opcode, - readUnsignedShort(v + 2)); - v += 4; - } - break; - case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes - v = v + 4 - (w & 3); - // reads instruction - label = w + readInt(v); - int min = readInt(v + 4); - int max = readInt(v + 8); - v += 12; - Label[] table = new Label[max - min + 1]; - for (j = 0; j < table.length; ++j) { - table[j] = labels[w + readInt(v)]; - v += 4; - } - mv.visitTableSwitchInsn(min, - max, - labels[label], - table); - break; - case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes - v = v + 4 - (w & 3); - // reads instruction - label = w + readInt(v); - j = readInt(v + 4); - v += 8; - int[] keys = new int[j]; - Label[] values = new Label[j]; - for (j = 0; j < keys.length; ++j) { - keys[j] = readInt(v); - values[j] = labels[w + readInt(v + 4)]; - v += 8; - } - mv.visitLookupSwitchInsn(labels[label], - keys, - values); - break; - case ClassWriter.VAR_INSN: - mv.visitVarInsn(opcode, b[v + 1] & 0xFF); - v += 2; - break; - case ClassWriter.SBYTE_INSN: - mv.visitIntInsn(opcode, b[v + 1]); - v += 2; - break; - case ClassWriter.SHORT_INSN: - mv.visitIntInsn(opcode, readShort(v + 1)); - v += 3; - break; - case ClassWriter.LDC_INSN: - mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c)); - v += 2; - break; - case ClassWriter.LDCW_INSN: - mv.visitLdcInsn(readConst(readUnsignedShort(v + 1), - c)); - v += 3; - break; - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.ITFMETH_INSN: { - int cpIndex = items[readUnsignedShort(v + 1)]; - String iowner = readClass(cpIndex, c); - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String iname = readUTF8(cpIndex, c); - String idesc = readUTF8(cpIndex + 2, c); - if (opcode < Opcodes.INVOKEVIRTUAL) { - mv.visitFieldInsn(opcode, iowner, iname, idesc); - } else { - mv.visitMethodInsn(opcode, iowner, iname, idesc); - } - if (opcode == Opcodes.INVOKEINTERFACE) { - v += 5; - } else { - v += 3; - } - break; - } - case ClassWriter.INDYMETH_INSN: { - int cpIndex = items[readUnsignedShort(v + 1)]; - int bsmIndex = bootstrapMethods[readUnsignedShort(cpIndex)]; - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String iname = readUTF8(cpIndex, c); - String idesc = readUTF8(cpIndex + 2, c); - - int mhIndex = readUnsignedShort(bsmIndex); - Handle bsm = (Handle) readConst(mhIndex, c); - int bsmArgCount = readUnsignedShort(bsmIndex + 2); - Object[] bsmArgs = new Object[bsmArgCount]; - bsmIndex += 4; - for(int a = 0; a < bsmArgCount; a++) { - int argIndex = readUnsignedShort(bsmIndex); - bsmArgs[a] = readConst(argIndex, c); - bsmIndex += 2; - } - mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs); - - v += 5; - break; - } - case ClassWriter.TYPE_INSN: - mv.visitTypeInsn(opcode, readClass(v + 1, c)); - v += 3; - break; - case ClassWriter.IINC_INSN: - mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]); - v += 3; - break; - // case MANA_INSN: - default: - mv.visitMultiANewArrayInsn(readClass(v + 1, c), - b[v + 3] & 0xFF); - v += 4; - break; - } + // visits the instruction at this offset + int opcode = b[u] & 0xFF; + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + mv.visitInsn(opcode); + u += 1; + break; + case ClassWriter.IMPLVAR_INSN: + if (opcode > Opcodes.ISTORE) { + opcode -= 59; // ISTORE_0 + mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), + opcode & 0x3); + } else { + opcode -= 26; // ILOAD_0 + mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3); } - l = labels[codeEnd - codeStart]; - if (l != null) { - mv.visitLabel(l); + u += 1; + break; + case ClassWriter.LABEL_INSN: + mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]); + u += 3; + break; + case ClassWriter.LABELW_INSN: + mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]); + u += 5; + break; + case ClassWriter.WIDE_INSN: + opcode = b[u + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4)); + u += 6; + } else { + mv.visitVarInsn(opcode, readUnsignedShort(u + 2)); + u += 4; } - // visits the local variable tables - if (!skipDebug && varTable != 0) { - int[] typeTable = null; - if (varTypeTable != 0) { - k = readUnsignedShort(varTypeTable) * 3; - w = varTypeTable + 2; - typeTable = new int[k]; - while (k > 0) { - typeTable[--k] = w + 6; // signature - typeTable[--k] = readUnsignedShort(w + 8); // index - typeTable[--k] = readUnsignedShort(w); // start - w += 10; - } - } - k = readUnsignedShort(varTable); - w = varTable + 2; - for (; k > 0; --k) { - int start = readUnsignedShort(w); - int length = readUnsignedShort(w + 2); - int index = readUnsignedShort(w + 8); - String vsignature = null; - if (typeTable != null) { - for (int a = 0; a < typeTable.length; a += 3) { - if (typeTable[a] == start - && typeTable[a + 1] == index) - { - vsignature = readUTF8(typeTable[a + 2], c); - break; - } - } - } - mv.visitLocalVariable(readUTF8(w + 4, c), - readUTF8(w + 6, c), - vsignature, - labels[start], - labels[start + length], - index); - w += 10; - } + break; + case ClassWriter.TABL_INSN: { + // skips 0 to 3 padding bytes + u = u + 4 - (offset & 3); + // reads instruction + int label = offset + readInt(u); + int min = readInt(u + 4); + int max = readInt(u + 8); + Label[] table = new Label[max - min + 1]; + u += 12; + for (int i = 0; i < table.length; ++i) { + table[i] = labels[offset + readInt(u)]; + u += 4; + } + mv.visitTableSwitchInsn(min, max, labels[label], table); + break; + } + case ClassWriter.LOOK_INSN: { + // skips 0 to 3 padding bytes + u = u + 4 - (offset & 3); + // reads instruction + int label = offset + readInt(u); + int len = readInt(u + 4); + int[] keys = new int[len]; + Label[] values = new Label[len]; + u += 8; + for (int i = 0; i < len; ++i) { + keys[i] = readInt(u); + values[i] = labels[offset + readInt(u + 4)]; + u += 8; + } + mv.visitLookupSwitchInsn(labels[label], keys, values); + break; + } + case ClassWriter.VAR_INSN: + mv.visitVarInsn(opcode, b[u + 1] & 0xFF); + u += 2; + break; + case ClassWriter.SBYTE_INSN: + mv.visitIntInsn(opcode, b[u + 1]); + u += 2; + break; + case ClassWriter.SHORT_INSN: + mv.visitIntInsn(opcode, readShort(u + 1)); + u += 3; + break; + case ClassWriter.LDC_INSN: + mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c)); + u += 2; + break; + case ClassWriter.LDCW_INSN: + mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c)); + u += 3; + break; + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.ITFMETH_INSN: { + int cpIndex = items[readUnsignedShort(u + 1)]; + String iowner = readClass(cpIndex, c); + cpIndex = items[readUnsignedShort(cpIndex + 2)]; + String iname = readUTF8(cpIndex, c); + String idesc = readUTF8(cpIndex + 2, c); + if (opcode < Opcodes.INVOKEVIRTUAL) { + mv.visitFieldInsn(opcode, iowner, iname, idesc); + } else { + mv.visitMethodInsn(opcode, iowner, iname, idesc); } - // visits the other attributes - while (cattrs != null) { - attr = cattrs.next; - cattrs.next = null; - mv.visitAttribute(cattrs); - cattrs = attr; + if (opcode == Opcodes.INVOKEINTERFACE) { + u += 5; + } else { + u += 3; } - // visits the max stack and max locals values - mv.visitMaxs(maxStack, maxLocals); + break; } + case ClassWriter.INDYMETH_INSN: { + int cpIndex = items[readUnsignedShort(u + 1)]; + int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)]; + Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c); + int bsmArgCount = readUnsignedShort(bsmIndex + 2); + Object[] bsmArgs = new Object[bsmArgCount]; + bsmIndex += 4; + for (int i = 0; i < bsmArgCount; i++) { + bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c); + bsmIndex += 2; + } + cpIndex = items[readUnsignedShort(cpIndex + 2)]; + String iname = readUTF8(cpIndex, c); + String idesc = readUTF8(cpIndex + 2, c); + mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs); + u += 5; + break; + } + case ClassWriter.TYPE_INSN: + mv.visitTypeInsn(opcode, readClass(u + 1, c)); + u += 3; + break; + case ClassWriter.IINC_INSN: + mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]); + u += 3; + break; + // case MANA_INSN: + default: + mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF); + u += 4; + break; + } + } + if (labels[codeLength] != null) { + mv.visitLabel(labels[codeLength]); + } - if (mv != null) { - mv.visitEnd(); + // visits the local variable tables + if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) { + int[] typeTable = null; + if (varTypeTable != 0) { + u = varTypeTable + 2; + typeTable = new int[readUnsignedShort(varTypeTable) * 3]; + for (int i = typeTable.length; i > 0;) { + typeTable[--i] = u + 6; // signature + typeTable[--i] = readUnsignedShort(u + 8); // index + typeTable[--i] = readUnsignedShort(u); // start + u += 10; + } + } + u = varTable + 2; + for (int i = readUnsignedShort(varTable); i > 0; --i) { + int start = readUnsignedShort(u); + int length = readUnsignedShort(u + 2); + int index = readUnsignedShort(u + 8); + String vsignature = null; + if (typeTable != null) { + for (int j = 0; j < typeTable.length; j += 3) { + if (typeTable[j] == start && typeTable[j + 1] == index) { + vsignature = readUTF8(typeTable[j + 2], c); + break; + } + } + } + mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c), + vsignature, labels[start], labels[start + length], + index); + u += 10; } } - // visits the end of the class - classVisitor.visitEnd(); + // visits the code attributes + while (attributes != null) { + Attribute attr = attributes.next; + attributes.next = null; + mv.visitAttribute(attributes); + attributes = attr; + } + + // visits the max stack and max locals values + mv.visitMaxs(maxStack, maxLocals); } /** * Reads parameter annotations and makes the given visitor visit them. * - * @param v start offset in {@link #b b} of the annotations to be read. - * @param desc the method descriptor. - * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or - * {@link #readConst readConst}. - * @param visible <tt>true</tt> if the annotations to be read are visible - * at runtime. - * @param mv the visitor that must visit the annotations. + * @param v + * start offset in {@link #b b} of the annotations to be read. + * @param desc + * the method descriptor. + * @param buf + * buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or {@link #readConst + * readConst}. + * @param visible + * <tt>true</tt> if the annotations to be read are visible at + * runtime. + * @param mv + * the visitor that must visit the annotations. */ - private void readParameterAnnotations( - int v, - final String desc, - final char[] buf, - final boolean visible, - final MethodVisitor mv) - { + private void readParameterAnnotations(int v, final String desc, + final char[] buf, final boolean visible, final MethodVisitor mv) { int i; int n = b[v++] & 0xFF; // workaround for a bug in javac (javac compiler generates a parameter @@ -1679,21 +1458,22 @@ public class ClassReader { /** * Reads the values of an annotation and makes the given visitor visit them. * - * @param v the start offset in {@link #b b} of the values to be read - * (including the unsigned short that gives the number of values). - * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or - * {@link #readConst readConst}. - * @param named if the annotation values are named or not. - * @param av the visitor that must visit the values. + * @param v + * the start offset in {@link #b b} of the values to be read + * (including the unsigned short that gives the number of + * values). + * @param buf + * buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or {@link #readConst + * readConst}. + * @param named + * if the annotation values are named or not. + * @param av + * the visitor that must visit the values. * @return the end offset of the annotation values. */ - private int readAnnotationValues( - int v, - final char[] buf, - final boolean named, - final AnnotationVisitor av) - { + private int readAnnotationValues(int v, final char[] buf, + final boolean named, final AnnotationVisitor av) { int i = readUnsignedShort(v); v += 2; if (named) { @@ -1714,210 +1494,371 @@ public class ClassReader { /** * Reads a value of an annotation and makes the given visitor visit it. * - * @param v the start offset in {@link #b b} of the value to be read (<i>not - * including the value name constant pool index</i>). - * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or - * {@link #readConst readConst}. - * @param name the name of the value to be read. - * @param av the visitor that must visit the value. + * @param v + * the start offset in {@link #b b} of the value to be read + * (<i>not including the value name constant pool index</i>). + * @param buf + * buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or {@link #readConst + * readConst}. + * @param name + * the name of the value to be read. + * @param av + * the visitor that must visit the value. * @return the end offset of the annotation value. */ - private int readAnnotationValue( - int v, - final char[] buf, - final String name, - final AnnotationVisitor av) - { + private int readAnnotationValue(int v, final char[] buf, final String name, + final AnnotationVisitor av) { int i; if (av == null) { switch (b[v] & 0xFF) { - case 'e': // enum_const_value - return v + 5; - case '@': // annotation_value - return readAnnotationValues(v + 3, buf, true, null); - case '[': // array_value - return readAnnotationValues(v + 1, buf, false, null); - default: - return v + 3; + case 'e': // enum_const_value + return v + 5; + case '@': // annotation_value + return readAnnotationValues(v + 3, buf, true, null); + case '[': // array_value + return readAnnotationValues(v + 1, buf, false, null); + default: + return v + 3; } } switch (b[v++] & 0xFF) { - case 'I': // pointer to CONSTANT_Integer - case 'J': // pointer to CONSTANT_Long - case 'F': // pointer to CONSTANT_Float - case 'D': // pointer to CONSTANT_Double - av.visit(name, readConst(readUnsignedShort(v), buf)); - v += 2; - break; - case 'B': // pointer to CONSTANT_Byte - av.visit(name, - new Byte((byte) readInt(items[readUnsignedShort(v)]))); - v += 2; - break; - case 'Z': // pointer to CONSTANT_Boolean - av.visit(name, readInt(items[readUnsignedShort(v)]) == 0 - ? Boolean.FALSE - : Boolean.TRUE); - v += 2; - break; - case 'S': // pointer to CONSTANT_Short - av.visit(name, - new Short((short) readInt(items[readUnsignedShort(v)]))); - v += 2; + case 'I': // pointer to CONSTANT_Integer + case 'J': // pointer to CONSTANT_Long + case 'F': // pointer to CONSTANT_Float + case 'D': // pointer to CONSTANT_Double + av.visit(name, readConst(readUnsignedShort(v), buf)); + v += 2; + break; + case 'B': // pointer to CONSTANT_Byte + av.visit(name, + new Byte((byte) readInt(items[readUnsignedShort(v)]))); + v += 2; + break; + case 'Z': // pointer to CONSTANT_Boolean + av.visit(name, + readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE + : Boolean.TRUE); + v += 2; + break; + case 'S': // pointer to CONSTANT_Short + av.visit(name, new Short( + (short) readInt(items[readUnsignedShort(v)]))); + v += 2; + break; + case 'C': // pointer to CONSTANT_Char + av.visit(name, new Character( + (char) readInt(items[readUnsignedShort(v)]))); + v += 2; + break; + case 's': // pointer to CONSTANT_Utf8 + av.visit(name, readUTF8(v, buf)); + v += 2; + break; + case 'e': // enum_const_value + av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); + v += 4; + break; + case 'c': // class_info + av.visit(name, Type.getType(readUTF8(v, buf))); + v += 2; + break; + case '@': // annotation_value + v = readAnnotationValues(v + 2, buf, true, + av.visitAnnotation(name, readUTF8(v, buf))); + break; + case '[': // array_value + int size = readUnsignedShort(v); + v += 2; + if (size == 0) { + return readAnnotationValues(v - 2, buf, false, + av.visitArray(name)); + } + switch (this.b[v++] & 0xFF) { + case 'B': + byte[] bv = new byte[size]; + for (i = 0; i < size; i++) { + bv[i] = (byte) readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, bv); + --v; break; - case 'C': // pointer to CONSTANT_Char - av.visit(name, - new Character((char) readInt(items[readUnsignedShort(v)]))); - v += 2; + case 'Z': + boolean[] zv = new boolean[size]; + for (i = 0; i < size; i++) { + zv[i] = readInt(items[readUnsignedShort(v)]) != 0; + v += 3; + } + av.visit(name, zv); + --v; break; - case 's': // pointer to CONSTANT_Utf8 - av.visit(name, readUTF8(v, buf)); - v += 2; + case 'S': + short[] sv = new short[size]; + for (i = 0; i < size; i++) { + sv[i] = (short) readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, sv); + --v; break; - case 'e': // enum_const_value - av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); - v += 4; + case 'C': + char[] cv = new char[size]; + for (i = 0; i < size; i++) { + cv[i] = (char) readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, cv); + --v; break; - case 'c': // class_info - av.visit(name, Type.getType(readUTF8(v, buf))); - v += 2; + case 'I': + int[] iv = new int[size]; + for (i = 0; i < size; i++) { + iv[i] = readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, iv); + --v; break; - case '@': // annotation_value - v = readAnnotationValues(v + 2, - buf, - true, - av.visitAnnotation(name, readUTF8(v, buf))); + case 'J': + long[] lv = new long[size]; + for (i = 0; i < size; i++) { + lv[i] = readLong(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, lv); + --v; break; - case '[': // array_value - int size = readUnsignedShort(v); - v += 2; - if (size == 0) { - return readAnnotationValues(v - 2, - buf, - false, - av.visitArray(name)); + case 'F': + float[] fv = new float[size]; + for (i = 0; i < size; i++) { + fv[i] = Float + .intBitsToFloat(readInt(items[readUnsignedShort(v)])); + v += 3; } - switch (this.b[v++] & 0xFF) { - case 'B': - byte[] bv = new byte[size]; - for (i = 0; i < size; i++) { - bv[i] = (byte) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, bv); - --v; - break; - case 'Z': - boolean[] zv = new boolean[size]; - for (i = 0; i < size; i++) { - zv[i] = readInt(items[readUnsignedShort(v)]) != 0; - v += 3; - } - av.visit(name, zv); - --v; - break; - case 'S': - short[] sv = new short[size]; - for (i = 0; i < size; i++) { - sv[i] = (short) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, sv); - --v; - break; - case 'C': - char[] cv = new char[size]; - for (i = 0; i < size; i++) { - cv[i] = (char) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, cv); - --v; - break; - case 'I': - int[] iv = new int[size]; - for (i = 0; i < size; i++) { - iv[i] = readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, iv); - --v; - break; - case 'J': - long[] lv = new long[size]; - for (i = 0; i < size; i++) { - lv[i] = readLong(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, lv); - --v; - break; - case 'F': - float[] fv = new float[size]; - for (i = 0; i < size; i++) { - fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)])); - v += 3; - } - av.visit(name, fv); - --v; - break; - case 'D': - double[] dv = new double[size]; - for (i = 0; i < size; i++) { - dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)])); - v += 3; - } - av.visit(name, dv); - --v; - break; - default: - v = readAnnotationValues(v - 3, - buf, - false, - av.visitArray(name)); + av.visit(name, fv); + --v; + break; + case 'D': + double[] dv = new double[size]; + for (i = 0; i < size; i++) { + dv[i] = Double + .longBitsToDouble(readLong(items[readUnsignedShort(v)])); + v += 3; } + av.visit(name, dv); + --v; + break; + default: + v = readAnnotationValues(v - 3, buf, false, av.visitArray(name)); + } } return v; } - private int readFrameType( - final Object[] frame, - final int index, - int v, - final char[] buf, - final Label[] labels) - { - int type = b[v++] & 0xFF; - switch (type) { - case 0: - frame[index] = Opcodes.TOP; - break; - case 1: - frame[index] = Opcodes.INTEGER; - break; - case 2: - frame[index] = Opcodes.FLOAT; + /** + * Computes the implicit frame of the method currently being parsed (as + * defined in the given {@link Context}) and stores it in the given context. + * + * @param frame + * information about the class being parsed. + */ + private void getImplicitFrame(final Context frame) { + String desc = frame.desc; + Object[] locals = frame.local; + int local = 0; + if ((frame.access & Opcodes.ACC_STATIC) == 0) { + if ("<init>".equals(frame.name)) { + locals[local++] = Opcodes.UNINITIALIZED_THIS; + } else { + locals[local++] = readClass(header + 2, frame.buffer); + } + } + int i = 1; + loop: while (true) { + int j = i; + switch (desc.charAt(i++)) { + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + locals[local++] = Opcodes.INTEGER; break; - case 3: - frame[index] = Opcodes.DOUBLE; + case 'F': + locals[local++] = Opcodes.FLOAT; break; - case 4: - frame[index] = Opcodes.LONG; + case 'J': + locals[local++] = Opcodes.LONG; break; - case 5: - frame[index] = Opcodes.NULL; + case 'D': + locals[local++] = Opcodes.DOUBLE; break; - case 6: - frame[index] = Opcodes.UNINITIALIZED_THIS; + case '[': + while (desc.charAt(i) == '[') { + ++i; + } + if (desc.charAt(i) == 'L') { + ++i; + while (desc.charAt(i) != ';') { + ++i; + } + } + locals[local++] = desc.substring(j, ++i); break; - case 7: // Object - frame[index] = readClass(v, buf); - v += 2; + case 'L': + while (desc.charAt(i) != ';') { + ++i; + } + locals[local++] = desc.substring(j + 1, i++); break; - default: // Uninitialized - frame[index] = readLabel(readUnsignedShort(v), labels); - v += 2; + default: + break loop; + } + } + frame.localCount = local; + } + + /** + * Reads a stack map frame and stores the result in the given + * {@link Context} object. + * + * @param stackMap + * the start offset of a stack map frame in the class file. + * @param zip + * if the stack map frame at stackMap is compressed or not. + * @param unzip + * if the stack map frame must be uncompressed. + * @param labels + * the labels of the method currently being parsed, indexed by + * their offset. A new label for the parsed stack map frame is + * stored in this array if it does not already exist. + * @param frame + * where the parsed stack map frame must be stored. + * @return the offset of the first byte following the parsed frame. + */ + private int readFrame(int stackMap, boolean zip, boolean unzip, + Label[] labels, Context frame) { + char[] c = frame.buffer; + int tag; + int delta; + if (zip) { + tag = b[stackMap++] & 0xFF; + } else { + tag = MethodWriter.FULL_FRAME; + frame.offset = -1; + } + frame.localDiff = 0; + if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) { + delta = tag; + frame.mode = Opcodes.F_SAME; + frame.stackCount = 0; + } else if (tag < MethodWriter.RESERVED) { + delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME; + stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); + frame.mode = Opcodes.F_SAME1; + frame.stackCount = 1; + } else { + delta = readUnsignedShort(stackMap); + stackMap += 2; + if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { + stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); + frame.mode = Opcodes.F_SAME1; + frame.stackCount = 1; + } else if (tag >= MethodWriter.CHOP_FRAME + && tag < MethodWriter.SAME_FRAME_EXTENDED) { + frame.mode = Opcodes.F_CHOP; + frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag; + frame.localCount -= frame.localDiff; + frame.stackCount = 0; + } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) { + frame.mode = Opcodes.F_SAME; + frame.stackCount = 0; + } else if (tag < MethodWriter.FULL_FRAME) { + int local = unzip ? frame.localCount : 0; + for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) { + stackMap = readFrameType(frame.local, local++, stackMap, c, + labels); + } + frame.mode = Opcodes.F_APPEND; + frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED; + frame.localCount += frame.localDiff; + frame.stackCount = 0; + } else { // if (tag == FULL_FRAME) { + frame.mode = Opcodes.F_FULL; + int n = readUnsignedShort(stackMap); + stackMap += 2; + frame.localDiff = n; + frame.localCount = n; + for (int local = 0; n > 0; n--) { + stackMap = readFrameType(frame.local, local++, stackMap, c, + labels); + } + n = readUnsignedShort(stackMap); + stackMap += 2; + frame.stackCount = n; + for (int stack = 0; n > 0; n--) { + stackMap = readFrameType(frame.stack, stack++, stackMap, c, + labels); + } + } + } + frame.offset += delta + 1; + readLabel(frame.offset, labels); + return stackMap; + } + + /** + * Reads a stack map frame type and stores it at the given index in the + * given array. + * + * @param frame + * the array where the parsed type must be stored. + * @param index + * the index in 'frame' where the parsed type must be stored. + * @param v + * the start offset of the stack map frame type to read. + * @param buf + * a buffer to read strings. + * @param labels + * the labels of the method currently being parsed, indexed by + * their offset. If the parsed type is an Uninitialized type, a + * new label for the corresponding NEW instruction is stored in + * this array if it does not already exist. + * @return the offset of the first byte after the parsed type. + */ + private int readFrameType(final Object[] frame, final int index, int v, + final char[] buf, final Label[] labels) { + int type = b[v++] & 0xFF; + switch (type) { + case 0: + frame[index] = Opcodes.TOP; + break; + case 1: + frame[index] = Opcodes.INTEGER; + break; + case 2: + frame[index] = Opcodes.FLOAT; + break; + case 3: + frame[index] = Opcodes.DOUBLE; + break; + case 4: + frame[index] = Opcodes.LONG; + break; + case 5: + frame[index] = Opcodes.NULL; + break; + case 6: + frame[index] = Opcodes.UNINITIALIZED_THIS; + break; + case 7: // Object + frame[index] = readClass(v, buf); + v += 2; + break; + default: // Uninitialized + frame[index] = readLabel(readUnsignedShort(v), labels); + v += 2; } return v; } @@ -1927,10 +1868,12 @@ public class ClassReader { * implementation of this method creates a label for the given offset if it * has not been already created. * - * @param offset a bytecode offset in a method. - * @param labels the already created labels, indexed by their offset. If a - * label already exists for offset this method must not create a new - * one. Otherwise it must store the new label in this array. + * @param offset + * a bytecode offset in a method. + * @param labels + * the already created labels, indexed by their offset. If a + * label already exists for offset this method must not create a + * new one. Otherwise it must store the new label in this array. * @return a non null Label, which must be equal to labels[offset]. */ protected Label readLabel(int offset, Label[] labels) { @@ -1941,39 +1884,67 @@ public class ClassReader { } /** + * Returns the start index of the attribute_info structure of this class. + * + * @return the start index of the attribute_info structure of this class. + */ + private int getAttributes() { + // skips the header + int u = header + 8 + readUnsignedShort(header + 6) * 2; + // skips fields and methods + for (int i = readUnsignedShort(u); i > 0; --i) { + for (int j = readUnsignedShort(u + 8); j > 0; --j) { + u += 6 + readInt(u + 12); + } + u += 8; + } + u += 2; + for (int i = readUnsignedShort(u); i > 0; --i) { + for (int j = readUnsignedShort(u + 8); j > 0; --j) { + u += 6 + readInt(u + 12); + } + u += 8; + } + // the attribute_info structure starts just after the methods + return u + 2; + } + + /** * Reads an attribute in {@link #b b}. * - * @param attrs prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to the - * type of one the prototypes is ignored (i.e. an empty - * {@link Attribute} instance is returned). - * @param type the type of the attribute. - * @param off index of the first byte of the attribute's content in - * {@link #b b}. The 6 attribute header bytes, containing the type - * and the length of the attribute, are not taken into account here - * (they have already been read). - * @param len the length of the attribute's content. - * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or - * {@link #readConst readConst}. - * @param codeOff index of the first byte of code's attribute content in - * {@link #b b}, or -1 if the attribute to be read is not a code - * attribute. The 6 attribute header bytes, containing the type and - * the length of the attribute, are not taken into account here. - * @param labels the labels of the method's code, or <tt>null</tt> if the - * attribute to be read is not a code attribute. + * @param attrs + * prototypes of the attributes that must be parsed during the + * visit of the class. Any attribute whose type is not equal to + * the type of one the prototypes is ignored (i.e. an empty + * {@link Attribute} instance is returned). + * @param type + * the type of the attribute. + * @param off + * index of the first byte of the attribute's content in + * {@link #b b}. The 6 attribute header bytes, containing the + * type and the length of the attribute, are not taken into + * account here (they have already been read). + * @param len + * the length of the attribute's content. + * @param buf + * buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or {@link #readConst + * readConst}. + * @param codeOff + * index of the first byte of code's attribute content in + * {@link #b b}, or -1 if the attribute to be read is not a code + * attribute. The 6 attribute header bytes, containing the type + * and the length of the attribute, are not taken into account + * here. + * @param labels + * the labels of the method's code, or <tt>null</tt> if the + * attribute to be read is not a code attribute. * @return the attribute that has been read, or <tt>null</tt> to skip this * attribute. */ - private Attribute readAttribute( - final Attribute[] attrs, - final String type, - final int off, - final int len, - final char[] buf, - final int codeOff, - final Label[] labels) - { + private Attribute readAttribute(final Attribute[] attrs, final String type, + final int off, final int len, final char[] buf, final int codeOff, + final Label[] labels) { for (int i = 0; i < attrs.length; ++i) { if (attrs[i].type.equals(type)) { return attrs[i].read(this, off, len, buf, codeOff, labels); @@ -1987,9 +1958,9 @@ public class ClassReader { // ------------------------------------------------------------------------ /** - * Returns the number of constant pool items in {@link #b b}. + * Returns the number of constant pool items in {@link #b b}. * - * @return the number of constant pool items in {@link #b b}. + * @return the number of constant pool items in {@link #b b}. */ public int getItemCount() { return items.length; @@ -2000,7 +1971,8 @@ public class ClassReader { * one. <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param item the index a constant pool item. + * @param item + * the index a constant pool item. * @return the start index of the constant pool item in {@link #b b}, plus * one. */ @@ -2024,7 +1996,8 @@ public class ClassReader { * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters.</i> * - * @param index the start index of the value to be read in {@link #b b}. + * @param index + * the start index of the value to be read in {@link #b b}. * @return the read value. */ public int readByte(final int index) { @@ -2032,11 +2005,12 @@ public class ClassReader { } /** - * Reads an unsigned short value in {@link #b b}. <i>This method is - * intended for {@link Attribute} sub classes, and is normally not needed by - * class generators or adapters.</i> + * Reads an unsigned short value in {@link #b b}. <i>This method is intended + * for {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters.</i> * - * @param index the start index of the value to be read in {@link #b b}. + * @param index + * the start index of the value to be read in {@link #b b}. * @return the read value. */ public int readUnsignedShort(final int index) { @@ -2049,7 +2023,8 @@ public class ClassReader { * for {@link Attribute} sub classes, and is normally not needed by class * generators or adapters.</i> * - * @param index the start index of the value to be read in {@link #b b}. + * @param index + * the start index of the value to be read in {@link #b b}. * @return the read value. */ public short readShort(final int index) { @@ -2062,7 +2037,8 @@ public class ClassReader { * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters.</i> * - * @param index the start index of the value to be read in {@link #b b}. + * @param index + * the start index of the value to be read in {@link #b b}. * @return the read value. */ public int readInt(final int index) { @@ -2072,11 +2048,12 @@ public class ClassReader { } /** - * Reads a signed long value in {@link #b b}. <i>This method is intended - * for {@link Attribute} sub classes, and is normally not needed by class + * Reads a signed long value in {@link #b b}. <i>This method is intended for + * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters.</i> * - * @param index the start index of the value to be read in {@link #b b}. + * @param index + * the start index of the value to be read in {@link #b b}. * @return the read value. */ public long readLong(final int index) { @@ -2090,14 +2067,19 @@ public class ClassReader { * is intended for {@link Attribute} sub classes, and is normally not needed * by class generators or adapters.</i> * - * @param index the start index of an unsigned short value in {@link #b b}, - * whose value is the index of an UTF8 constant pool item. - * @param buf buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. + * @param index + * the start index of an unsigned short value in {@link #b b}, + * whose value is the index of an UTF8 constant pool item. + * @param buf + * buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. * @return the String corresponding to the specified UTF8 item. */ public String readUTF8(int index, final char[] buf) { int item = readUnsignedShort(index); + if (index == 0 || item == 0) { + return null; + } String s = strings[item]; if (s != null) { return s; @@ -2109,10 +2091,13 @@ public class ClassReader { /** * Reads UTF8 string in {@link #b b}. * - * @param index start offset of the UTF8 string to be read. - * @param utfLen length of the UTF8 string to be read. - * @param buf buffer to be used to read the string. This buffer must be - * sufficiently large. It is not automatically resized. + * @param index + * start offset of the UTF8 string to be read. + * @param utfLen + * length of the UTF8 string to be read. + * @param buf + * buffer to be used to read the string. This buffer must be + * sufficiently large. It is not automatically resized. * @return the String corresponding to the specified UTF8 string. */ private String readUTF(int index, final int utfLen, final char[] buf) { @@ -2125,28 +2110,28 @@ public class ClassReader { while (index < endIndex) { c = b[index++]; switch (st) { - case 0: - c = c & 0xFF; - if (c < 0x80) { // 0xxxxxxx - buf[strLen++] = (char) c; - } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx - cc = (char) (c & 0x1F); - st = 1; - } else { // 1110 xxxx 10xx xxxx 10xx xxxx - cc = (char) (c & 0x0F); - st = 2; - } - break; + case 0: + c = c & 0xFF; + if (c < 0x80) { // 0xxxxxxx + buf[strLen++] = (char) c; + } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx + cc = (char) (c & 0x1F); + st = 1; + } else { // 1110 xxxx 10xx xxxx 10xx xxxx + cc = (char) (c & 0x0F); + st = 2; + } + break; - case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char - buf[strLen++] = (char) ((cc << 6) | (c & 0x3F)); - st = 0; - break; + case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char + buf[strLen++] = (char) ((cc << 6) | (c & 0x3F)); + st = 0; + break; - case 2: // byte 2 of 3-byte char - cc = (char) ((cc << 6) | (c & 0x3F)); - st = 1; - break; + case 2: // byte 2 of 3-byte char + cc = (char) ((cc << 6) | (c & 0x3F)); + st = 1; + break; } } return new String(buf, 0, strLen); @@ -2157,10 +2142,12 @@ public class ClassReader { * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters.</i> * - * @param index the start index of an unsigned short value in {@link #b b}, - * whose value is the index of a class constant pool item. - * @param buf buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. + * @param index + * the start index of an unsigned short value in {@link #b b}, + * whose value is the index of a class constant pool item. + * @param buf + * buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. * @return the String corresponding to the specified class item. */ public String readClass(final int index, final char[] buf) { @@ -2175,9 +2162,11 @@ public class ClassReader { * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters.</i> * - * @param item the index of a constant pool item. - * @param buf buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. + * @param item + * the index of a constant pool item. + * @param buf + * buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, * {@link String}, {@link Type} or {@link Handle} corresponding to * the given constant pool item. @@ -2185,32 +2174,29 @@ public class ClassReader { 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)); - case ClassWriter.FLOAT: - return new Float(Float.intBitsToFloat(readInt(index))); - case ClassWriter.LONG: - return new Long(readLong(index)); - case ClassWriter.DOUBLE: - return new Double(Double.longBitsToDouble(readLong(index))); - case ClassWriter.CLASS: - return Type.getObjectType(readUTF8(index, buf)); - case ClassWriter.STR: - return readUTF8(index, buf); - case ClassWriter.MTYPE: - return Type.getMethodType(readUTF8(index, buf)); - - //case ClassWriter.HANDLE_BASE + [1..9]: - default: { - int tag = readByte(index); - int[] items = this.items; - int cpIndex = items[readUnsignedShort(index + 1)]; - String owner = readClass(cpIndex, buf); - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String name = readUTF8(cpIndex, buf); - String desc = readUTF8(cpIndex + 2, buf); - return new Handle(tag, owner, name, desc); - } + case ClassWriter.INT: + return new Integer(readInt(index)); + case ClassWriter.FLOAT: + return new Float(Float.intBitsToFloat(readInt(index))); + case ClassWriter.LONG: + return new Long(readLong(index)); + case ClassWriter.DOUBLE: + return new Double(Double.longBitsToDouble(readLong(index))); + case ClassWriter.CLASS: + return Type.getObjectType(readUTF8(index, buf)); + case ClassWriter.STR: + return readUTF8(index, buf); + case ClassWriter.MTYPE: + return Type.getMethodType(readUTF8(index, buf)); + default: // case ClassWriter.HANDLE_BASE + [1..9]: + int tag = readByte(index); + int[] items = this.items; + int cpIndex = items[readUnsignedShort(index + 1)]; + String owner = readClass(cpIndex, buf); + cpIndex = items[readUnsignedShort(cpIndex + 2)]; + String name = readUTF8(cpIndex, buf); + String desc = readUTF8(cpIndex + 2, buf); + return new Handle(tag, owner, name, desc); } } } diff --git a/src/asm/scala/tools/asm/ClassVisitor.java b/src/asm/scala/tools/asm/ClassVisitor.java index ae38ae0ab9..3fc364d5e5 100644 --- a/src/asm/scala/tools/asm/ClassVisitor.java +++ b/src/asm/scala/tools/asm/ClassVisitor.java @@ -30,11 +30,11 @@ package scala.tools.asm; /** - * A visitor to visit a Java class. The methods of this class must be called - * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [ + * A visitor to visit a Java class. The methods of this class must be called in + * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [ * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | - * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> | - * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>. + * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> | <tt>visitField</tt> | + * <tt>visitMethod</tt> )* <tt>visitEnd</tt>. * * @author Eric Bruneton */ @@ -55,8 +55,9 @@ public abstract class ClassVisitor { /** * Constructs a new {@link ClassVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. */ public ClassVisitor(final int api) { this(api, null); @@ -65,15 +66,17 @@ public abstract class ClassVisitor { /** * Constructs a new {@link ClassVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param cv the class visitor to which this visitor must delegate method - * calls. May be null. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param cv + * the class visitor to which this visitor must delegate method + * calls. May be null. */ public ClassVisitor(final int api, final ClassVisitor cv) { - /*if (api != Opcodes.ASM4) { + if (api != Opcodes.ASM4) { throw new IllegalArgumentException(); - }*/ + } this.api = api; this.cv = cv; } @@ -81,30 +84,30 @@ public abstract class ClassVisitor { /** * Visits the header of the class. * - * @param version the class version. - * @param access the class's access flags (see {@link Opcodes}). This - * parameter also indicates if the class is deprecated. - * @param name the internal name of the class (see - * {@link Type#getInternalName() getInternalName}). - * @param signature the signature of this class. May be <tt>null</tt> if - * the class is not a generic one, and does not extend or implement - * generic classes or interfaces. - * @param superName the internal of name of the super class (see - * {@link Type#getInternalName() getInternalName}). For interfaces, - * the super class is {@link Object}. May be <tt>null</tt>, but - * only for the {@link Object} class. - * @param interfaces the internal names of the class's interfaces (see - * {@link Type#getInternalName() getInternalName}). May be - * <tt>null</tt>. + * @param version + * the class version. + * @param access + * the class's access flags (see {@link Opcodes}). This parameter + * also indicates if the class is deprecated. + * @param name + * the internal name of the class (see + * {@link Type#getInternalName() getInternalName}). + * @param signature + * the signature of this class. May be <tt>null</tt> if the class + * is not a generic one, and does not extend or implement generic + * classes or interfaces. + * @param superName + * the internal of name of the super class (see + * {@link Type#getInternalName() getInternalName}). For + * interfaces, the super class is {@link Object}. May be + * <tt>null</tt>, but only for the {@link Object} class. + * @param interfaces + * the internal names of the class's interfaces (see + * {@link Type#getInternalName() getInternalName}). May be + * <tt>null</tt>. */ - public void visit( - int version, - int access, - String name, - String signature, - String superName, - String[] interfaces) - { + public void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { if (cv != null) { cv.visit(version, access, name, signature, superName, interfaces); } @@ -113,11 +116,13 @@ public abstract class ClassVisitor { /** * Visits the source of the class. * - * @param source the name of the source file from which the class was - * compiled. May be <tt>null</tt>. - * @param debug additional debug information to compute the correspondance - * between source and compiled elements of the class. May be - * <tt>null</tt>. + * @param source + * the name of the source file from which the class was compiled. + * May be <tt>null</tt>. + * @param debug + * additional debug information to compute the correspondance + * between source and compiled elements of the class. May be + * <tt>null</tt>. */ public void visitSource(String source, String debug) { if (cv != null) { @@ -129,16 +134,19 @@ public abstract class ClassVisitor { * Visits the enclosing class of the class. This method must be called only * if the class has an enclosing class. * - * @param owner internal name of the enclosing class of the class. - * @param name the name of the method that contains the class, or - * <tt>null</tt> if the class is not enclosed in a method of its - * enclosing class. - * @param desc the descriptor of the method that contains the class, or - * <tt>null</tt> if the class is not enclosed in a method of its - * enclosing class. + * @param owner + * internal name of the enclosing class of the class. + * @param name + * the name of the method that contains the class, or + * <tt>null</tt> if the class is not enclosed in a method of its + * enclosing class. + * @param desc + * the descriptor of the method that contains the class, or + * <tt>null</tt> if the class is not enclosed in a method of its + * enclosing class. */ public void visitOuterClass(String owner, String name, String desc) { - if (cv != null) { + if (cv != null) { cv.visitOuterClass(owner, name, desc); } } @@ -146,8 +154,10 @@ public abstract class ClassVisitor { /** * Visits an annotation of the class. * - * @param desc the class descriptor of the annotation class. - * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * <tt>true</tt> if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or <tt>null</tt> if * this visitor is not interested in visiting this annotation. */ @@ -161,7 +171,8 @@ public abstract class ClassVisitor { /** * Visits a non standard attribute of the class. * - * @param attr an attribute. + * @param attr + * an attribute. */ public void visitAttribute(Attribute attr) { if (cv != null) { @@ -173,23 +184,22 @@ public abstract class ClassVisitor { * Visits information about an inner class. This inner class is not * necessarily a member of the class being visited. * - * @param name the internal name of an inner class (see - * {@link Type#getInternalName() getInternalName}). - * @param outerName the internal name of the class to which the inner class - * belongs (see {@link Type#getInternalName() getInternalName}). May - * be <tt>null</tt> for not member classes. - * @param innerName the (simple) name of the inner class inside its - * enclosing class. May be <tt>null</tt> for anonymous inner - * classes. - * @param access the access flags of the inner class as originally declared - * in the enclosing class. + * @param name + * the internal name of an inner class (see + * {@link Type#getInternalName() getInternalName}). + * @param outerName + * the internal name of the class to which the inner class + * belongs (see {@link Type#getInternalName() getInternalName}). + * May be <tt>null</tt> for not member classes. + * @param innerName + * the (simple) name of the inner class inside its enclosing + * class. May be <tt>null</tt> for anonymous inner classes. + * @param access + * the access flags of the inner class as originally declared in + * the enclosing class. */ - public void visitInnerClass( - String name, - String outerName, - String innerName, - int access) - { + public void visitInnerClass(String name, String outerName, + String innerName, int access) { if (cv != null) { cv.visitInnerClass(name, outerName, innerName, access); } @@ -198,33 +208,32 @@ public abstract class ClassVisitor { /** * Visits a field of the class. * - * @param access the field's access flags (see {@link Opcodes}). This - * parameter also indicates if the field is synthetic and/or - * deprecated. - * @param name the field's name. - * @param desc the field's descriptor (see {@link Type Type}). - * @param signature the field's signature. May be <tt>null</tt> if the - * field's type does not use generic types. - * @param value the field's initial value. This parameter, which may be - * <tt>null</tt> if the field does not have an initial value, must - * be an {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double} or a {@link String} (for <tt>int</tt>, - * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields - * respectively). <i>This parameter is only used for static fields</i>. - * Its value is ignored for non static fields, which must be - * initialized through bytecode instructions in constructors or - * methods. + * @param access + * the field's access flags (see {@link Opcodes}). This parameter + * also indicates if the field is synthetic and/or deprecated. + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link Type Type}). + * @param signature + * the field's signature. May be <tt>null</tt> if the field's + * type does not use generic types. + * @param value + * the field's initial value. This parameter, which may be + * <tt>null</tt> if the field does not have an initial value, + * must be an {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} or a {@link String} (for <tt>int</tt>, + * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields + * respectively). <i>This parameter is only used for static + * fields</i>. Its value is ignored for non static fields, which + * must be initialized through bytecode instructions in + * constructors or methods. * @return a visitor to visit field annotations and attributes, or - * <tt>null</tt> if this class visitor is not interested in - * visiting these annotations and attributes. + * <tt>null</tt> if this class visitor is not interested in visiting + * these annotations and attributes. */ - public FieldVisitor visitField( - int access, - String name, - String desc, - String signature, - Object value) - { + public FieldVisitor visitField(int access, String name, String desc, + String signature, Object value) { if (cv != null) { return cv.visitField(access, name, desc, signature, value); } @@ -233,31 +242,31 @@ public abstract class ClassVisitor { /** * Visits a method of the class. This method <i>must</i> return a new - * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is - * called, i.e., it should not return a previously returned visitor. + * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called, + * i.e., it should not return a previously returned visitor. * - * @param access the method's access flags (see {@link Opcodes}). This - * parameter also indicates if the method is synthetic and/or - * deprecated. - * @param name the method's name. - * @param desc the method's descriptor (see {@link Type Type}). - * @param signature the method's signature. May be <tt>null</tt> if the - * method parameters, return type and exceptions do not use generic - * types. - * @param exceptions the internal names of the method's exception classes - * (see {@link Type#getInternalName() getInternalName}). May be - * <tt>null</tt>. + * @param access + * the method's access flags (see {@link Opcodes}). This + * parameter also indicates if the method is synthetic and/or + * deprecated. + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param signature + * the method's signature. May be <tt>null</tt> if the method + * parameters, return type and exceptions do not use generic + * types. + * @param exceptions + * the internal names of the method's exception classes (see + * {@link Type#getInternalName() getInternalName}). May be + * <tt>null</tt>. * @return an object to visit the byte code of the method, or <tt>null</tt> * if this class visitor is not interested in visiting the code of * this method. */ - public MethodVisitor visitMethod( - int access, - String name, - String desc, - String signature, - String[] exceptions) - { + public MethodVisitor visitMethod(int access, String name, String desc, + String signature, String[] exceptions) { if (cv != null) { return cv.visitMethod(access, name, desc, signature, exceptions); } diff --git a/src/asm/scala/tools/asm/ClassWriter.java b/src/asm/scala/tools/asm/ClassWriter.java index c7a0736b51..93ed7313c7 100644 --- a/src/asm/scala/tools/asm/ClassWriter.java +++ b/src/asm/scala/tools/asm/ClassWriter.java @@ -66,12 +66,18 @@ public class ClassWriter extends ClassVisitor { public static final int COMPUTE_FRAMES = 2; /** - * Pseudo access flag to distinguish between the synthetic attribute and - * the synthetic access flag. + * Pseudo access flag to distinguish between the synthetic attribute and the + * synthetic access flag. */ static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000; /** + * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC. + */ + static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE + / Opcodes.ACC_SYNTHETIC; + + /** * The type of instructions without any argument. */ static final int NOARG_INSN = 0; @@ -238,8 +244,8 @@ public class ClassWriter extends ClassVisitor { /** * The base value for all CONSTANT_MethodHandle constant pool items. - * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into - * 9 different items. + * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9 + * different items. */ static final int HANDLE_BASE = 20; @@ -266,9 +272,8 @@ public class ClassWriter extends ClassVisitor { static final int TYPE_MERGED = 32; /** - * The type of BootstrapMethods items. These items are stored in a - * special class attribute named BootstrapMethods and - * not in the constant pool. + * The type of BootstrapMethods items. These items are stored in a special + * class attribute named BootstrapMethods and not in the constant pool. */ static final int BSM = 33; @@ -327,10 +332,10 @@ public class ClassWriter extends ClassVisitor { * necessarily be stored in the constant pool. This type table is used by * the control flow and data flow analysis algorithm used to compute stack * map frames from scratch. This array associates to each index <tt>i</tt> - * the Item whose index is <tt>i</tt>. All Item objects stored in this - * array are also stored in the {@link #items} hash table. These two arrays - * allow to retrieve an Item from its index or, conversely, to get the index - * of an Item from its value. Each Item stores an internal name in its + * the Item whose index is <tt>i</tt>. All Item objects stored in this array + * are also stored in the {@link #items} hash table. These two arrays allow + * to retrieve an Item from its index or, conversely, to get the index of an + * Item from its value. Each Item stores an internal name in its * {@link Item#strVal1} field. */ Item[] typeTable; @@ -439,16 +444,16 @@ public class ClassWriter extends ClassVisitor { /** * The fields of this class. These fields are stored in a linked list of * {@link FieldWriter} objects, linked to each other by their - * {@link FieldWriter#fv} field. This field stores the first element of - * this list. + * {@link FieldWriter#fv} field. This field stores the first element of this + * list. */ FieldWriter firstField; /** * The fields of this class. These fields are stored in a linked list of * {@link FieldWriter} objects, linked to each other by their - * {@link FieldWriter#fv} field. This field stores the last element of - * this list. + * {@link FieldWriter#fv} field. This field stores the last element of this + * list. */ FieldWriter lastField; @@ -463,8 +468,8 @@ public class ClassWriter extends ClassVisitor { /** * The methods of this class. These methods are stored in a linked list of * {@link MethodWriter} objects, linked to each other by their - * {@link MethodWriter#mv} field. This field stores the last element of - * this list. + * {@link MethodWriter#mv} field. This field stores the last element of this + * list. */ MethodWriter lastMethod; @@ -584,8 +589,10 @@ public class ClassWriter extends ClassVisitor { /** * Constructs a new {@link ClassWriter} object. * - * @param flags option flags that can be used to modify the default behavior - * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}. + * @param flags + * option flags that can be used to modify the default behavior + * of this class. See {@link #COMPUTE_MAXS}, + * {@link #COMPUTE_FRAMES}. */ public ClassWriter(final int flags) { super(Opcodes.ASM4); @@ -606,26 +613,32 @@ public class ClassWriter extends ClassVisitor { * "mostly add" bytecode transformations. These optimizations are the * following: * - * <ul> <li>The constant pool from the original class is copied as is in the - * new class, which saves time. New constant pool entries will be added at - * the end if necessary, but unused constant pool entries <i>won't be - * removed</i>.</li> <li>Methods that are not transformed are copied as is - * in the new class, directly from the original class bytecode (i.e. without - * emitting visit events for all the method instructions), which saves a - * <i>lot</i> of time. Untransformed methods are detected by the fact that - * the {@link ClassReader} receives {@link MethodVisitor} objects that come - * from a {@link ClassWriter} (and not from any other {@link ClassVisitor} - * instance).</li> </ul> + * <ul> + * <li>The constant pool from the original class is copied as is in the new + * class, which saves time. New constant pool entries will be added at the + * end if necessary, but unused constant pool entries <i>won't be + * removed</i>.</li> + * <li>Methods that are not transformed are copied as is in the new class, + * directly from the original class bytecode (i.e. without emitting visit + * events for all the method instructions), which saves a <i>lot</i> of + * time. Untransformed methods are detected by the fact that the + * {@link ClassReader} receives {@link MethodVisitor} objects that come from + * a {@link ClassWriter} (and not from any other {@link ClassVisitor} + * instance).</li> + * </ul> * - * @param classReader the {@link ClassReader} used to read the original - * class. It will be used to copy the entire constant pool from the - * original class and also to copy other fragments of original - * bytecode where applicable. - * @param flags option flags that can be used to modify the default behavior - * of this class. <i>These option flags do not affect methods that - * are copied as is in the new class. This means that the maximum - * stack size nor the stack frames will be computed for these - * methods</i>. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}. + * @param classReader + * the {@link ClassReader} used to read the original class. It + * will be used to copy the entire constant pool from the + * original class and also to copy other fragments of original + * bytecode where applicable. + * @param flags + * option flags that can be used to modify the default behavior + * of this class. <i>These option flags do not affect methods + * that are copied as is in the new class. This means that the + * maximum stack size nor the stack frames will be computed for + * these methods</i>. See {@link #COMPUTE_MAXS}, + * {@link #COMPUTE_FRAMES}. */ public ClassWriter(final ClassReader classReader, final int flags) { this(flags); @@ -638,14 +651,9 @@ public class ClassWriter extends ClassVisitor { // ------------------------------------------------------------------------ @Override - public final void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces) - { + public final void visit(final int version, final int access, + final String name, final String signature, final String superName, + final String[] interfaces) { this.version = version; this.access = access; this.name = newClass(name); @@ -674,11 +682,8 @@ public class ClassWriter extends ClassVisitor { } @Override - public final void visitOuterClass( - final String owner, - final String name, - final String desc) - { + public final void visitOuterClass(final String owner, final String name, + final String desc) { enclosingMethodOwner = newClass(owner); if (name != null && desc != null) { enclosingMethod = newNameType(name, desc); @@ -686,10 +691,8 @@ public class ClassWriter extends ClassVisitor { } @Override - public final AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public final AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } @@ -714,12 +717,8 @@ public class ClassWriter extends ClassVisitor { } @Override - public final void visitInnerClass( - final String name, - final String outerName, - final String innerName, - final int access) - { + public final void visitInnerClass(final String name, + final String outerName, final String innerName, final int access) { if (innerClasses == null) { innerClasses = new ByteVector(); } @@ -731,32 +730,16 @@ public class ClassWriter extends ClassVisitor { } @Override - public final FieldVisitor visitField( - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { + public final FieldVisitor visitField(final int access, final String name, + final String desc, final String signature, final Object value) { return new FieldWriter(this, access, name, desc, signature, value); } @Override - public final MethodVisitor visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { - return new MethodWriter(this, - access, - name, - desc, - signature, - exceptions, - computeMaxs, - computeFrames); + public final MethodVisitor visitMethod(final int access, final String name, + final String desc, final String signature, final String[] exceptions) { + return new MethodWriter(this, access, name, desc, signature, + exceptions, computeMaxs, computeFrames); } @Override @@ -773,7 +756,7 @@ public class ClassWriter extends ClassVisitor { * @return the bytecode of the class that was build with this class writer. */ public byte[] toByteArray() { - if (index > Short.MAX_VALUE) { + if (index > 0xFFFF) { throw new RuntimeException("Class file too large!"); } // computes the real size of the bytecode of this class @@ -793,8 +776,9 @@ public class ClassWriter extends ClassVisitor { mb = (MethodWriter) mb.mv; } int attributeCount = 0; - if (bootstrapMethods != null) { // we put it as first argument in order - // to improve a bit ClassReader.copyBootstrapMethods + if (bootstrapMethods != null) { + // we put it as first attribute in order to improve a bit + // ClassReader.copyBootstrapMethods ++attributeCount; size += 8 + bootstrapMethods.length; newUTF8("BootstrapMethods"); @@ -824,12 +808,13 @@ public class ClassWriter extends ClassVisitor { size += 6; newUTF8("Deprecated"); } - if ((access & Opcodes.ACC_SYNTHETIC) != 0 - && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0)) - { - ++attributeCount; - size += 6; - newUTF8("Synthetic"); + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((version & 0xFFFF) < Opcodes.V1_5 + || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { + ++attributeCount; + size += 6; + newUTF8("Synthetic"); + } } if (innerClasses != null) { ++attributeCount; @@ -856,9 +841,8 @@ public class ClassWriter extends ClassVisitor { ByteVector out = new ByteVector(size); out.putInt(0xCAFEBABE).putInt(version); out.putShort(index).putByteArray(pool.data, 0, pool.length); - int mask = Opcodes.ACC_DEPRECATED - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC)); + int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE + | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC); out.putShort(access & ~mask).putShort(name).putShort(superName); out.putShort(interfaceCount); for (int i = 0; i < interfaceCount; ++i) { @@ -877,9 +861,10 @@ public class ClassWriter extends ClassVisitor { mb = (MethodWriter) mb.mv; } out.putShort(attributeCount); - if (bootstrapMethods != null) { // should be the first class attribute ? + if (bootstrapMethods != null) { out.putShort(newUTF8("BootstrapMethods")); - out.putInt(bootstrapMethods.length + 2).putShort(bootstrapMethodsCount); + out.putInt(bootstrapMethods.length + 2).putShort( + bootstrapMethodsCount); out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); } if (ClassReader.SIGNATURES && signature != 0) { @@ -900,10 +885,11 @@ public class ClassWriter extends ClassVisitor { if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(newUTF8("Deprecated")).putInt(0); } - if ((access & Opcodes.ACC_SYNTHETIC) != 0 - && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0)) - { - out.putShort(newUTF8("Synthetic")).putInt(0); + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((version & 0xFFFF) < Opcodes.V1_5 + || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { + out.putShort(newUTF8("Synthetic")).putInt(0); + } } if (innerClasses != null) { out.putShort(newUTF8("InnerClasses")); @@ -937,10 +923,11 @@ public class ClassWriter extends ClassVisitor { * Adds a number or string constant to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * - * @param cst the value of the constant to be added to the constant pool. - * This parameter must be an {@link Integer}, a {@link Float}, a - * {@link Long}, a {@link Double}, a {@link String} or a - * {@link Type}. + * @param cst + * the value of the constant to be added to the constant pool. + * This parameter must be an {@link Integer}, a {@link Float}, a + * {@link Long}, a {@link Double}, a {@link String} or a + * {@link Type}. * @return a new or already existing constant item with the given value. */ Item newConstItem(final Object cst) { @@ -973,12 +960,12 @@ public class ClassWriter extends ClassVisitor { } else if (cst instanceof Type) { Type t = (Type) cst; int s = t.getSort(); - if (s == Type.ARRAY) { - return newClassItem(t.getDescriptor()); - } else if (s == Type.OBJECT) { + if (s == Type.OBJECT) { return newClassItem(t.getInternalName()); - } else { // s == Type.METHOD + } else if (s == Type.METHOD) { return newMethodTypeItem(t.getDescriptor()); + } else { // s == primitive type or array + return newClassItem(t.getDescriptor()); } } else if (cst instanceof Handle) { Handle h = (Handle) cst; @@ -994,9 +981,10 @@ public class ClassWriter extends ClassVisitor { * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param cst the value of the constant to be added to the constant pool. - * This parameter must be an {@link Integer}, a {@link Float}, a - * {@link Long}, a {@link Double} or a {@link String}. + * @param cst + * the value of the constant to be added to the constant pool. + * This parameter must be an {@link Integer}, a {@link Float}, a + * {@link Long}, a {@link Double} or a {@link String}. * @return the index of a new or already existing constant item with the * given value. */ @@ -1010,7 +998,8 @@ public class ClassWriter extends ClassVisitor { * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters.</i> * - * @param value the String value. + * @param value + * the String value. * @return the index of a new or already existing UTF8 item. */ public int newUTF8(final String value) { @@ -1030,7 +1019,8 @@ public class ClassWriter extends ClassVisitor { * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param value the internal name of the class. + * @param value + * the internal name of the class. * @return a new or already existing class reference item. */ Item newClassItem(final String value) { @@ -1050,7 +1040,8 @@ public class ClassWriter extends ClassVisitor { * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param value the internal name of the class. + * @param value + * the internal name of the class. * @return the index of a new or already existing class reference item. */ public int newClass(final String value) { @@ -1063,7 +1054,8 @@ public class ClassWriter extends ClassVisitor { * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param methodDesc method descriptor of the method type. + * @param methodDesc + * method descriptor of the method type. * @return a new or already existing method type reference item. */ Item newMethodTypeItem(final String methodDesc) { @@ -1083,7 +1075,8 @@ public class ClassWriter extends ClassVisitor { * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param methodDesc method descriptor of the method type. + * @param methodDesc + * method descriptor of the method type. * @return the index of a new or already existing method type reference * item. */ @@ -1097,33 +1090,34 @@ public class ClassWriter extends ClassVisitor { * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters.</i> * - * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, - * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, - * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, - * {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - * @param owner the internal name of the field or method owner class. - * @param name the name of the field or method. - * @param desc the descriptor of the field or method. + * @param tag + * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, + * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, + * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the field or method owner class. + * @param name + * the name of the field or method. + * @param desc + * the descriptor of the field or method. * @return a new or an already existing method type reference item. */ - Item newHandleItem( - final int tag, - final String owner, - final String name, - final String desc) - { + Item newHandleItem(final int tag, final String owner, final String name, + final String desc) { key4.set(HANDLE_BASE + tag, owner, name, desc); Item result = get(key4); if (result == null) { if (tag <= Opcodes.H_PUTSTATIC) { put112(HANDLE, tag, newField(owner, name, desc)); } else { - put112(HANDLE, tag, newMethod(owner, - name, - desc, - tag == Opcodes.H_INVOKEINTERFACE)); + put112(HANDLE, + tag, + newMethod(owner, name, desc, + tag == Opcodes.H_INVOKEINTERFACE)); } result = new Item(index++, key4); put(result); @@ -1132,29 +1126,30 @@ public class ClassWriter extends ClassVisitor { } /** - * Adds a handle to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> + * Adds a handle to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. <i>This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters.</i> * - * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, - * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, - * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, - * {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - * @param owner the internal name of the field or method owner class. - * @param name the name of the field or method. - * @param desc the descriptor of the field or method. + * @param tag + * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, + * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, + * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the field or method owner class. + * @param name + * the name of the field or method. + * @param desc + * the descriptor of the field or method. * @return the index of a new or already existing method type reference * item. */ - public int newHandle( - final int tag, - final String owner, - final String name, - final String desc) - { + public int newHandle(final int tag, final String owner, final String name, + final String desc) { return newHandleItem(tag, owner, name, desc).index; } @@ -1164,19 +1159,19 @@ public class ClassWriter extends ClassVisitor { * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param name name of the invoked method. - * @param desc descriptor of the invoke method. - * @param bsm the bootstrap method. - * @param bsmArgs the bootstrap method constant arguments. + * @param name + * name of the invoked method. + * @param desc + * descriptor of the invoke method. + * @param bsm + * the bootstrap method. + * @param bsmArgs + * the bootstrap method constant arguments. * * @return a new or an already existing invokedynamic type reference item. */ - Item newInvokeDynamicItem( - final String name, - final String desc, - final Handle bsm, - final Object... bsmArgs) - { + Item newInvokeDynamicItem(final String name, final String desc, + final Handle bsm, final Object... bsmArgs) { // cache for performance ByteVector bootstrapMethods = this.bootstrapMethods; if (bootstrapMethods == null) { @@ -1186,9 +1181,7 @@ public class ClassWriter extends ClassVisitor { int position = bootstrapMethods.length; // record current position int hashCode = bsm.hashCode(); - bootstrapMethods.putShort(newHandle(bsm.tag, - bsm.owner, - bsm.name, + bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name, bsm.desc)); int argsLength = bsmArgs.length; @@ -1250,20 +1243,20 @@ public class ClassWriter extends ClassVisitor { * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param name name of the invoked method. - * @param desc descriptor of the invoke method. - * @param bsm the bootstrap method. - * @param bsmArgs the bootstrap method constant arguments. + * @param name + * name of the invoked method. + * @param desc + * descriptor of the invoke method. + * @param bsm + * the bootstrap method. + * @param bsmArgs + * the bootstrap method constant arguments. * - * @return the index of a new or already existing invokedynamic - * reference item. - */ - public int newInvokeDynamic( - final String name, - final String desc, - final Handle bsm, - final Object... bsmArgs) - { + * @return the index of a new or already existing invokedynamic reference + * item. + */ + public int newInvokeDynamic(final String name, final String desc, + final Handle bsm, final Object... bsmArgs) { return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index; } @@ -1271,13 +1264,15 @@ public class ClassWriter extends ClassVisitor { * Adds a field reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. * - * @param owner the internal name of the field's owner class. - * @param name the field's name. - * @param desc the field's descriptor. + * @param owner + * the internal name of the field's owner class. + * @param name + * the field's name. + * @param desc + * the field's descriptor. * @return a new or already existing field reference item. */ - Item newFieldItem(final String owner, final String name, final String desc) - { + Item newFieldItem(final String owner, final String name, final String desc) { key3.set(FIELD, owner, name, desc); Item result = get(key3); if (result == null) { @@ -1294,13 +1289,15 @@ public class ClassWriter extends ClassVisitor { * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param owner the internal name of the field's owner class. - * @param name the field's name. - * @param desc the field's descriptor. + * @param owner + * the internal name of the field's owner class. + * @param name + * the field's name. + * @param desc + * the field's descriptor. * @return the index of a new or already existing field reference item. */ - public int newField(final String owner, final String name, final String desc) - { + public int newField(final String owner, final String name, final String desc) { return newFieldItem(owner, name, desc).index; } @@ -1308,18 +1305,18 @@ public class ClassWriter extends ClassVisitor { * Adds a method reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. * - * @param owner the internal name of the method's owner class. - * @param name the method's name. - * @param desc the method's descriptor. - * @param itf <tt>true</tt> if <tt>owner</tt> is an interface. + * @param owner + * the internal name of the method's owner class. + * @param name + * the method's name. + * @param desc + * the method's descriptor. + * @param itf + * <tt>true</tt> if <tt>owner</tt> is an interface. * @return a new or already existing method reference item. */ - Item newMethodItem( - final String owner, - final String name, - final String desc, - final boolean itf) - { + Item newMethodItem(final String owner, final String name, + final String desc, final boolean itf) { int type = itf ? IMETH : METH; key3.set(type, owner, name, desc); Item result = get(key3); @@ -1337,18 +1334,18 @@ public class ClassWriter extends ClassVisitor { * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * - * @param owner the internal name of the method's owner class. - * @param name the method's name. - * @param desc the method's descriptor. - * @param itf <tt>true</tt> if <tt>owner</tt> is an interface. + * @param owner + * the internal name of the method's owner class. + * @param name + * the method's name. + * @param desc + * the method's descriptor. + * @param itf + * <tt>true</tt> if <tt>owner</tt> is an interface. * @return the index of a new or already existing method reference item. */ - public int newMethod( - final String owner, - final String name, - final String desc, - final boolean itf) - { + public int newMethod(final String owner, final String name, + final String desc, final boolean itf) { return newMethodItem(owner, name, desc, itf).index; } @@ -1356,7 +1353,8 @@ public class ClassWriter extends ClassVisitor { * Adds an integer to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. * - * @param value the int value. + * @param value + * the int value. * @return a new or already existing int item. */ Item newInteger(final int value) { @@ -1374,7 +1372,8 @@ public class ClassWriter extends ClassVisitor { * Adds a float to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * - * @param value the float value. + * @param value + * the float value. * @return a new or already existing float item. */ Item newFloat(final float value) { @@ -1392,7 +1391,8 @@ public class ClassWriter extends ClassVisitor { * Adds a long to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * - * @param value the long value. + * @param value + * the long value. * @return a new or already existing long item. */ Item newLong(final long value) { @@ -1411,7 +1411,8 @@ public class ClassWriter extends ClassVisitor { * Adds a double to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * - * @param value the double value. + * @param value + * the double value. * @return a new or already existing double item. */ Item newDouble(final double value) { @@ -1430,7 +1431,8 @@ public class ClassWriter extends ClassVisitor { * Adds a string to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * - * @param value the String value. + * @param value + * the String value. * @return a new or already existing string item. */ private Item newString(final String value) { @@ -1450,8 +1452,10 @@ public class ClassWriter extends ClassVisitor { * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters.</i> * - * @param name a name. - * @param desc a type descriptor. + * @param name + * a name. + * @param desc + * a type descriptor. * @return the index of a new or already existing name and type item. */ public int newNameType(final String name, final String desc) { @@ -1462,8 +1466,10 @@ public class ClassWriter extends ClassVisitor { * Adds a name and type to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. * - * @param name a name. - * @param desc a type descriptor. + * @param name + * a name. + * @param desc + * a type descriptor. * @return a new or already existing name and type item. */ Item newNameTypeItem(final String name, final String desc) { @@ -1481,7 +1487,8 @@ public class ClassWriter extends ClassVisitor { * Adds the given internal name to {@link #typeTable} and returns its index. * Does nothing if the type table already contains this internal name. * - * @param type the internal name to be added to the type table. + * @param type + * the internal name to be added to the type table. * @return the index of this internal name in the type table. */ int addType(final String type) { @@ -1498,9 +1505,11 @@ public class ClassWriter extends ClassVisitor { * index. This method is used for UNINITIALIZED types, made of an internal * name and a bytecode offset. * - * @param type the internal name to be added to the type table. - * @param offset the bytecode offset of the NEW instruction that created - * this UNINITIALIZED type value. + * @param type + * the internal name to be added to the type table. + * @param offset + * the bytecode offset of the NEW instruction that created this + * UNINITIALIZED type value. * @return the index of this internal name in the type table. */ int addUninitializedType(final String type, final int offset) { @@ -1518,7 +1527,8 @@ public class ClassWriter extends ClassVisitor { /** * Adds the given Item to {@link #typeTable}. * - * @param item the value to be added to the type table. + * @param item + * the value to be added to the type table. * @return the added Item, which a new Item instance with the same value as * the given Item. */ @@ -1544,8 +1554,10 @@ public class ClassWriter extends ClassVisitor { * {@link #items} hash table to speedup future calls with the same * parameters. * - * @param type1 index of an internal name in {@link #typeTable}. - * @param type2 index of an internal name in {@link #typeTable}. + * @param type1 + * index of an internal name in {@link #typeTable}. + * @param type2 + * index of an internal name in {@link #typeTable}. * @return the index of the common super type of the two given types. */ int getMergedType(final int type1, final int type2) { @@ -1572,13 +1584,14 @@ public class ClassWriter extends ClassVisitor { * that is currently being generated by this ClassWriter, which can of * course not be loaded since it is under construction. * - * @param type1 the internal name of a class. - * @param type2 the internal name of another class. + * @param type1 + * the internal name of a class. + * @param type2 + * the internal name of another class. * @return the internal name of the common super class of the two given * classes. */ - protected String getCommonSuperClass(final String type1, final String type2) - { + protected String getCommonSuperClass(final String type1, final String type2) { Class<?> c, d; ClassLoader classLoader = getClass().getClassLoader(); try { @@ -1607,7 +1620,8 @@ public class ClassWriter extends ClassVisitor { * Returns the constant pool's hash table item which is equal to the given * item. * - * @param key a constant pool item. + * @param key + * a constant pool item. * @return the constant pool's hash table item which is equal to the given * item, or <tt>null</tt> if there is no such item. */ @@ -1623,7 +1637,8 @@ public class ClassWriter extends ClassVisitor { * Puts the given item in the constant pool's hash table. The hash table * <i>must</i> not already contains this item. * - * @param i the item to be added to the constant pool's hash table. + * @param i + * the item to be added to the constant pool's hash table. */ private void put(final Item i) { if (index + typeCount > threshold) { @@ -1651,9 +1666,12 @@ public class ClassWriter extends ClassVisitor { /** * Puts one byte and two shorts into the constant pool. * - * @param b a byte. - * @param s1 a short. - * @param s2 another short. + * @param b + * a byte. + * @param s1 + * a short. + * @param s2 + * another short. */ private void put122(final int b, final int s1, final int s2) { pool.put12(b, s1).putShort(s2); @@ -1662,9 +1680,12 @@ public class ClassWriter extends ClassVisitor { /** * Puts two bytes and one short into the constant pool. * - * @param b1 a byte. - * @param b2 another byte. - * @param s a short. + * @param b1 + * a byte. + * @param b2 + * another byte. + * @param s + * a short. */ private void put112(final int b1, final int b2, final int s) { pool.put11(b1, b2).putShort(s); diff --git a/src/asm/scala/tools/asm/Context.java b/src/asm/scala/tools/asm/Context.java new file mode 100644 index 0000000000..7b3a2ad9dd --- /dev/null +++ b/src/asm/scala/tools/asm/Context.java @@ -0,0 +1,110 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package scala.tools.asm; + +/** + * Information about a class being parsed in a {@link ClassReader}. + * + * @author Eric Bruneton + */ +class Context { + + /** + * Prototypes of the attributes that must be parsed for this class. + */ + Attribute[] attrs; + + /** + * The {@link ClassReader} option flags for the parsing of this class. + */ + int flags; + + /** + * The buffer used to read strings. + */ + char[] buffer; + + /** + * The start index of each bootstrap method. + */ + int[] bootstrapMethods; + + /** + * The access flags of the method currently being parsed. + */ + int access; + + /** + * The name of the method currently being parsed. + */ + String name; + + /** + * The descriptor of the method currently being parsed. + */ + String desc; + + /** + * The offset of the latest stack map frame that has been parsed. + */ + int offset; + + /** + * The encoding of the latest stack map frame that has been parsed. + */ + int mode; + + /** + * The number of locals in the latest stack map frame that has been parsed. + */ + int localCount; + + /** + * The number locals in the latest stack map frame that has been parsed, + * minus the number of locals in the previous frame. + */ + int localDiff; + + /** + * The local values of the latest stack map frame that has been parsed. + */ + Object[] local; + + /** + * The stack size of the latest stack map frame that has been parsed. + */ + int stackCount; + + /** + * The stack values of the latest stack map frame that has been parsed. + */ + Object[] stack; +} diff --git a/src/asm/scala/tools/asm/FieldVisitor.java b/src/asm/scala/tools/asm/FieldVisitor.java index 9ac0f6236f..9171f331e5 100644 --- a/src/asm/scala/tools/asm/FieldVisitor.java +++ b/src/asm/scala/tools/asm/FieldVisitor.java @@ -30,9 +30,9 @@ package scala.tools.asm; /** - * A visitor to visit a Java field. The methods of this class must be called - * in the following order: ( <tt>visitAnnotation</tt> | - * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>. + * A visitor to visit a Java field. The methods of this class must be called in + * the following order: ( <tt>visitAnnotation</tt> | <tt>visitAttribute</tt> )* + * <tt>visitEnd</tt>. * * @author Eric Bruneton */ @@ -53,8 +53,9 @@ public abstract class FieldVisitor { /** * Constructs a new {@link FieldVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. */ public FieldVisitor(final int api) { this(api, null); @@ -63,15 +64,17 @@ public abstract class FieldVisitor { /** * Constructs a new {@link FieldVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param fv the field visitor to which this visitor must delegate method - * calls. May be null. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param fv + * the field visitor to which this visitor must delegate method + * calls. May be null. */ public FieldVisitor(final int api, final FieldVisitor fv) { - /*if (api != Opcodes.ASM4) { + if (api != Opcodes.ASM4) { throw new IllegalArgumentException(); - }*/ + } this.api = api; this.fv = fv; } @@ -79,8 +82,10 @@ public abstract class FieldVisitor { /** * Visits an annotation of the field. * - * @param desc the class descriptor of the annotation class. - * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * <tt>true</tt> if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or <tt>null</tt> if * this visitor is not interested in visiting this annotation. */ @@ -94,7 +99,8 @@ public abstract class FieldVisitor { /** * Visits a non standard attribute of the field. * - * @param attr an attribute. + * @param attr + * an attribute. */ public void visitAttribute(Attribute attr) { if (fv != null) { diff --git a/src/asm/scala/tools/asm/FieldWriter.java b/src/asm/scala/tools/asm/FieldWriter.java index 45ef6d0df3..02c6059b91 100644 --- a/src/asm/scala/tools/asm/FieldWriter.java +++ b/src/asm/scala/tools/asm/FieldWriter.java @@ -92,21 +92,21 @@ final class FieldWriter extends FieldVisitor { /** * Constructs a new {@link FieldWriter}. * - * @param cw the class writer to which this field must be added. - * @param access the field's access flags (see {@link Opcodes}). - * @param name the field's name. - * @param desc the field's descriptor (see {@link Type}). - * @param signature the field's signature. May be <tt>null</tt>. - * @param value the field's constant value. May be <tt>null</tt>. + * @param cw + * the class writer to which this field must be added. + * @param access + * the field's access flags (see {@link Opcodes}). + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link Type}). + * @param signature + * the field's signature. May be <tt>null</tt>. + * @param value + * the field's constant value. May be <tt>null</tt>. */ - FieldWriter( - final ClassWriter cw, - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { + FieldWriter(final ClassWriter cw, final int access, final String name, + final String desc, final String signature, final Object value) { super(Opcodes.ASM4); if (cw.firstField == null) { cw.firstField = this; @@ -131,10 +131,8 @@ final class FieldWriter extends FieldVisitor { // ------------------------------------------------------------------------ @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } @@ -177,11 +175,12 @@ final class FieldWriter extends FieldVisitor { cw.newUTF8("ConstantValue"); size += 8; } - if ((access & Opcodes.ACC_SYNTHETIC) != 0 - && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0)) - { - cw.newUTF8("Synthetic"); - size += 6; + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + cw.newUTF8("Synthetic"); + size += 6; + } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { cw.newUTF8("Deprecated"); @@ -208,21 +207,23 @@ final class FieldWriter extends FieldVisitor { /** * Puts the content of this field into the given byte vector. * - * @param out where the content of this field must be put. + * @param out + * where the content of this field must be put. */ void put(final ByteVector out) { - int mask = Opcodes.ACC_DEPRECATED - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC)); + final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; + int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); out.putShort(access & ~mask).putShort(name).putShort(desc); int attributeCount = 0; if (value != 0) { ++attributeCount; } - if ((access & Opcodes.ACC_SYNTHETIC) != 0 - && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0)) - { - ++attributeCount; + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + ++attributeCount; + } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; @@ -244,10 +245,11 @@ final class FieldWriter extends FieldVisitor { out.putShort(cw.newUTF8("ConstantValue")); out.putInt(2).putShort(value); } - if ((access & Opcodes.ACC_SYNTHETIC) != 0 - && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0)) - { - out.putShort(cw.newUTF8("Synthetic")).putInt(0); + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + out.putShort(cw.newUTF8("Synthetic")).putInt(0); + } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); diff --git a/src/asm/scala/tools/asm/Frame.java b/src/asm/scala/tools/asm/Frame.java index 387b56796d..bcc3e8450b 100644 --- a/src/asm/scala/tools/asm/Frame.java +++ b/src/asm/scala/tools/asm/Frame.java @@ -80,13 +80,13 @@ final class Frame { * table contains only internal type names (array type descriptors are * forbidden - dimensions must be represented through the DIM field). * - * The LONG and DOUBLE types are always represented by using two slots (LONG + - * TOP or DOUBLE + TOP), for local variable types as well as in the operand - * stack. This is necessary to be able to simulate DUPx_y instructions, - * whose effect would be dependent on the actual type values if types were - * always represented by a single slot in the stack (and this is not - * possible, since actual type values are not always known - cf LOCAL and - * STACK type kinds). + * The LONG and DOUBLE types are always represented by using two slots (LONG + * + TOP or DOUBLE + TOP), for local variable types as well as in the + * operand stack. This is necessary to be able to simulate DUPx_y + * instructions, whose effect would be dependent on the actual type values + * if types were always represented by a single slot in the stack (and this + * is not possible, since actual type values are not always known - cf LOCAL + * and STACK type kinds). */ /** @@ -117,9 +117,9 @@ final class Frame { /** * Flag used for LOCAL and STACK types. Indicates that if this type happens * to be a long or double type (during the computations of input frames), - * then it must be set to TOP because the second word of this value has - * been reused to store other data in the basic block. Hence the first word - * no longer stores a valid long or double value. + * then it must be set to TOP because the second word of this value has been + * reused to store other data in the basic block. Hence the first word no + * longer stores a valid long or double value. */ static final int TOP_IF_LONG_OR_DOUBLE = 0x800000; @@ -523,7 +523,8 @@ final class Frame { /** * Returns the output frame local variable type at the given index. * - * @param local the index of the local that must be returned. + * @param local + * the index of the local that must be returned. * @return the output frame local variable type at the given index. */ private int get(final int local) { @@ -545,8 +546,10 @@ final class Frame { /** * Sets the output frame local variable type at the given index. * - * @param local the index of the local that must be set. - * @param type the value of the local that must be set. + * @param local + * the index of the local that must be set. + * @param type + * the value of the local that must be set. */ private void set(final int local, final int type) { // creates and/or resizes the output local variables array if necessary @@ -566,7 +569,8 @@ final class Frame { /** * Pushes a new type onto the output frame stack. * - * @param type the type that must be pushed. + * @param type + * the type that must be pushed. */ private void push(final int type) { // creates and/or resizes the output stack array if necessary @@ -591,10 +595,12 @@ final class Frame { /** * Pushes a new type onto the output frame stack. * - * @param cw the ClassWriter to which this label belongs. - * @param desc the descriptor of the type to be pushed. Can also be a method - * descriptor (in this case this method pushes its return type onto - * the output frame stack). + * @param cw + * the ClassWriter to which this label belongs. + * @param desc + * the descriptor of the type to be pushed. Can also be a method + * descriptor (in this case this method pushes its return type + * onto the output frame stack). */ private void push(final ClassWriter cw, final String desc) { int type = type(cw, desc); @@ -609,72 +615,74 @@ final class Frame { /** * Returns the int encoding of the given type. * - * @param cw the ClassWriter to which this label belongs. - * @param desc a type descriptor. + * @param cw + * the ClassWriter to which this label belongs. + * @param desc + * a type descriptor. * @return the int encoding of the given type. */ private static int type(final ClassWriter cw, final String desc) { String t; int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; switch (desc.charAt(index)) { - case 'V': - return 0; + case 'V': + return 0; + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + return INTEGER; + case 'F': + return FLOAT; + case 'J': + return LONG; + case 'D': + return DOUBLE; + case 'L': + // stores the internal name, not the descriptor! + t = desc.substring(index + 1, desc.length() - 1); + return OBJECT | cw.addType(t); + // case '[': + default: + // extracts the dimensions and the element type + int data; + int dims = index + 1; + while (desc.charAt(dims) == '[') { + ++dims; + } + switch (desc.charAt(dims)) { case 'Z': + data = BOOLEAN; + break; case 'C': + data = CHAR; + break; case 'B': + data = BYTE; + break; case 'S': + data = SHORT; + break; case 'I': - return INTEGER; + data = INTEGER; + break; case 'F': - return FLOAT; + data = FLOAT; + break; case 'J': - return LONG; + data = LONG; + break; case 'D': - return DOUBLE; - case 'L': - // stores the internal name, not the descriptor! - t = desc.substring(index + 1, desc.length() - 1); - return OBJECT | cw.addType(t); - // case '[': + data = DOUBLE; + break; + // case 'L': default: - // extracts the dimensions and the element type - int data; - int dims = index + 1; - while (desc.charAt(dims) == '[') { - ++dims; - } - switch (desc.charAt(dims)) { - case 'Z': - data = BOOLEAN; - break; - case 'C': - data = CHAR; - break; - case 'B': - data = BYTE; - break; - case 'S': - data = SHORT; - break; - case 'I': - data = INTEGER; - break; - case 'F': - data = FLOAT; - break; - case 'J': - data = LONG; - break; - case 'D': - data = DOUBLE; - break; - // case 'L': - default: - // stores the internal name, not the descriptor - t = desc.substring(dims + 1, desc.length() - 1); - data = OBJECT | cw.addType(t); - } - return (dims - index) << 28 | data; + // stores the internal name, not the descriptor + t = desc.substring(dims + 1, desc.length() - 1); + data = OBJECT | cw.addType(t); + } + return (dims - index) << 28 | data; } } @@ -695,7 +703,8 @@ final class Frame { /** * Pops the given number of types from the output frame stack. * - * @param elements the number of types that must be popped. + * @param elements + * the number of types that must be popped. */ private void pop(final int elements) { if (outputStackTop >= elements) { @@ -712,9 +721,10 @@ final class Frame { /** * Pops a type from the output frame stack. * - * @param desc the descriptor of the type to be popped. Can also be a method - * descriptor (in this case this method pops the types corresponding - * to the method arguments). + * @param desc + * the descriptor of the type to be popped. Can also be a method + * descriptor (in this case this method pops the types + * corresponding to the method arguments). */ private void pop(final String desc) { char c = desc.charAt(0); @@ -731,7 +741,8 @@ final class Frame { * Adds a new type to the list of types on which a constructor is invoked in * the basic block. * - * @param var a type on a which a constructor is invoked. + * @param var + * a type on a which a constructor is invoked. */ private void init(final int var) { // creates and/or resizes the initializations array if necessary @@ -752,8 +763,10 @@ final class Frame { * Replaces the given type with the appropriate type if it is one of the * types on which a constructor is invoked in the basic block. * - * @param cw the ClassWriter to which this label belongs. - * @param t a type + * @param cw + * the ClassWriter to which this label belongs. + * @param t + * a type * @return t or, if t is one of the types on which a constructor is invoked * in the basic block, the type corresponding to this constructor. */ @@ -787,17 +800,17 @@ final class Frame { * Initializes the input frame of the first basic block from the method * descriptor. * - * @param cw the ClassWriter to which this label belongs. - * @param access the access flags of the method to which this label belongs. - * @param args the formal parameter types of this method. - * @param maxLocals the maximum number of local variables of this method. + * @param cw + * the ClassWriter to which this label belongs. + * @param access + * the access flags of the method to which this label belongs. + * @param args + * the formal parameter types of this method. + * @param maxLocals + * the maximum number of local variables of this method. */ - void initInputFrame( - final ClassWriter cw, - final int access, - final Type[] args, - final int maxLocals) - { + void initInputFrame(final ClassWriter cw, final int access, + final Type[] args, final int maxLocals) { inputLocals = new int[maxLocals]; inputStack = new int[0]; int i = 0; @@ -823,435 +836,435 @@ final class Frame { /** * Simulates the action of the given instruction on the output stack frame. * - * @param opcode the opcode of the instruction. - * @param arg the operand of the instruction, if any. - * @param cw the class writer to which this label belongs. - * @param item the operand of the instructions, if any. + * @param opcode + * the opcode of the instruction. + * @param arg + * the operand of the instruction, if any. + * @param cw + * the class writer to which this label belongs. + * @param item + * the operand of the instructions, if any. */ - void execute( - final int opcode, - final int arg, - final ClassWriter cw, - final Item item) - { + void execute(final int opcode, final int arg, final ClassWriter cw, + final Item item) { int t1, t2, t3, t4; switch (opcode) { - case Opcodes.NOP: - case Opcodes.INEG: - case Opcodes.LNEG: - case Opcodes.FNEG: - case Opcodes.DNEG: - case Opcodes.I2B: - case Opcodes.I2C: - case Opcodes.I2S: - case Opcodes.GOTO: - case Opcodes.RETURN: - break; - case Opcodes.ACONST_NULL: - push(NULL); - break; - case Opcodes.ICONST_M1: - case Opcodes.ICONST_0: - case Opcodes.ICONST_1: - case Opcodes.ICONST_2: - case Opcodes.ICONST_3: - case Opcodes.ICONST_4: - case Opcodes.ICONST_5: - case Opcodes.BIPUSH: - case Opcodes.SIPUSH: - case Opcodes.ILOAD: + case Opcodes.NOP: + case Opcodes.INEG: + case Opcodes.LNEG: + case Opcodes.FNEG: + case Opcodes.DNEG: + case Opcodes.I2B: + case Opcodes.I2C: + case Opcodes.I2S: + case Opcodes.GOTO: + case Opcodes.RETURN: + break; + case Opcodes.ACONST_NULL: + push(NULL); + break; + case Opcodes.ICONST_M1: + case Opcodes.ICONST_0: + case Opcodes.ICONST_1: + case Opcodes.ICONST_2: + case Opcodes.ICONST_3: + case Opcodes.ICONST_4: + case Opcodes.ICONST_5: + case Opcodes.BIPUSH: + case Opcodes.SIPUSH: + case Opcodes.ILOAD: + push(INTEGER); + break; + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + case Opcodes.LLOAD: + push(LONG); + push(TOP); + break; + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + case Opcodes.FLOAD: + push(FLOAT); + break; + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + case Opcodes.DLOAD: + push(DOUBLE); + push(TOP); + break; + case Opcodes.LDC: + switch (item.type) { + case ClassWriter.INT: push(INTEGER); break; - case Opcodes.LCONST_0: - case Opcodes.LCONST_1: - case Opcodes.LLOAD: + case ClassWriter.LONG: push(LONG); push(TOP); break; - case Opcodes.FCONST_0: - case Opcodes.FCONST_1: - case Opcodes.FCONST_2: - case Opcodes.FLOAD: + case ClassWriter.FLOAT: push(FLOAT); break; - case Opcodes.DCONST_0: - case Opcodes.DCONST_1: - case Opcodes.DLOAD: + case ClassWriter.DOUBLE: push(DOUBLE); push(TOP); break; - case Opcodes.LDC: - switch (item.type) { - case ClassWriter.INT: - push(INTEGER); - break; - case ClassWriter.LONG: - push(LONG); - push(TOP); - break; - case ClassWriter.FLOAT: - push(FLOAT); - break; - case ClassWriter.DOUBLE: - push(DOUBLE); - push(TOP); - break; - case ClassWriter.CLASS: - push(OBJECT | cw.addType("java/lang/Class")); - break; - case ClassWriter.STR: - push(OBJECT | cw.addType("java/lang/String")); - break; - case ClassWriter.MTYPE: - push(OBJECT | cw.addType("java/lang/invoke/MethodType")); - break; - // case ClassWriter.HANDLE_BASE + [1..9]: - default: - push(OBJECT | cw.addType("java/lang/invoke/MethodHandle")); - } - break; - case Opcodes.ALOAD: - push(get(arg)); - break; - case Opcodes.IALOAD: - case Opcodes.BALOAD: - case Opcodes.CALOAD: - case Opcodes.SALOAD: - pop(2); - push(INTEGER); - break; - case Opcodes.LALOAD: - case Opcodes.D2L: - pop(2); - push(LONG); - push(TOP); + case ClassWriter.CLASS: + push(OBJECT | cw.addType("java/lang/Class")); break; - case Opcodes.FALOAD: - pop(2); - push(FLOAT); + case ClassWriter.STR: + push(OBJECT | cw.addType("java/lang/String")); break; - case Opcodes.DALOAD: - case Opcodes.L2D: - pop(2); - push(DOUBLE); - push(TOP); + case ClassWriter.MTYPE: + push(OBJECT | cw.addType("java/lang/invoke/MethodType")); break; - case Opcodes.AALOAD: - pop(1); - t1 = pop(); - push(ELEMENT_OF + t1); - break; - case Opcodes.ISTORE: - case Opcodes.FSTORE: - case Opcodes.ASTORE: - t1 = pop(); - set(arg, t1); - if (arg > 0) { - t2 = get(arg - 1); - // if t2 is of kind STACK or LOCAL we cannot know its size! - if (t2 == LONG || t2 == DOUBLE) { - set(arg - 1, TOP); - } else if ((t2 & KIND) != BASE) { - set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); - } + // case ClassWriter.HANDLE_BASE + [1..9]: + default: + push(OBJECT | cw.addType("java/lang/invoke/MethodHandle")); + } + break; + case Opcodes.ALOAD: + push(get(arg)); + break; + case Opcodes.IALOAD: + case Opcodes.BALOAD: + case Opcodes.CALOAD: + case Opcodes.SALOAD: + pop(2); + push(INTEGER); + break; + case Opcodes.LALOAD: + case Opcodes.D2L: + pop(2); + push(LONG); + push(TOP); + break; + case Opcodes.FALOAD: + pop(2); + push(FLOAT); + break; + case Opcodes.DALOAD: + case Opcodes.L2D: + pop(2); + push(DOUBLE); + push(TOP); + break; + case Opcodes.AALOAD: + pop(1); + t1 = pop(); + push(ELEMENT_OF + t1); + break; + case Opcodes.ISTORE: + case Opcodes.FSTORE: + case Opcodes.ASTORE: + t1 = pop(); + set(arg, t1); + if (arg > 0) { + t2 = get(arg - 1); + // if t2 is of kind STACK or LOCAL we cannot know its size! + if (t2 == LONG || t2 == DOUBLE) { + set(arg - 1, TOP); + } else if ((t2 & KIND) != BASE) { + set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); } - break; - case Opcodes.LSTORE: - case Opcodes.DSTORE: - pop(1); - t1 = pop(); - set(arg, t1); - set(arg + 1, TOP); - if (arg > 0) { - t2 = get(arg - 1); - // if t2 is of kind STACK or LOCAL we cannot know its size! - if (t2 == LONG || t2 == DOUBLE) { - set(arg - 1, TOP); - } else if ((t2 & KIND) != BASE) { - set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); - } + } + break; + case Opcodes.LSTORE: + case Opcodes.DSTORE: + pop(1); + t1 = pop(); + set(arg, t1); + set(arg + 1, TOP); + if (arg > 0) { + t2 = get(arg - 1); + // if t2 is of kind STACK or LOCAL we cannot know its size! + if (t2 == LONG || t2 == DOUBLE) { + set(arg - 1, TOP); + } else if ((t2 & KIND) != BASE) { + set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); } - break; - case Opcodes.IASTORE: - case Opcodes.BASTORE: - case Opcodes.CASTORE: - case Opcodes.SASTORE: - case Opcodes.FASTORE: - case Opcodes.AASTORE: - pop(3); - break; - case Opcodes.LASTORE: - case Opcodes.DASTORE: - pop(4); - break; - case Opcodes.POP: - case Opcodes.IFEQ: - case Opcodes.IFNE: - case Opcodes.IFLT: - case Opcodes.IFGE: - case Opcodes.IFGT: - case Opcodes.IFLE: - case Opcodes.IRETURN: - case Opcodes.FRETURN: - case Opcodes.ARETURN: - case Opcodes.TABLESWITCH: - case Opcodes.LOOKUPSWITCH: - case Opcodes.ATHROW: - case Opcodes.MONITORENTER: - case Opcodes.MONITOREXIT: - case Opcodes.IFNULL: - case Opcodes.IFNONNULL: - pop(1); - break; - case Opcodes.POP2: - case Opcodes.IF_ICMPEQ: - case Opcodes.IF_ICMPNE: - case Opcodes.IF_ICMPLT: - case Opcodes.IF_ICMPGE: - case Opcodes.IF_ICMPGT: - case Opcodes.IF_ICMPLE: - case Opcodes.IF_ACMPEQ: - case Opcodes.IF_ACMPNE: - case Opcodes.LRETURN: - case Opcodes.DRETURN: - pop(2); - break; - case Opcodes.DUP: - t1 = pop(); - push(t1); - push(t1); - break; - case Opcodes.DUP_X1: - t1 = pop(); - t2 = pop(); - push(t1); - push(t2); - push(t1); - break; - case Opcodes.DUP_X2: - t1 = pop(); - t2 = pop(); - t3 = pop(); - push(t1); - push(t3); - push(t2); - push(t1); - break; - case Opcodes.DUP2: - t1 = pop(); - t2 = pop(); - push(t2); - push(t1); - push(t2); - push(t1); - break; - case Opcodes.DUP2_X1: - t1 = pop(); - t2 = pop(); - t3 = pop(); - push(t2); - push(t1); - push(t3); - push(t2); - push(t1); - break; - case Opcodes.DUP2_X2: - t1 = pop(); - t2 = pop(); - t3 = pop(); - t4 = pop(); - push(t2); - push(t1); - push(t4); - push(t3); - push(t2); - push(t1); - break; - case Opcodes.SWAP: + } + break; + case Opcodes.IASTORE: + case Opcodes.BASTORE: + case Opcodes.CASTORE: + case Opcodes.SASTORE: + case Opcodes.FASTORE: + case Opcodes.AASTORE: + pop(3); + break; + case Opcodes.LASTORE: + case Opcodes.DASTORE: + pop(4); + break; + case Opcodes.POP: + case Opcodes.IFEQ: + case Opcodes.IFNE: + case Opcodes.IFLT: + case Opcodes.IFGE: + case Opcodes.IFGT: + case Opcodes.IFLE: + case Opcodes.IRETURN: + case Opcodes.FRETURN: + case Opcodes.ARETURN: + case Opcodes.TABLESWITCH: + case Opcodes.LOOKUPSWITCH: + case Opcodes.ATHROW: + case Opcodes.MONITORENTER: + case Opcodes.MONITOREXIT: + case Opcodes.IFNULL: + case Opcodes.IFNONNULL: + pop(1); + break; + case Opcodes.POP2: + case Opcodes.IF_ICMPEQ: + case Opcodes.IF_ICMPNE: + case Opcodes.IF_ICMPLT: + case Opcodes.IF_ICMPGE: + case Opcodes.IF_ICMPGT: + case Opcodes.IF_ICMPLE: + case Opcodes.IF_ACMPEQ: + case Opcodes.IF_ACMPNE: + case Opcodes.LRETURN: + case Opcodes.DRETURN: + pop(2); + break; + case Opcodes.DUP: + t1 = pop(); + push(t1); + push(t1); + break; + case Opcodes.DUP_X1: + t1 = pop(); + t2 = pop(); + push(t1); + push(t2); + push(t1); + break; + case Opcodes.DUP_X2: + t1 = pop(); + t2 = pop(); + t3 = pop(); + push(t1); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.DUP2: + t1 = pop(); + t2 = pop(); + push(t2); + push(t1); + push(t2); + push(t1); + break; + case Opcodes.DUP2_X1: + t1 = pop(); + t2 = pop(); + t3 = pop(); + push(t2); + push(t1); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.DUP2_X2: + t1 = pop(); + t2 = pop(); + t3 = pop(); + t4 = pop(); + push(t2); + push(t1); + push(t4); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.SWAP: + t1 = pop(); + t2 = pop(); + push(t1); + push(t2); + break; + case Opcodes.IADD: + case Opcodes.ISUB: + case Opcodes.IMUL: + case Opcodes.IDIV: + case Opcodes.IREM: + case Opcodes.IAND: + case Opcodes.IOR: + case Opcodes.IXOR: + case Opcodes.ISHL: + case Opcodes.ISHR: + case Opcodes.IUSHR: + case Opcodes.L2I: + case Opcodes.D2I: + case Opcodes.FCMPL: + case Opcodes.FCMPG: + pop(2); + push(INTEGER); + break; + case Opcodes.LADD: + case Opcodes.LSUB: + case Opcodes.LMUL: + case Opcodes.LDIV: + case Opcodes.LREM: + case Opcodes.LAND: + case Opcodes.LOR: + case Opcodes.LXOR: + pop(4); + push(LONG); + push(TOP); + break; + case Opcodes.FADD: + case Opcodes.FSUB: + case Opcodes.FMUL: + case Opcodes.FDIV: + case Opcodes.FREM: + case Opcodes.L2F: + case Opcodes.D2F: + pop(2); + push(FLOAT); + break; + case Opcodes.DADD: + case Opcodes.DSUB: + case Opcodes.DMUL: + case Opcodes.DDIV: + case Opcodes.DREM: + pop(4); + push(DOUBLE); + push(TOP); + break; + case Opcodes.LSHL: + case Opcodes.LSHR: + case Opcodes.LUSHR: + pop(3); + push(LONG); + push(TOP); + break; + case Opcodes.IINC: + set(arg, INTEGER); + break; + case Opcodes.I2L: + case Opcodes.F2L: + pop(1); + push(LONG); + push(TOP); + break; + case Opcodes.I2F: + pop(1); + push(FLOAT); + break; + case Opcodes.I2D: + case Opcodes.F2D: + pop(1); + push(DOUBLE); + push(TOP); + break; + case Opcodes.F2I: + case Opcodes.ARRAYLENGTH: + case Opcodes.INSTANCEOF: + pop(1); + push(INTEGER); + break; + case Opcodes.LCMP: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + pop(4); + push(INTEGER); + break; + case Opcodes.JSR: + case Opcodes.RET: + throw new RuntimeException( + "JSR/RET are not supported with computeFrames option"); + case Opcodes.GETSTATIC: + push(cw, item.strVal3); + break; + case Opcodes.PUTSTATIC: + pop(item.strVal3); + break; + case Opcodes.GETFIELD: + pop(1); + push(cw, item.strVal3); + break; + case Opcodes.PUTFIELD: + pop(item.strVal3); + pop(); + break; + case Opcodes.INVOKEVIRTUAL: + case Opcodes.INVOKESPECIAL: + case Opcodes.INVOKESTATIC: + case Opcodes.INVOKEINTERFACE: + pop(item.strVal3); + if (opcode != Opcodes.INVOKESTATIC) { t1 = pop(); - t2 = pop(); - push(t1); - push(t2); - break; - case Opcodes.IADD: - case Opcodes.ISUB: - case Opcodes.IMUL: - case Opcodes.IDIV: - case Opcodes.IREM: - case Opcodes.IAND: - case Opcodes.IOR: - case Opcodes.IXOR: - case Opcodes.ISHL: - case Opcodes.ISHR: - case Opcodes.IUSHR: - case Opcodes.L2I: - case Opcodes.D2I: - case Opcodes.FCMPL: - case Opcodes.FCMPG: - pop(2); - push(INTEGER); - break; - case Opcodes.LADD: - case Opcodes.LSUB: - case Opcodes.LMUL: - case Opcodes.LDIV: - case Opcodes.LREM: - case Opcodes.LAND: - case Opcodes.LOR: - case Opcodes.LXOR: - pop(4); - push(LONG); - push(TOP); - break; - case Opcodes.FADD: - case Opcodes.FSUB: - case Opcodes.FMUL: - case Opcodes.FDIV: - case Opcodes.FREM: - case Opcodes.L2F: - case Opcodes.D2F: - pop(2); - push(FLOAT); - break; - case Opcodes.DADD: - case Opcodes.DSUB: - case Opcodes.DMUL: - case Opcodes.DDIV: - case Opcodes.DREM: - pop(4); - push(DOUBLE); - push(TOP); - break; - case Opcodes.LSHL: - case Opcodes.LSHR: - case Opcodes.LUSHR: - pop(3); - push(LONG); - push(TOP); - break; - case Opcodes.IINC: - set(arg, INTEGER); - break; - case Opcodes.I2L: - case Opcodes.F2L: - pop(1); - push(LONG); - push(TOP); - break; - case Opcodes.I2F: - pop(1); - push(FLOAT); - break; - case Opcodes.I2D: - case Opcodes.F2D: - pop(1); - push(DOUBLE); - push(TOP); - break; - case Opcodes.F2I: - case Opcodes.ARRAYLENGTH: - case Opcodes.INSTANCEOF: - pop(1); - push(INTEGER); - break; - case Opcodes.LCMP: - case Opcodes.DCMPL: - case Opcodes.DCMPG: - pop(4); - push(INTEGER); - break; - case Opcodes.JSR: - case Opcodes.RET: - throw new RuntimeException("JSR/RET are not supported with computeFrames option"); - case Opcodes.GETSTATIC: - push(cw, item.strVal3); - break; - case Opcodes.PUTSTATIC: - pop(item.strVal3); - break; - case Opcodes.GETFIELD: - pop(1); - push(cw, item.strVal3); - break; - case Opcodes.PUTFIELD: - pop(item.strVal3); - pop(); - break; - case Opcodes.INVOKEVIRTUAL: - case Opcodes.INVOKESPECIAL: - case Opcodes.INVOKESTATIC: - case Opcodes.INVOKEINTERFACE: - pop(item.strVal3); - if (opcode != Opcodes.INVOKESTATIC) { - t1 = pop(); - if (opcode == Opcodes.INVOKESPECIAL - && item.strVal2.charAt(0) == '<') - { - init(t1); - } + if (opcode == Opcodes.INVOKESPECIAL + && item.strVal2.charAt(0) == '<') { + init(t1); } - push(cw, item.strVal3); + } + push(cw, item.strVal3); + break; + case Opcodes.INVOKEDYNAMIC: + pop(item.strVal2); + push(cw, item.strVal2); + break; + case Opcodes.NEW: + push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg)); + break; + case Opcodes.NEWARRAY: + pop(); + switch (arg) { + case Opcodes.T_BOOLEAN: + push(ARRAY_OF | BOOLEAN); break; - case Opcodes.INVOKEDYNAMIC: - pop(item.strVal2); - push(cw, item.strVal2); + case Opcodes.T_CHAR: + push(ARRAY_OF | CHAR); break; - case Opcodes.NEW: - push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg)); + case Opcodes.T_BYTE: + push(ARRAY_OF | BYTE); break; - case Opcodes.NEWARRAY: - pop(); - switch (arg) { - case Opcodes.T_BOOLEAN: - push(ARRAY_OF | BOOLEAN); - break; - case Opcodes.T_CHAR: - push(ARRAY_OF | CHAR); - break; - case Opcodes.T_BYTE: - push(ARRAY_OF | BYTE); - break; - case Opcodes.T_SHORT: - push(ARRAY_OF | SHORT); - break; - case Opcodes.T_INT: - push(ARRAY_OF | INTEGER); - break; - case Opcodes.T_FLOAT: - push(ARRAY_OF | FLOAT); - break; - case Opcodes.T_DOUBLE: - push(ARRAY_OF | DOUBLE); - break; - // case Opcodes.T_LONG: - default: - push(ARRAY_OF | LONG); - break; - } + case Opcodes.T_SHORT: + push(ARRAY_OF | SHORT); break; - case Opcodes.ANEWARRAY: - String s = item.strVal1; - pop(); - if (s.charAt(0) == '[') { - push(cw, '[' + s); - } else { - push(ARRAY_OF | OBJECT | cw.addType(s)); - } + case Opcodes.T_INT: + push(ARRAY_OF | INTEGER); break; - case Opcodes.CHECKCAST: - s = item.strVal1; - pop(); - if (s.charAt(0) == '[') { - push(cw, s); - } else { - push(OBJECT | cw.addType(s)); - } + case Opcodes.T_FLOAT: + push(ARRAY_OF | FLOAT); break; - // case Opcodes.MULTIANEWARRAY: + case Opcodes.T_DOUBLE: + push(ARRAY_OF | DOUBLE); + break; + // case Opcodes.T_LONG: default: - pop(arg); - push(cw, item.strVal1); + push(ARRAY_OF | LONG); break; + } + break; + case Opcodes.ANEWARRAY: + String s = item.strVal1; + pop(); + if (s.charAt(0) == '[') { + push(cw, '[' + s); + } else { + push(ARRAY_OF | OBJECT | cw.addType(s)); + } + break; + case Opcodes.CHECKCAST: + s = item.strVal1; + pop(); + if (s.charAt(0) == '[') { + push(cw, s); + } else { + push(OBJECT | cw.addType(s)); + } + break; + // case Opcodes.MULTIANEWARRAY: + default: + pop(arg); + push(cw, item.strVal1); + break; } } @@ -1260,10 +1273,13 @@ final class Frame { * frames of this basic block. Returns <tt>true</tt> if the input frame of * the given label has been changed by this operation. * - * @param cw the ClassWriter to which this label belongs. - * @param frame the basic block whose input frame must be updated. - * @param edge the kind of the {@link Edge} between this label and 'label'. - * See {@link Edge#info}. + * @param cw + * the ClassWriter to which this label belongs. + * @param frame + * the basic block whose input frame must be updated. + * @param edge + * the kind of the {@link Edge} between this label and 'label'. + * See {@link Edge#info}. * @return <tt>true</tt> if the input frame of the given label has been * changed by this operation. */ @@ -1294,7 +1310,8 @@ final class Frame { } else { t = dim + inputStack[nStack - (s & VALUE)]; } - if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) { + if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 + && (t == LONG || t == DOUBLE)) { t = TOP; } } @@ -1346,7 +1363,8 @@ final class Frame { } else { t = dim + inputStack[nStack - (s & VALUE)]; } - if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) { + if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 + && (t == LONG || t == DOUBLE)) { t = TOP; } } @@ -1363,19 +1381,19 @@ final class Frame { * type. Returns <tt>true</tt> if the type array has been modified by this * operation. * - * @param cw the ClassWriter to which this label belongs. - * @param t the type with which the type array element must be merged. - * @param types an array of types. - * @param index the index of the type that must be merged in 'types'. + * @param cw + * the ClassWriter to which this label belongs. + * @param t + * the type with which the type array element must be merged. + * @param types + * an array of types. + * @param index + * the index of the type that must be merged in 'types'. * @return <tt>true</tt> if the type array has been modified by this * operation. */ - private static boolean merge( - final ClassWriter cw, - int t, - final int[] types, - final int index) - { + private static boolean merge(final ClassWriter cw, int t, + final int[] types, final int index) { int u = types[index]; if (u == t) { // if the types are equal, merge(u,t)=u, so there is no change diff --git a/src/asm/scala/tools/asm/Handle.java b/src/asm/scala/tools/asm/Handle.java index be8f334192..5dd06a54b9 100644 --- a/src/asm/scala/tools/asm/Handle.java +++ b/src/asm/scala/tools/asm/Handle.java @@ -66,18 +66,23 @@ public final class Handle { /** * Constructs a new field or method handle. * - * @param tag the kind of field or method designated by this Handle. Must be - * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, - * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, - * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - * @param owner the internal name of the field or method designed by this - * handle. - * @param name the name of the field or method designated by this handle. - * @param desc the descriptor of the field or method designated by this - * handle. + * @param tag + * the kind of field or method designated by this Handle. Must be + * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, + * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, + * {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the field or method designed by this + * handle. + * @param name + * the name of the field or method designated by this handle. + * @param desc + * the descriptor of the field or method designated by this + * handle. */ public Handle(int tag, String owner, String name, String desc) { this.tag = tag; @@ -101,11 +106,9 @@ public final class Handle { } /** - * Returns the internal name of the field or method designed by this - * handle. + * Returns the internal name of the field or method designed by this handle. * - * @return the internal name of the field or method designed by this - * handle. + * @return the internal name of the field or method designed by this handle. */ public String getOwner() { return owner; @@ -138,8 +141,8 @@ public final class Handle { return false; } Handle h = (Handle) obj; - return tag == h.tag && owner.equals(h.owner) - && name.equals(h.name) && desc.equals(h.desc); + return tag == h.tag && owner.equals(h.owner) && name.equals(h.name) + && desc.equals(h.desc); } @Override @@ -149,8 +152,13 @@ public final class Handle { /** * Returns the textual representation of this handle. The textual - * representation is: <pre>owner '.' name desc ' ' '(' tag ')'</pre>. As - * this format is unambiguous, it can be parsed if necessary. + * representation is: + * + * <pre> + * owner '.' name desc ' ' '(' tag ')' + * </pre> + * + * . As this format is unambiguous, it can be parsed if necessary. */ @Override public String toString() { diff --git a/src/asm/scala/tools/asm/Handler.java b/src/asm/scala/tools/asm/Handler.java index 9e92bb98be..a06cb8152a 100644 --- a/src/asm/scala/tools/asm/Handler.java +++ b/src/asm/scala/tools/asm/Handler.java @@ -72,9 +72,12 @@ class Handler { * Removes the range between start and end from the given exception * handlers. * - * @param h an exception handler list. - * @param start the start of the range to be removed. - * @param end the end of the range to be removed. Maybe null. + * @param h + * an exception handler list. + * @param start + * the start of the range to be removed. + * @param end + * the end of the range to be removed. Maybe null. * @return the exception handler list with the start-end range removed. */ static Handler remove(Handler h, Label start, Label end) { diff --git a/src/asm/scala/tools/asm/Item.java b/src/asm/scala/tools/asm/Item.java index 021a0b11d3..94195a1082 100644 --- a/src/asm/scala/tools/asm/Item.java +++ b/src/asm/scala/tools/asm/Item.java @@ -53,8 +53,8 @@ final class Item { * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. * - * MethodHandle constant 9 variations are stored using a range - * of 9 values from {@link ClassWriter#HANDLE_BASE} + 1 to + * MethodHandle constant 9 variations are stored using a range of 9 values + * from {@link ClassWriter#HANDLE_BASE} + 1 to * {@link ClassWriter#HANDLE_BASE} + 9. * * Special Item types are used for Items that are stored in the ClassWriter @@ -115,7 +115,8 @@ final class Item { * Constructs an uninitialized {@link Item} for constant pool element at * given position. * - * @param index index of the item to be constructed. + * @param index + * index of the item to be constructed. */ Item(final int index) { this.index = index; @@ -124,8 +125,10 @@ final class Item { /** * Constructs a copy of the given item. * - * @param index index of the item to be constructed. - * @param i the item that must be copied into the item to be constructed. + * @param index + * index of the item to be constructed. + * @param i + * the item that must be copied into the item to be constructed. */ Item(final int index, final Item i) { this.index = index; @@ -141,7 +144,8 @@ final class Item { /** * Sets this item to an integer item. * - * @param intVal the value of this item. + * @param intVal + * the value of this item. */ void set(final int intVal) { this.type = ClassWriter.INT; @@ -152,7 +156,8 @@ final class Item { /** * Sets this item to a long item. * - * @param longVal the value of this item. + * @param longVal + * the value of this item. */ void set(final long longVal) { this.type = ClassWriter.LONG; @@ -163,7 +168,8 @@ final class Item { /** * Sets this item to a float item. * - * @param floatVal the value of this item. + * @param floatVal + * the value of this item. */ void set(final float floatVal) { this.type = ClassWriter.FLOAT; @@ -174,7 +180,8 @@ final class Item { /** * Sets this item to a double item. * - * @param doubleVal the value of this item. + * @param doubleVal + * the value of this item. */ void set(final double doubleVal) { this.type = ClassWriter.DOUBLE; @@ -185,49 +192,53 @@ final class Item { /** * Sets this item to an item that do not hold a primitive value. * - * @param type the type of this item. - * @param strVal1 first part of the value of this item. - * @param strVal2 second part of the value of this item. - * @param strVal3 third part of the value of this item. + * @param type + * the type of this item. + * @param strVal1 + * first part of the value of this item. + * @param strVal2 + * second part of the value of this item. + * @param strVal3 + * third part of the value of this item. */ - void set( - final int type, - final String strVal1, - final String strVal2, - final String strVal3) - { + void set(final int type, final String strVal1, final String strVal2, + final String strVal3) { this.type = type; this.strVal1 = strVal1; this.strVal2 = strVal2; this.strVal3 = strVal3; switch (type) { - case ClassWriter.UTF8: - case ClassWriter.STR: - case ClassWriter.CLASS: - case ClassWriter.MTYPE: - case ClassWriter.TYPE_NORMAL: - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); - return; - case ClassWriter.NAME_TYPE: - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() - * strVal2.hashCode()); - return; - // ClassWriter.FIELD: - // ClassWriter.METH: - // ClassWriter.IMETH: - // ClassWriter.HANDLE_BASE + 1..9 - default: - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() - * strVal2.hashCode() * strVal3.hashCode()); + case ClassWriter.UTF8: + case ClassWriter.STR: + case ClassWriter.CLASS: + case ClassWriter.MTYPE: + case ClassWriter.TYPE_NORMAL: + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); + return; + case ClassWriter.NAME_TYPE: { + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() + * strVal2.hashCode()); + return; + } + // ClassWriter.FIELD: + // ClassWriter.METH: + // ClassWriter.IMETH: + // ClassWriter.HANDLE_BASE + 1..9 + default: + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() + * strVal2.hashCode() * strVal3.hashCode()); } } /** * Sets the item to an InvokeDynamic item. * - * @param name invokedynamic's name. - * @param desc invokedynamic's desc. - * @param bsmIndex zero based index into the class attribute BootrapMethods. + * @param name + * invokedynamic's name. + * @param desc + * invokedynamic's desc. + * @param bsmIndex + * zero based index into the class attribute BootrapMethods. */ void set(String name, String desc, int bsmIndex) { this.type = ClassWriter.INDY; @@ -241,10 +252,12 @@ final class Item { /** * Sets the item to a BootstrapMethod item. * - * @param position position in byte in the class attribute BootrapMethods. - * @param hashCode hashcode of the item. This hashcode is processed from - * the hashcode of the bootstrap method and the hashcode of - * all bootstrap arguments. + * @param position + * position in byte in the class attribute BootrapMethods. + * @param hashCode + * hashcode of the item. This hashcode is processed from the + * hashcode of the bootstrap method and the hashcode of all + * bootstrap arguments. */ void set(int position, int hashCode) { this.type = ClassWriter.BSM; @@ -256,41 +269,42 @@ final class Item { * Indicates if the given item is equal to this one. <i>This method assumes * that the two items have the same {@link #type}</i>. * - * @param i the item to be compared to this one. Both items must have the - * same {@link #type}. + * @param i + * the item to be compared to this one. Both items must have the + * same {@link #type}. * @return <tt>true</tt> if the given item if equal to this one, * <tt>false</tt> otherwise. */ boolean isEqualTo(final Item i) { switch (type) { - case ClassWriter.UTF8: - case ClassWriter.STR: - case ClassWriter.CLASS: - case ClassWriter.MTYPE: - case ClassWriter.TYPE_NORMAL: - return i.strVal1.equals(strVal1); - case ClassWriter.TYPE_MERGED: - case ClassWriter.LONG: - case ClassWriter.DOUBLE: - return i.longVal == longVal; - case ClassWriter.INT: - case ClassWriter.FLOAT: - return i.intVal == intVal; - case ClassWriter.TYPE_UNINIT: - return i.intVal == intVal && i.strVal1.equals(strVal1); - case ClassWriter.NAME_TYPE: - return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2); - case ClassWriter.INDY: - return i.longVal == longVal && i.strVal1.equals(strVal1) - && i.strVal2.equals(strVal2); - - // case ClassWriter.FIELD: - // case ClassWriter.METH: - // case ClassWriter.IMETH: - // case ClassWriter.HANDLE_BASE + 1..9 - default: - return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2) - && i.strVal3.equals(strVal3); + case ClassWriter.UTF8: + case ClassWriter.STR: + case ClassWriter.CLASS: + case ClassWriter.MTYPE: + case ClassWriter.TYPE_NORMAL: + return i.strVal1.equals(strVal1); + case ClassWriter.TYPE_MERGED: + case ClassWriter.LONG: + case ClassWriter.DOUBLE: + return i.longVal == longVal; + case ClassWriter.INT: + case ClassWriter.FLOAT: + return i.intVal == intVal; + case ClassWriter.TYPE_UNINIT: + return i.intVal == intVal && i.strVal1.equals(strVal1); + case ClassWriter.NAME_TYPE: + return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2); + case ClassWriter.INDY: { + return i.longVal == longVal && i.strVal1.equals(strVal1) + && i.strVal2.equals(strVal2); + } + // case ClassWriter.FIELD: + // case ClassWriter.METH: + // case ClassWriter.IMETH: + // case ClassWriter.HANDLE_BASE + 1..9 + default: + return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2) + && i.strVal3.equals(strVal3); } } diff --git a/src/asm/scala/tools/asm/Label.java b/src/asm/scala/tools/asm/Label.java index 712c7f251f..5d5529ce74 100644 --- a/src/asm/scala/tools/asm/Label.java +++ b/src/asm/scala/tools/asm/Label.java @@ -32,9 +32,9 @@ package scala.tools.asm; /** * A label represents a position in the bytecode of a method. Labels are used * for jump, goto, and switch instructions, and for try catch blocks. A label - * designates the <i>instruction</i> that is just after. Note however that - * there can be other elements between a label and the instruction it - * designates (such as other labels, stack map frames, line numbers, etc.). + * designates the <i>instruction</i> that is just after. Note however that there + * can be other elements between a label and the instruction it designates (such + * as other labels, stack map frames, line numbers, etc.). * * @author Eric Bruneton */ @@ -110,8 +110,8 @@ public class Label { /** * Field used to associate user information to a label. Warning: this field * is used by the ASM tree package. In order to use it with the ASM tree - * package you must override the {@link - * org.objectweb.asm.tree.MethodNode#getLabelNode} method. + * package you must override the + * {@link scala.tools.asm.tree.MethodNode#getLabelNode} method. */ public Object info; @@ -154,7 +154,7 @@ public class Label { * indicates if this reference uses 2 or 4 bytes, and its absolute value * gives the position of the bytecode instruction. This array is also used * as a bitset to store the subroutines to which a basic block belongs. This - * information is needed in {@linked MethodWriter#visitMaxs}, after all + * information is needed in {@linked MethodWriter#visitMaxs}, after all * forward references have been resolved. Hence the same array can be used * for both purposes without problems. */ @@ -177,11 +177,11 @@ public class Label { * state of the local variables and the operand stack at the end of each * basic block, called the "output frame", <i>relatively</i> to the frame * state at the beginning of the basic block, which is called the "input - * frame", and which is <i>unknown</i> during this step. The second step, - * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that - * computes information about the input frame of each basic block, from the - * input state of the first basic block (known from the method signature), - * and by the using the previously computed relative output frames. + * frame", and which is <i>unknown</i> during this step. The second step, in + * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes + * information about the input frame of each basic block, from the input + * state of the first basic block (known from the method signature), and by + * the using the previously computed relative output frames. * * The algorithm used to compute the maximum stack size only computes the * relative output and absolute input stack heights, while the algorithm @@ -266,11 +266,13 @@ public class Label { * generators or adapters.</i> * * @return the offset corresponding to this label. - * @throws IllegalStateException if this label is not resolved yet. + * @throws IllegalStateException + * if this label is not resolved yet. */ public int getOffset() { if ((status & RESOLVED) == 0) { - throw new IllegalStateException("Label offset position has not been resolved yet"); + throw new IllegalStateException( + "Label offset position has not been resolved yet"); } return position; } @@ -281,21 +283,21 @@ public class Label { * directly. Otherwise, a null offset is written and a new forward reference * is declared for this label. * - * @param owner the code writer that calls this method. - * @param out the bytecode of the method. - * @param source the position of first byte of the bytecode instruction that - * contains this label. - * @param wideOffset <tt>true</tt> if the reference must be stored in 4 - * bytes, or <tt>false</tt> if it must be stored with 2 bytes. - * @throws IllegalArgumentException if this label has not been created by - * the given code writer. - */ - void put( - final MethodWriter owner, - final ByteVector out, - final int source, - final boolean wideOffset) - { + * @param owner + * the code writer that calls this method. + * @param out + * the bytecode of the method. + * @param source + * the position of first byte of the bytecode instruction that + * contains this label. + * @param wideOffset + * <tt>true</tt> if the reference must be stored in 4 bytes, or + * <tt>false</tt> if it must be stored with 2 bytes. + * @throws IllegalArgumentException + * if this label has not been created by the given code writer. + */ + void put(final MethodWriter owner, final ByteVector out, final int source, + final boolean wideOffset) { if ((status & RESOLVED) == 0) { if (wideOffset) { addReference(-1 - source, out.length); @@ -319,25 +321,21 @@ public class Label { * yet. For backward references, the offset of the reference can be, and * must be, computed and stored directly. * - * @param sourcePosition the position of the referencing instruction. This - * position will be used to compute the offset of this forward - * reference. - * @param referencePosition the position where the offset for this forward - * reference must be stored. - */ - private void addReference( - final int sourcePosition, - final int referencePosition) - { + * @param sourcePosition + * the position of the referencing instruction. This position + * will be used to compute the offset of this forward reference. + * @param referencePosition + * the position where the offset for this forward reference must + * be stored. + */ + private void addReference(final int sourcePosition, + final int referencePosition) { if (srcAndRefPositions == null) { srcAndRefPositions = new int[6]; } if (referenceCount >= srcAndRefPositions.length) { int[] a = new int[srcAndRefPositions.length + 6]; - System.arraycopy(srcAndRefPositions, - 0, - a, - 0, + System.arraycopy(srcAndRefPositions, 0, a, 0, srcAndRefPositions.length); srcAndRefPositions = a; } @@ -351,9 +349,12 @@ public class Label { * position becomes known. This method fills in the blanks that where left * in the bytecode by each forward reference previously added to this label. * - * @param owner the code writer that calls this method. - * @param position the position of this label in the bytecode. - * @param data the bytecode of the method. + * @param owner + * the code writer that calls this method. + * @param position + * the position of this label in the bytecode. + * @param data + * the bytecode of the method. * @return <tt>true</tt> if a blank that was left for this label was to * small to store the offset. In such a case the corresponding jump * instruction is replaced with a pseudo instruction (using unused @@ -361,14 +362,12 @@ public class Label { * instructions will need to be replaced with true instructions with * wider offsets (4 bytes instead of 2). This is done in * {@link MethodWriter#resizeInstructions}. - * @throws IllegalArgumentException if this label has already been resolved, - * or if it has not been created by the given code writer. - */ - boolean resolve( - final MethodWriter owner, - final int position, - final byte[] data) - { + * @throws IllegalArgumentException + * if this label has already been resolved, or if it has not + * been created by the given code writer. + */ + boolean resolve(final MethodWriter owner, final int position, + final byte[] data) { boolean needUpdate = false; this.status |= RESOLVED; this.position = position; @@ -431,7 +430,8 @@ public class Label { /** * Returns true is this basic block belongs to the given subroutine. * - * @param id a subroutine id. + * @param id + * a subroutine id. * @return true is this basic block belongs to the given subroutine. */ boolean inSubroutine(final long id) { @@ -445,7 +445,8 @@ public class Label { * Returns true if this basic block and the given one belong to a common * subroutine. * - * @param block another basic block. + * @param block + * another basic block. * @return true if this basic block and the given one belong to a common * subroutine. */ @@ -464,8 +465,10 @@ public class Label { /** * Marks this basic block as belonging to the given subroutine. * - * @param id a subroutine id. - * @param nbSubroutines the total number of subroutines in the method. + * @param id + * a subroutine id. + * @param nbSubroutines + * the total number of subroutines in the method. */ void addToSubroutine(final long id, final int nbSubroutines) { if ((status & VISITED) == 0) { @@ -481,14 +484,16 @@ public class Label { * flow graph to find all the blocks that are reachable from the current * block WITHOUT following any JSR target. * - * @param JSR a JSR block that jumps to this subroutine. If this JSR is not - * null it is added to the successor of the RET blocks found in the - * subroutine. - * @param id the id of this subroutine. - * @param nbSubroutines the total number of subroutines in the method. - */ - void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) - { + * @param JSR + * a JSR block that jumps to this subroutine. If this JSR is not + * null it is added to the successor of the RET blocks found in + * the subroutine. + * @param id + * the id of this subroutine. + * @param nbSubroutines + * the total number of subroutines in the method. + */ + void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) { // user managed stack of labels, to avoid using a recursive method // (recursivity can lead to stack overflow with very large methods) Label stack = this; diff --git a/src/asm/scala/tools/asm/MethodVisitor.java b/src/asm/scala/tools/asm/MethodVisitor.java index a8a859a6a9..e43ca97823 100644 --- a/src/asm/scala/tools/asm/MethodVisitor.java +++ b/src/asm/scala/tools/asm/MethodVisitor.java @@ -30,19 +30,19 @@ package scala.tools.asm; /** - * A visitor to visit a Java method. The methods of this class must be - * called in the following order: [ <tt>visitAnnotationDefault</tt> ] ( + * A visitor to visit a Java method. The methods of this class must be called in + * the following order: [ <tt>visitAnnotationDefault</tt> ] ( * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> | * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> | - * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> | - * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] - * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt> - * and <tt>visitLabel</tt> methods must be called in the sequential order of - * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt> - * must be called <i>before</i> the labels passed as arguments have been - * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt> - * methods must be called <i>after</i> the labels passed as arguments have been - * visited. + * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | + * <tt>visitTryCatchBlock</tt> | <tt>visitLocalVariable</tt> | + * <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In + * addition, the <tt>visit</tt><i>X</i>Insn</tt> and <tt>visitLabel</tt> methods + * must be called in the sequential order of the bytecode instructions of the + * visited code, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the + * labels passed as arguments have been visited, and the + * <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt> methods must be + * called <i>after</i> the labels passed as arguments have been visited. * * @author Eric Bruneton */ @@ -63,8 +63,9 @@ public abstract class MethodVisitor { /** * Constructs a new {@link MethodVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. */ public MethodVisitor(final int api) { this(api, null); @@ -73,15 +74,17 @@ public abstract class MethodVisitor { /** * Constructs a new {@link MethodVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param mv the method visitor to which this visitor must delegate method - * calls. May be null. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param mv + * the method visitor to which this visitor must delegate method + * calls. May be null. */ public MethodVisitor(final int api, final MethodVisitor mv) { - /*if (api != Opcodes.ASM4) { + if (api != Opcodes.ASM4) { throw new IllegalArgumentException(); - }*/ + } this.api = api; this.mv = mv; } @@ -94,8 +97,8 @@ public abstract class MethodVisitor { * Visits the default value of this annotation interface method. * * @return a visitor to the visit the actual default value of this - * annotation interface method, or <tt>null</tt> if this visitor - * is not interested in visiting this default value. The 'name' + * annotation interface method, or <tt>null</tt> if this visitor is + * not interested in visiting this default value. The 'name' * parameters passed to the methods of this annotation visitor are * ignored. Moreover, exacly one visit method must be called on this * annotation visitor, followed by visitEnd. @@ -110,8 +113,10 @@ public abstract class MethodVisitor { /** * Visits an annotation of this method. * - * @param desc the class descriptor of the annotation class. - * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * <tt>true</tt> if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or <tt>null</tt> if * this visitor is not interested in visiting this annotation. */ @@ -125,17 +130,17 @@ public abstract class MethodVisitor { /** * Visits an annotation of a parameter this method. * - * @param parameter the parameter index. - * @param desc the class descriptor of the annotation class. - * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @param parameter + * the parameter index. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * <tt>true</tt> if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or <tt>null</tt> if * this visitor is not interested in visiting this annotation. */ - public AnnotationVisitor visitParameterAnnotation( - int parameter, - String desc, - boolean visible) - { + public AnnotationVisitor visitParameterAnnotation(int parameter, + String desc, boolean visible) { if (mv != null) { return mv.visitParameterAnnotation(parameter, desc, visible); } @@ -145,7 +150,8 @@ public abstract class MethodVisitor { /** * Visits a non standard attribute of this method. * - * @param attr an attribute. + * @param attr + * an attribute. */ public void visitAttribute(Attribute attr) { if (mv != null) { @@ -169,57 +175,74 @@ public abstract class MethodVisitor { * such as GOTO or THROW, that is the target of a jump instruction, or that * starts an exception handler block. The visited types must describe the * values of the local variables and of the operand stack elements <i>just - * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only - * for classes whose version is greater than or equal to - * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically - * "deltas" from the state of the previous frame (very first frame is - * implicitly defined by the method's parameters and access flags): <ul> + * before</i> <b>i</b> is executed.<br> + * <br> + * (*) this is mandatory only for classes whose version is greater than or + * equal to {@link Opcodes#V1_6 V1_6}. <br> + * <br> + * The frames of a method must be given either in expanded form, or in + * compressed form (all frames must use the same format, i.e. you must not + * mix expanded and compressed frames within a single method): + * <ul> + * <li>In expanded form, all frames must have the F_NEW type.</li> + * <li>In compressed form, frames are basically "deltas" from the state of + * the previous frame: + * <ul> * <li>{@link Opcodes#F_SAME} representing frame with exactly the same - * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1} - * representing frame with exactly the same locals as the previous frame and - * with single value on the stack (<code>nStack</code> is 1 and - * <code>stack[0]</code> contains value for the type of the stack item).</li> + * locals as the previous frame and with the empty stack.</li> + * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same + * locals as the previous frame and with single value on the stack ( + * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the + * type of the stack item).</li> * <li>{@link Opcodes#F_APPEND} representing frame with current locals are * the same as the locals in the previous frame, except that additional * locals are defined (<code>nLocal</code> is 1, 2 or 3 and * <code>local</code> elements contains values representing added types).</li> - * <li>{@link Opcodes#F_CHOP} representing frame with current locals are - * the same as the locals in the previous frame, except that the last 1-3 - * locals are absent and with the empty stack (<code>nLocals</code> is 1, - * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame - * data.</li> </li> </ul> + * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the + * same as the locals in the previous frame, except that the last 1-3 locals + * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li> + * <li>{@link Opcodes#F_FULL} representing complete frame data.</li></li> + * </ul> + * </ul> <br> + * In both cases the first frame, corresponding to the method's parameters + * and access flags, is implicit and must not be visited. Also, it is + * illegal to visit two or more frames for the same code location (i.e., at + * least one instruction must be visited between two calls to visitFrame). * - * @param type the type of this stack map frame. Must be - * {@link Opcodes#F_NEW} for expanded frames, or - * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, - * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or - * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed - * frames. - * @param nLocal the number of local variables in the visited frame. - * @param local the local variable types in this frame. This array must not - * be modified. Primitive types are represented by - * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, - * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, - * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or - * {@link Opcodes#UNINITIALIZED_THIS} (long and double are - * represented by a single element). Reference types are represented - * by String objects (representing internal names), and uninitialized - * types by Label objects (this label designates the NEW instruction - * that created this uninitialized value). - * @param nStack the number of operand stack elements in the visited frame. - * @param stack the operand stack types in this frame. This array must not - * be modified. Its content has the same format as the "local" array. - * @throws IllegalStateException if a frame is visited just after another - * one, without any instruction between the two (unless this frame - * is a Opcodes#F_SAME frame, in which case it is silently ignored). + * @param type + * the type of this stack map frame. Must be + * {@link Opcodes#F_NEW} for expanded frames, or + * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, + * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or + * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for + * compressed frames. + * @param nLocal + * the number of local variables in the visited frame. + * @param local + * the local variable types in this frame. This array must not be + * modified. Primitive types are represented by + * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, + * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are + * represented by a single element). Reference types are + * represented by String objects (representing internal names), + * and uninitialized types by Label objects (this label + * designates the NEW instruction that created this uninitialized + * value). + * @param nStack + * the number of operand stack elements in the visited frame. + * @param stack + * the operand stack types in this frame. This array must not be + * modified. Its content has the same format as the "local" + * array. + * @throws IllegalStateException + * if a frame is visited just after another one, without any + * instruction between the two (unless this frame is a + * Opcodes#F_SAME frame, in which case it is silently ignored). */ - public void visitFrame( - int type, - int nLocal, - Object[] local, - int nStack, - Object[] stack) - { + public void visitFrame(int type, int nLocal, Object[] local, int nStack, + Object[] stack) { if (mv != null) { mv.visitFrame(type, nLocal, local, nStack, stack); } @@ -232,20 +255,22 @@ public abstract class MethodVisitor { /** * Visits a zero operand instruction. * - * @param opcode the opcode of the instruction to be visited. This opcode is - * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, - * ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0, - * FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD, - * DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE, - * DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP, - * DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD, - * DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, - * FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, - * LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, - * I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, - * I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, - * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, - * MONITORENTER, or MONITOREXIT. + * @param opcode + * the opcode of the instruction to be visited. This opcode is + * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, + * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, + * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, + * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, + * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, + * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, + * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, + * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, + * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, + * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, + * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, + * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, + * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, + * or MONITOREXIT. */ public void visitInsn(int opcode) { if (mv != null) { @@ -256,17 +281,20 @@ public abstract class MethodVisitor { /** * Visits an instruction with a single int operand. * - * @param opcode the opcode of the instruction to be visited. This opcode is - * either BIPUSH, SIPUSH or NEWARRAY. - * @param operand the operand of the instruction to be visited.<br> When - * opcode is BIPUSH, operand value should be between Byte.MIN_VALUE - * and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value - * should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When - * opcode is NEWARRAY, operand value should be one of - * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, - * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, - * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, - * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. + * @param opcode + * the opcode of the instruction to be visited. This opcode is + * either BIPUSH, SIPUSH or NEWARRAY. + * @param operand + * the operand of the instruction to be visited.<br> + * When opcode is BIPUSH, operand value should be between + * Byte.MIN_VALUE and Byte.MAX_VALUE.<br> + * When opcode is SIPUSH, operand value should be between + * Short.MIN_VALUE and Short.MAX_VALUE.<br> + * When opcode is NEWARRAY, operand value should be one of + * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, + * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, + * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, + * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. */ public void visitIntInsn(int opcode, int operand) { if (mv != null) { @@ -278,11 +306,13 @@ public abstract class MethodVisitor { * Visits a local variable instruction. A local variable instruction is an * instruction that loads or stores the value of a local variable. * - * @param opcode the opcode of the local variable instruction to be visited. - * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, - * LSTORE, FSTORE, DSTORE, ASTORE or RET. - * @param var the operand of the instruction to be visited. This operand is - * the index of a local variable. + * @param opcode + * the opcode of the local variable instruction to be visited. + * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, + * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. + * @param var + * the operand of the instruction to be visited. This operand is + * the index of a local variable. */ public void visitVarInsn(int opcode, int var) { if (mv != null) { @@ -294,11 +324,13 @@ public abstract class MethodVisitor { * Visits a type instruction. A type instruction is an instruction that * takes the internal name of a class as parameter. * - * @param opcode the opcode of the type instruction to be visited. This - * opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. - * @param type the operand of the instruction to be visited. This operand - * must be the internal name of an object or array class (see {@link - * Type#getInternalName() getInternalName}). + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. + * @param type + * the operand of the instruction to be visited. This operand + * must be the internal name of an object or array class (see + * {@link Type#getInternalName() getInternalName}). */ public void visitTypeInsn(int opcode, String type) { if (mv != null) { @@ -310,14 +342,19 @@ public abstract class MethodVisitor { * Visits a field instruction. A field instruction is an instruction that * loads or stores the value of a field of an object. * - * @param opcode the opcode of the type instruction to be visited. This - * opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. - * @param owner the internal name of the field's owner class (see {@link - * Type#getInternalName() getInternalName}). - * @param name the field's name. - * @param desc the field's descriptor (see {@link Type Type}). + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. + * @param owner + * the internal name of the field's owner class (see + * {@link Type#getInternalName() getInternalName}). + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link Type Type}). */ - public void visitFieldInsn(int opcode, String owner, String name, String desc) { + public void visitFieldInsn(int opcode, String owner, String name, + String desc) { if (mv != null) { mv.visitFieldInsn(opcode, owner, name, desc); } @@ -327,15 +364,20 @@ public abstract class MethodVisitor { * Visits a method instruction. A method instruction is an instruction that * invokes a method. * - * @param opcode the opcode of the type instruction to be visited. This - * opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC - * or INVOKEINTERFACE. - * @param owner the internal name of the method's owner class (see {@link - * Type#getInternalName() getInternalName}). - * @param name the method's name. - * @param desc the method's descriptor (see {@link Type Type}). + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner + * the internal name of the method's owner class (see + * {@link Type#getInternalName() getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). */ - public void visitMethodInsn(int opcode, String owner, String name, String desc) { + public void visitMethodInsn(int opcode, String owner, String name, + String desc) { if (mv != null) { mv.visitMethodInsn(opcode, owner, name, desc); } @@ -344,16 +386,21 @@ public abstract class MethodVisitor { /** * Visits an invokedynamic instruction. * - * @param name the method's name. - * @param desc the method's descriptor (see {@link Type Type}). - * @param bsm the bootstrap method. - * @param bsmArgs the bootstrap method constant arguments. Each argument - * must be an {@link Integer}, {@link Float}, {@link Long}, - * {@link Double}, {@link String}, {@link Type} or {@link Handle} - * value. This method is allowed to modify the content of the array - * so a caller should expect that this array may change. + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param bsm + * the bootstrap method. + * @param bsmArgs + * the bootstrap method constant arguments. Each argument must be + * an {@link Integer}, {@link Float}, {@link Long}, + * {@link Double}, {@link String}, {@link Type} or {@link Handle} + * value. This method is allowed to modify the content of the + * array so a caller should expect that this array may change. */ - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { if (mv != null) { mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); } @@ -363,13 +410,15 @@ public abstract class MethodVisitor { * Visits a jump instruction. A jump instruction is an instruction that may * jump to another instruction. * - * @param opcode the opcode of the type instruction to be visited. This - * opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, - * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, - * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. - * @param label the operand of the instruction to be visited. This operand - * is a label that designates the instruction to which the jump - * instruction may jump. + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, + * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, + * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. + * @param label + * the operand of the instruction to be visited. This operand is + * a label that designates the instruction to which the jump + * instruction may jump. */ public void visitJumpInsn(int opcode, Label label) { if (mv != null) { @@ -381,7 +430,8 @@ public abstract class MethodVisitor { * Visits a label. A label designates the instruction that will be visited * just after it. * - * @param label a {@link Label Label} object. + * @param label + * a {@link Label Label} object. */ public void visitLabel(Label label) { if (mv != null) { @@ -398,41 +448,44 @@ public abstract class MethodVisitor { * future versions of the Java Virtual Machine. To easily detect new * constant types, implementations of this method should check for * unexpected constant types, like this: + * * <pre> * if (cst instanceof Integer) { - * // ... + * // ... * } else if (cst instanceof Float) { - * // ... + * // ... * } else if (cst instanceof Long) { - * // ... - * } else if (cst instanceof Double) { - * // ... - * } else if (cst instanceof String) { - * // ... - * } else if (cst instanceof Type) { - * int sort = ((Type) cst).getSort(); - * if (sort == Type.OBJECT) { * // ... - * } else if (sort == Type.ARRAY) { + * } else if (cst instanceof Double) { * // ... - * } else if (sort == Type.METHOD) { + * } else if (cst instanceof String) { * // ... - * } else { - * // throw an exception - * } + * } else if (cst instanceof Type) { + * int sort = ((Type) cst).getSort(); + * if (sort == Type.OBJECT) { + * // ... + * } else if (sort == Type.ARRAY) { + * // ... + * } else if (sort == Type.METHOD) { + * // ... + * } else { + * // throw an exception + * } * } else if (cst instanceof Handle) { - * // ... + * // ... * } else { - * // throw an exception - * }</pre> + * // throw an exception + * } + * </pre> * - * @param cst the constant to be loaded on the stack. This parameter must be - * a non null {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double}, a {@link String}, a {@link Type} of OBJECT or ARRAY - * sort for <tt>.class</tt> constants, for classes whose version is - * 49.0, a {@link Type} of METHOD sort or a {@link Handle} for - * MethodType and MethodHandle constants, for classes whose version - * is 51.0. + * @param cst + * the constant to be loaded on the stack. This parameter must be + * a non null {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double}, a {@link String}, a {@link Type} of OBJECT or + * ARRAY sort for <tt>.class</tt> constants, for classes whose + * version is 49.0, a {@link Type} of METHOD sort or a + * {@link Handle} for MethodType and MethodHandle constants, for + * classes whose version is 51.0. */ public void visitLdcInsn(Object cst) { if (mv != null) { @@ -443,8 +496,10 @@ public abstract class MethodVisitor { /** * Visits an IINC instruction. * - * @param var index of the local variable to be incremented. - * @param increment amount to increment the local variable by. + * @param var + * index of the local variable to be incremented. + * @param increment + * amount to increment the local variable by. */ public void visitIincInsn(int var, int increment) { if (mv != null) { @@ -455,13 +510,18 @@ public abstract class MethodVisitor { /** * Visits a TABLESWITCH instruction. * - * @param min the minimum key value. - * @param max the maximum key value. - * @param dflt beginning of the default handler block. - * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is - * the beginning of the handler block for the <tt>min + i</tt> key. + * @param min + * the minimum key value. + * @param max + * the maximum key value. + * @param dflt + * beginning of the default handler block. + * @param labels + * beginnings of the handler blocks. <tt>labels[i]</tt> is the + * beginning of the handler block for the <tt>min + i</tt> key. */ - public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { + public void visitTableSwitchInsn(int min, int max, Label dflt, + Label... labels) { if (mv != null) { mv.visitTableSwitchInsn(min, max, dflt, labels); } @@ -470,10 +530,13 @@ public abstract class MethodVisitor { /** * Visits a LOOKUPSWITCH instruction. * - * @param dflt beginning of the default handler block. - * @param keys the values of the keys. - * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is - * the beginning of the handler block for the <tt>keys[i]</tt> key. + * @param dflt + * beginning of the default handler block. + * @param keys + * the values of the keys. + * @param labels + * beginnings of the handler blocks. <tt>labels[i]</tt> is the + * beginning of the handler block for the <tt>keys[i]</tt> key. */ public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { if (mv != null) { @@ -484,8 +547,10 @@ public abstract class MethodVisitor { /** * Visits a MULTIANEWARRAY instruction. * - * @param desc an array type descriptor (see {@link Type Type}). - * @param dims number of dimensions of the array to allocate. + * @param desc + * an array type descriptor (see {@link Type Type}). + * @param dims + * number of dimensions of the array to allocate. */ public void visitMultiANewArrayInsn(String desc, int dims) { if (mv != null) { @@ -500,17 +565,22 @@ public abstract class MethodVisitor { /** * Visits a try catch block. * - * @param start beginning of the exception handler's scope (inclusive). - * @param end end of the exception handler's scope (exclusive). - * @param handler beginning of the exception handler's code. - * @param type internal name of the type of exceptions handled by the - * handler, or <tt>null</tt> to catch any exceptions (for "finally" - * blocks). - * @throws IllegalArgumentException if one of the labels has already been - * visited by this visitor (by the {@link #visitLabel visitLabel} - * method). + * @param start + * beginning of the exception handler's scope (inclusive). + * @param end + * end of the exception handler's scope (exclusive). + * @param handler + * beginning of the exception handler's code. + * @param type + * internal name of the type of exceptions handled by the + * handler, or <tt>null</tt> to catch any exceptions (for + * "finally" blocks). + * @throws IllegalArgumentException + * if one of the labels has already been visited by this visitor + * (by the {@link #visitLabel visitLabel} method). */ - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { + public void visitTryCatchBlock(Label start, Label end, Label handler, + String type) { if (mv != null) { mv.visitTryCatchBlock(start, end, handler, type); } @@ -519,28 +589,28 @@ public abstract class MethodVisitor { /** * Visits a local variable declaration. * - * @param name the name of a local variable. - * @param desc the type descriptor of this local variable. - * @param signature the type signature of this local variable. May be - * <tt>null</tt> if the local variable type does not use generic - * types. - * @param start the first instruction corresponding to the scope of this - * local variable (inclusive). - * @param end the last instruction corresponding to the scope of this local - * variable (exclusive). - * @param index the local variable's index. - * @throws IllegalArgumentException if one of the labels has not already - * been visited by this visitor (by the - * {@link #visitLabel visitLabel} method). + * @param name + * the name of a local variable. + * @param desc + * the type descriptor of this local variable. + * @param signature + * the type signature of this local variable. May be + * <tt>null</tt> if the local variable type does not use generic + * types. + * @param start + * the first instruction corresponding to the scope of this local + * variable (inclusive). + * @param end + * the last instruction corresponding to the scope of this local + * variable (exclusive). + * @param index + * the local variable's index. + * @throws IllegalArgumentException + * if one of the labels has not already been visited by this + * visitor (by the {@link #visitLabel visitLabel} method). */ - public void visitLocalVariable( - String name, - String desc, - String signature, - Label start, - Label end, - int index) - { + public void visitLocalVariable(String name, String desc, String signature, + Label start, Label end, int index) { if (mv != null) { mv.visitLocalVariable(name, desc, signature, start, end, index); } @@ -549,12 +619,14 @@ public abstract class MethodVisitor { /** * Visits a line number declaration. * - * @param line a line number. This number refers to the source file from - * which the class was compiled. - * @param start the first instruction corresponding to this line number. - * @throws IllegalArgumentException if <tt>start</tt> has not already been - * visited by this visitor (by the {@link #visitLabel visitLabel} - * method). + * @param line + * a line number. This number refers to the source file from + * which the class was compiled. + * @param start + * the first instruction corresponding to this line number. + * @throws IllegalArgumentException + * if <tt>start</tt> has not already been visited by this + * visitor (by the {@link #visitLabel visitLabel} method). */ public void visitLineNumber(int line, Label start) { if (mv != null) { @@ -566,8 +638,10 @@ public abstract class MethodVisitor { * Visits the maximum stack size and the maximum number of local variables * of the method. * - * @param maxStack maximum stack size of the method. - * @param maxLocals maximum number of local variables for the method. + * @param maxStack + * maximum stack size of the method. + * @param maxLocals + * maximum number of local variables for the method. */ public void visitMaxs(int maxStack, int maxLocals) { if (mv != null) { diff --git a/src/asm/scala/tools/asm/MethodWriter.java b/src/asm/scala/tools/asm/MethodWriter.java index 321bacb6fc..f5fbd1e74f 100644 --- a/src/asm/scala/tools/asm/MethodWriter.java +++ b/src/asm/scala/tools/asm/MethodWriter.java @@ -42,7 +42,7 @@ class MethodWriter extends MethodVisitor { /** * Pseudo access flag used to denote constructors. */ - static final int ACC_CONSTRUCTOR = 262144; + static final int ACC_CONSTRUCTOR = 0x80000; /** * Frame has exactly the same locals as the previous stack map frame and @@ -229,7 +229,7 @@ class MethodWriter extends MethodVisitor { private int maxLocals; /** - * Number of local variables in the current stack map frame. + * Number of local variables in the current stack map frame. */ private int currentLocals; @@ -257,11 +257,6 @@ class MethodWriter extends MethodVisitor { private int[] previousFrame; /** - * Index of the next element to be added in {@link #frame}. - */ - private int frameIndex; - - /** * The current stack map frame. The first element contains the offset of the * instruction to which the frame corresponds, the second element is the * number of locals and the third one is the number of stack elements. The @@ -357,7 +352,8 @@ class MethodWriter extends MethodVisitor { * A list of labels. This list is the list of basic blocks in the method, * i.e. a list of Label objects linked to each other by their * {@link Label#successor} field, in the order they are visited by - * {@link MethodVisitor#visitLabel}, and starting with the first basic block. + * {@link MethodVisitor#visitLabel}, and starting with the first basic + * block. */ private Label labels; @@ -396,28 +392,30 @@ class MethodWriter extends MethodVisitor { /** * Constructs a new {@link MethodWriter}. * - * @param cw the class writer in which the method must be added. - * @param access the method's access flags (see {@link Opcodes}). - * @param name the method's name. - * @param desc the method's descriptor (see {@link Type}). - * @param signature the method's signature. May be <tt>null</tt>. - * @param exceptions the internal names of the method's exceptions. May be - * <tt>null</tt>. - * @param computeMaxs <tt>true</tt> if the maximum stack size and number - * of local variables must be automatically computed. - * @param computeFrames <tt>true</tt> if the stack map tables must be - * recomputed from scratch. - */ - MethodWriter( - final ClassWriter cw, - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions, - final boolean computeMaxs, - final boolean computeFrames) - { + * @param cw + * the class writer in which the method must be added. + * @param access + * the method's access flags (see {@link Opcodes}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type}). + * @param signature + * the method's signature. May be <tt>null</tt>. + * @param exceptions + * the internal names of the method's exceptions. May be + * <tt>null</tt>. + * @param computeMaxs + * <tt>true</tt> if the maximum stack size and number of local + * variables must be automatically computed. + * @param computeFrames + * <tt>true</tt> if the stack map tables must be recomputed from + * scratch. + */ + MethodWriter(final ClassWriter cw, final int access, final String name, + final String desc, final String signature, + final String[] exceptions, final boolean computeMaxs, + final boolean computeFrames) { super(Opcodes.ASM4); if (cw.firstMethod == null) { cw.firstMethod = this; @@ -427,6 +425,9 @@ class MethodWriter extends MethodVisitor { cw.lastMethod = this; this.cw = cw; this.access = access; + if ("<init>".equals(name)) { + this.access |= ACC_CONSTRUCTOR; + } this.name = cw.newUTF8(name); this.desc = cw.newUTF8(desc); this.descriptor = desc; @@ -442,9 +443,6 @@ class MethodWriter extends MethodVisitor { } this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); if (computeMaxs || computeFrames) { - if (computeFrames && "<init>".equals(name)) { - this.access |= ACC_CONSTRUCTOR; - } // updates maxLocals int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2; if ((access & Opcodes.ACC_STATIC) != 0) { @@ -473,10 +471,8 @@ class MethodWriter extends MethodVisitor { } @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } @@ -495,11 +491,8 @@ class MethodWriter extends MethodVisitor { } @Override - public AnnotationVisitor visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) - { + public AnnotationVisitor visitParameterAnnotation(final int parameter, + final String desc, final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } @@ -545,20 +538,18 @@ class MethodWriter extends MethodVisitor { } @Override - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) - { + public void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack) { if (!ClassReader.FRAMES || compute == FRAMES) { return; } if (type == Opcodes.F_NEW) { + if (previousFrame == null) { + visitImplicitFirstFrame(); + } currentLocals = nLocal; - startFrame(code.length, nLocal, nStack); + int frameIndex = startFrame(code.length, nLocal, nStack); for (int i = 0; i < nLocal; ++i) { if (local[i] instanceof String) { frame[frameIndex++] = Frame.OBJECT @@ -601,48 +592,44 @@ class MethodWriter extends MethodVisitor { } switch (type) { - case Opcodes.F_FULL: - currentLocals = nLocal; - stackMap.putByte(FULL_FRAME) - .putShort(delta) - .putShort(nLocal); - for (int i = 0; i < nLocal; ++i) { - writeFrameType(local[i]); - } - stackMap.putShort(nStack); - for (int i = 0; i < nStack; ++i) { - writeFrameType(stack[i]); - } - break; - case Opcodes.F_APPEND: - currentLocals += nLocal; - stackMap.putByte(SAME_FRAME_EXTENDED + nLocal) - .putShort(delta); - for (int i = 0; i < nLocal; ++i) { - writeFrameType(local[i]); - } - break; - case Opcodes.F_CHOP: - currentLocals -= nLocal; - stackMap.putByte(SAME_FRAME_EXTENDED - nLocal) + case Opcodes.F_FULL: + currentLocals = nLocal; + stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal); + for (int i = 0; i < nLocal; ++i) { + writeFrameType(local[i]); + } + stackMap.putShort(nStack); + for (int i = 0; i < nStack; ++i) { + writeFrameType(stack[i]); + } + break; + case Opcodes.F_APPEND: + currentLocals += nLocal; + stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta); + for (int i = 0; i < nLocal; ++i) { + writeFrameType(local[i]); + } + break; + case Opcodes.F_CHOP: + currentLocals -= nLocal; + stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta); + break; + case Opcodes.F_SAME: + if (delta < 64) { + stackMap.putByte(delta); + } else { + stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); + } + break; + case Opcodes.F_SAME1: + if (delta < 64) { + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); + } else { + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) .putShort(delta); - break; - case Opcodes.F_SAME: - if (delta < 64) { - stackMap.putByte(delta); - } else { - stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); - } - break; - case Opcodes.F_SAME1: - if (delta < 64) { - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); - } else { - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) - .putShort(delta); - } - writeFrameType(stack[0]); - break; + } + writeFrameType(stack[0]); + break; } previousFrameOffset = code.length; @@ -672,8 +659,7 @@ class MethodWriter extends MethodVisitor { } // if opcode == ATHROW or xRETURN, ends current block (no successor) if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) - || opcode == Opcodes.ATHROW) - { + || opcode == Opcodes.ATHROW) { noSuccessor(); } } @@ -731,8 +717,7 @@ class MethodWriter extends MethodVisitor { // updates max locals int n; if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD - || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) - { + || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) { n = var + 2; } else { n = var + 1; @@ -784,12 +769,8 @@ class MethodWriter extends MethodVisitor { } @Override - public void visitFieldInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc) { Item i = cw.newFieldItem(owner, name, desc); // Label currentBlock = this.currentBlock; if (currentBlock != null) { @@ -800,19 +781,19 @@ class MethodWriter extends MethodVisitor { // computes the stack size variation char c = desc.charAt(0); switch (opcode) { - case Opcodes.GETSTATIC: - size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); - break; - case Opcodes.PUTSTATIC: - size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); - break; - case Opcodes.GETFIELD: - size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); - break; - // case Constants.PUTFIELD: - default: - size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); - break; + case Opcodes.GETSTATIC: + size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); + break; + case Opcodes.PUTSTATIC: + size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); + break; + case Opcodes.GETFIELD: + size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); + break; + // case Constants.PUTFIELD: + default: + size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); + break; } // updates current and max stack sizes if (size > maxStackSize) { @@ -826,12 +807,8 @@ class MethodWriter extends MethodVisitor { } @Override - public void visitMethodInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { boolean itf = opcode == Opcodes.INVOKEINTERFACE; Item i = cw.newMethodItem(owner, name, desc, itf); int argSize = i.intVal; @@ -882,12 +859,8 @@ class MethodWriter extends MethodVisitor { } @Override - public void visitInvokeDynamicInsn( - final String name, - final String desc, - final Handle bsm, - final Object... bsmArgs) - { + public void visitInvokeDynamicInsn(final String name, final String desc, + final Handle bsm, final Object... bsmArgs) { Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs); int argSize = i.intVal; // Label currentBlock = this.currentBlock; @@ -967,8 +940,7 @@ class MethodWriter extends MethodVisitor { } // adds the instruction to the bytecode of the method if ((label.status & Label.RESOLVED) != 0 - && label.position - code.length < Short.MIN_VALUE) - { + && label.position - code.length < Short.MIN_VALUE) { /* * case of a backward jump with an offset < -32768. In this case we * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx @@ -986,8 +958,7 @@ class MethodWriter extends MethodVisitor { if (nextInsn != null) { nextInsn.status |= Label.TARGET; } - code.putByte(opcode <= 166 - ? ((opcode + 1) ^ 1) - 1 + code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); code.putShort(8); // jump offset code.putByte(200); // GOTO_W @@ -1082,8 +1053,7 @@ class MethodWriter extends MethodVisitor { } else { int size; // computes the stack size variation - if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) - { + if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { size = stackSize + 2; } else { size = stackSize + 1; @@ -1122,8 +1092,7 @@ class MethodWriter extends MethodVisitor { } // adds the instruction to the bytecode of the method if ((var > 255) || (increment > 127) || (increment < -128)) { - code.putByte(196 /* WIDE */) - .put12(Opcodes.IINC, var) + code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var) .putShort(increment); } else { code.putByte(Opcodes.IINC).put11(var, increment); @@ -1131,12 +1100,8 @@ class MethodWriter extends MethodVisitor { } @Override - public void visitTableSwitchInsn( - final int min, - final int max, - final Label dflt, - final Label... labels) - { + public void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels) { // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.TABLESWITCH); @@ -1151,11 +1116,8 @@ class MethodWriter extends MethodVisitor { } @Override - public void visitLookupSwitchInsn( - final Label dflt, - final int[] keys, - final Label[] labels) - { + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, + final Label[] labels) { // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.LOOKUPSWITCH); @@ -1214,12 +1176,8 @@ class MethodWriter extends MethodVisitor { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type) { ++handlerCount; Handler h = new Handler(); h.start = start; @@ -1236,14 +1194,9 @@ class MethodWriter extends MethodVisitor { } @Override - public void visitLocalVariable( - final String name, - final String desc, - final String signature, - final Label start, - final Label end, - final int index) - { + public void visitLocalVariable(final String name, final String desc, + final String signature, final Label start, final Label end, + final int index) { if (signature != null) { if (localVarType == null) { localVarType = new ByteVector(); @@ -1251,8 +1204,7 @@ class MethodWriter extends MethodVisitor { ++localVarTypeCount; localVarType.putShort(start.position) .putShort(end.position - start.position) - .putShort(cw.newUTF8(name)) - .putShort(cw.newUTF8(signature)) + .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature)) .putShort(index); } if (localVar == null) { @@ -1261,8 +1213,7 @@ class MethodWriter extends MethodVisitor { ++localVarCount; localVar.putShort(start.position) .putShort(end.position - start.position) - .putShort(cw.newUTF8(name)) - .putShort(cw.newUTF8(desc)) + .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc)) .putShort(index); if (compute != NOTHING) { // updates max locals @@ -1294,8 +1245,7 @@ class MethodWriter extends MethodVisitor { Label h = handler.handler.getFirst(); Label e = handler.end.getFirst(); // computes the kind of the edges to 'h' - String t = handler.desc == null - ? "java/lang/Throwable" + String t = handler.desc == null ? "java/lang/Throwable" : handler.desc; int kind = Frame.OBJECT | cw.addType(t); // h is an exception handler @@ -1382,11 +1332,12 @@ class MethodWriter extends MethodVisitor { } code.data[end] = (byte) Opcodes.ATHROW; // emits a frame for this unreachable block - startFrame(start, 0, 1); - frame[frameIndex++] = Frame.OBJECT + int frameIndex = startFrame(start, 0, 1); + frame[frameIndex] = Frame.OBJECT | cw.addType("java/lang/Throwable"); endFrame(); - // removes the start-end range from the exception handlers + // removes the start-end range from the exception + // handlers firstHandler = Handler.remove(firstHandler, l, k); } } @@ -1535,8 +1486,10 @@ class MethodWriter extends MethodVisitor { /** * Adds a successor to the {@link #currentBlock currentBlock} block. * - * @param info information about the control flow edge to be added. - * @param successor the successor block to be added to the current block. + * @param info + * information about the control flow edge to be added. + * @param successor + * the successor block to be added to the current block. */ private void addSuccessor(final int info, final Label successor) { // creates and initializes an Edge object... @@ -1573,7 +1526,8 @@ class MethodWriter extends MethodVisitor { /** * Visits a frame that has been computed from scratch. * - * @param f the frame that must be visited. + * @param f + * the frame that must be visited. */ private void visitFrame(final Frame f) { int i, t; @@ -1606,7 +1560,7 @@ class MethodWriter extends MethodVisitor { } } // visits the frame and its content - startFrame(f.owner.position, nLocal, nStack); + int frameIndex = startFrame(f.owner.position, nLocal, nStack); for (i = 0; nLocal > 0; ++i, --nLocal) { t = locals[i]; frame[frameIndex++] = t; @@ -1625,15 +1579,78 @@ class MethodWriter extends MethodVisitor { } /** + * Visit the implicit first frame of this method. + */ + private void visitImplicitFirstFrame() { + // There can be at most descriptor.length() + 1 locals + int frameIndex = startFrame(0, descriptor.length() + 1, 0); + if ((access & Opcodes.ACC_STATIC) == 0) { + if ((access & ACC_CONSTRUCTOR) == 0) { + frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName); + } else { + frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS; + } + } + int i = 1; + loop: while (true) { + int j = i; + switch (descriptor.charAt(i++)) { + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + frame[frameIndex++] = 1; // Opcodes.INTEGER; + break; + case 'F': + frame[frameIndex++] = 2; // Opcodes.FLOAT; + break; + case 'J': + frame[frameIndex++] = 4; // Opcodes.LONG; + break; + case 'D': + frame[frameIndex++] = 3; // Opcodes.DOUBLE; + break; + case '[': + while (descriptor.charAt(i) == '[') { + ++i; + } + if (descriptor.charAt(i) == 'L') { + ++i; + while (descriptor.charAt(i) != ';') { + ++i; + } + } + frame[frameIndex++] = Frame.OBJECT + | cw.addType(descriptor.substring(j, ++i)); + break; + case 'L': + while (descriptor.charAt(i) != ';') { + ++i; + } + frame[frameIndex++] = Frame.OBJECT + | cw.addType(descriptor.substring(j + 1, i++)); + break; + default: + break loop; + } + } + frame[1] = frameIndex - 3; + endFrame(); + } + + /** * Starts the visit of a stack map frame. * - * @param offset the offset of the instruction to which the frame - * corresponds. - * @param nLocal the number of local variables in the frame. - * @param nStack the number of stack elements in the frame. - */ - private void startFrame(final int offset, final int nLocal, final int nStack) - { + * @param offset + * the offset of the instruction to which the frame corresponds. + * @param nLocal + * the number of local variables in the frame. + * @param nStack + * the number of stack elements in the frame. + * @return the index of the next element to be written in this frame. + */ + private int startFrame(final int offset, final int nLocal, final int nStack) { int n = 3 + nLocal + nStack; if (frame == null || frame.length < n) { frame = new int[n]; @@ -1641,7 +1658,7 @@ class MethodWriter extends MethodVisitor { frame[0] = offset; frame[1] = nLocal; frame[2] = nStack; - frameIndex = 3; + return 3; } /** @@ -1686,24 +1703,23 @@ class MethodWriter extends MethodVisitor { if (cstackSize == 0) { k = clocalsSize - localsSize; switch (k) { - case -3: - case -2: - case -1: - type = CHOP_FRAME; - localsSize = clocalsSize; - break; - case 0: - type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED; - break; - case 1: - case 2: - case 3: - type = APPEND_FRAME; - break; + case -3: + case -2: + case -1: + type = CHOP_FRAME; + localsSize = clocalsSize; + break; + case 0: + type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED; + break; + case 1: + case 2: + case 3: + type = APPEND_FRAME; + break; } } else if (clocalsSize == localsSize && cstackSize == 1) { - type = delta < 63 - ? SAME_LOCALS_1_STACK_ITEM_FRAME + type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED; } if (type != FULL_FRAME) { @@ -1718,36 +1734,34 @@ class MethodWriter extends MethodVisitor { } } switch (type) { - case SAME_FRAME: - stackMap.putByte(delta); - break; - case SAME_LOCALS_1_STACK_ITEM_FRAME: - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); - writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); - break; - case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) - .putShort(delta); - writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); - break; - case SAME_FRAME_EXTENDED: - stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); - break; - case CHOP_FRAME: - stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); - break; - case APPEND_FRAME: - stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); - writeFrameTypes(3 + localsSize, 3 + clocalsSize); - break; - // case FULL_FRAME: - default: - stackMap.putByte(FULL_FRAME) - .putShort(delta) - .putShort(clocalsSize); - writeFrameTypes(3, 3 + clocalsSize); - stackMap.putShort(cstackSize); - writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); + case SAME_FRAME: + stackMap.putByte(delta); + break; + case SAME_LOCALS_1_STACK_ITEM_FRAME: + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); + writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); + break; + case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort( + delta); + writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); + break; + case SAME_FRAME_EXTENDED: + stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); + break; + case CHOP_FRAME: + stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); + break; + case APPEND_FRAME: + stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); + writeFrameTypes(3 + localsSize, 3 + clocalsSize); + break; + // case FULL_FRAME: + default: + stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize); + writeFrameTypes(3, 3 + clocalsSize); + stackMap.putShort(cstackSize); + writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); } } @@ -1757,8 +1771,10 @@ class MethodWriter extends MethodVisitor { * in {@link Label} to the format used in StackMapTable attributes. In * particular, it converts type table indexes to constant pool indexes. * - * @param start index of the first type in {@link #frame} to write. - * @param end index of last type in {@link #frame} to write (exclusive). + * @param start + * index of the first type in {@link #frame} to write. + * @param end + * index of last type in {@link #frame} to write (exclusive). */ private void writeFrameTypes(final int start, final int end) { for (int i = start; i < end; ++i) { @@ -1767,15 +1783,15 @@ class MethodWriter extends MethodVisitor { if (d == 0) { int v = t & Frame.BASE_VALUE; switch (t & Frame.BASE_KIND) { - case Frame.OBJECT: - stackMap.putByte(7) - .putShort(cw.newClass(cw.typeTable[v].strVal1)); - break; - case Frame.UNINITIALIZED: - stackMap.putByte(8).putShort(cw.typeTable[v].intVal); - break; - default: - stackMap.putByte(v); + case Frame.OBJECT: + stackMap.putByte(7).putShort( + cw.newClass(cw.typeTable[v].strVal1)); + break; + case Frame.UNINITIALIZED: + stackMap.putByte(8).putShort(cw.typeTable[v].intVal); + break; + default: + stackMap.putByte(v); } } else { StringBuffer buf = new StringBuffer(); @@ -1789,29 +1805,29 @@ class MethodWriter extends MethodVisitor { buf.append(';'); } else { switch (t & 0xF) { - case 1: - buf.append('I'); - break; - case 2: - buf.append('F'); - break; - case 3: - buf.append('D'); - break; - case 9: - buf.append('Z'); - break; - case 10: - buf.append('B'); - break; - case 11: - buf.append('C'); - break; - case 12: - buf.append('S'); - break; - default: - buf.append('J'); + case 1: + buf.append('I'); + break; + case 2: + buf.append('F'); + break; + case 3: + buf.append('D'); + break; + case 9: + buf.append('Z'); + break; + case 10: + buf.append('B'); + break; + case 11: + buf.append('C'); + break; + case 12: + buf.append('S'); + break; + default: + buf.append('J'); } } stackMap.putByte(7).putShort(cw.newClass(buf.toString())); @@ -1875,10 +1891,7 @@ class MethodWriter extends MethodVisitor { size += 8 + stackMap.length; } if (cattrs != null) { - size += cattrs.getSize(cw, - code.data, - code.length, - maxStack, + size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals); } } @@ -1886,11 +1899,12 @@ class MethodWriter extends MethodVisitor { cw.newUTF8("Exceptions"); size += 8 + 2 * exceptionCount; } - if ((access & Opcodes.ACC_SYNTHETIC) != 0 - && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0)) - { - cw.newUTF8("Synthetic"); - size += 6; + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + cw.newUTF8("Synthetic"); + size += 6; + } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { cw.newUTF8("Deprecated"); @@ -1936,13 +1950,15 @@ class MethodWriter extends MethodVisitor { /** * Puts the bytecode of this method in the given byte vector. * - * @param out the byte vector into which the bytecode of this method must be - * copied. + * @param out + * the byte vector into which the bytecode of this method must be + * copied. */ final void put(final ByteVector out) { - int mask = Opcodes.ACC_DEPRECATED + final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; + int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC)); + | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); out.putShort(access & ~mask).putShort(name).putShort(desc); if (classReaderOffset != 0) { out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); @@ -1955,10 +1971,11 @@ class MethodWriter extends MethodVisitor { if (exceptionCount > 0) { ++attributeCount; } - if ((access & Opcodes.ACC_SYNTHETIC) != 0 - && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0)) - { - ++attributeCount; + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + ++attributeCount; + } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; @@ -2000,10 +2017,7 @@ class MethodWriter extends MethodVisitor { size += 8 + stackMap.length; } if (cattrs != null) { - size += cattrs.getSize(cw, - code.data, - code.length, - maxStack, + size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals); } out.putShort(cw.newUTF8("Code")).putInt(size); @@ -2013,10 +2027,8 @@ class MethodWriter extends MethodVisitor { if (handlerCount > 0) { Handler h = firstHandler; while (h != null) { - out.putShort(h.start.position) - .putShort(h.end.position) - .putShort(h.handler.position) - .putShort(h.type); + out.putShort(h.start.position).putShort(h.end.position) + .putShort(h.handler.position).putShort(h.type); h = h.next; } } @@ -2063,24 +2075,24 @@ class MethodWriter extends MethodVisitor { } } if (exceptionCount > 0) { - out.putShort(cw.newUTF8("Exceptions")) - .putInt(2 * exceptionCount + 2); + out.putShort(cw.newUTF8("Exceptions")).putInt( + 2 * exceptionCount + 2); out.putShort(exceptionCount); for (int i = 0; i < exceptionCount; ++i) { out.putShort(exceptions[i]); } } - if ((access & Opcodes.ACC_SYNTHETIC) != 0 - && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0)) - { - out.putShort(cw.newUTF8("Synthetic")).putInt(0); + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + out.putShort(cw.newUTF8("Synthetic")).putInt(0); + } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); } if (ClassReader.SIGNATURES && signature != null) { - out.putShort(cw.newUTF8("Signature")) - .putInt(2) + out.putShort(cw.newUTF8("Signature")).putInt(2) .putShort(cw.newUTF8(signature)); } if (ClassReader.ANNOTATIONS && annd != null) { @@ -2123,10 +2135,12 @@ class MethodWriter extends MethodVisitor { * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W * 32765. This, in turn, may require to increase the size of another jump * instruction, and so on... All these operations are handled automatically - * by this method. <p> <i>This method must be called after all the method - * that is being built has been visited</i>. In particular, the - * {@link Label Label} objects used to construct the method are no longer - * valid after this method has been called. + * by this method. + * <p> + * <i>This method must be called after all the method that is being built + * has been visited</i>. In particular, the {@link Label Label} objects used + * to construct the method are no longer valid after this method has been + * called. */ private void resizeInstructions() { byte[] b = code.data; // bytecode of the method @@ -2176,158 +2190,14 @@ class MethodWriter extends MethodVisitor { int insert = 0; // bytes to be added after this instruction switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - u += 1; - break; - case ClassWriter.LABEL_INSN: - if (opcode > 201) { - // converts temporary opcodes 202 to 217, 218 and - // 219 to IFEQ ... JSR (inclusive), IFNULL and - // IFNONNULL - opcode = opcode < 218 ? opcode - 49 : opcode - 20; - label = u + readUnsignedShort(b, u + 1); - } else { - label = u + readShort(b, u + 1); - } - newOffset = getNewOffset(allIndexes, allSizes, u, label); - if (newOffset < Short.MIN_VALUE - || newOffset > Short.MAX_VALUE) - { - if (!resize[u]) { - if (opcode == Opcodes.GOTO - || opcode == Opcodes.JSR) - { - // two additional bytes will be required to - // replace this GOTO or JSR instruction with - // a GOTO_W or a JSR_W - insert = 2; - } else { - // five additional bytes will be required to - // replace this IFxxx <l> instruction with - // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx - // is the "opposite" opcode of IFxxx (i.e., - // IFNE for IFEQ) and where <l'> designates - // the instruction just after the GOTO_W. - insert = 5; - } - resize[u] = true; - } - } - u += 3; - break; - case ClassWriter.LABELW_INSN: - u += 5; - break; - case ClassWriter.TABL_INSN: - if (state == 1) { - // true number of bytes to be added (or removed) - // from this instruction = (future number of padding - // bytes - current number of padding byte) - - // previously over estimated variation = - // = ((3 - newOffset%4) - (3 - u%4)) - u%4 - // = (-newOffset%4 + u%4) - u%4 - // = -(newOffset & 3) - newOffset = getNewOffset(allIndexes, allSizes, 0, u); - insert = -(newOffset & 3); - } else if (!resize[u]) { - // over estimation of the number of bytes to be - // added to this instruction = 3 - current number - // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3 - insert = u & 3; - resize[u] = true; - } - // skips instruction - u = u + 4 - (u & 3); - u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; - break; - case ClassWriter.LOOK_INSN: - if (state == 1) { - // like TABL_INSN - newOffset = getNewOffset(allIndexes, allSizes, 0, u); - insert = -(newOffset & 3); - } else if (!resize[u]) { - // like TABL_INSN - insert = u & 3; - resize[u] = true; - } - // skips instruction - u = u + 4 - (u & 3); - u += 8 * readInt(b, u + 4) + 8; - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - u += 6; - } else { - u += 4; - } - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - u += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - u += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - u += 5; - break; - // case ClassWriter.MANA_INSN: - default: - u += 4; - break; - } - if (insert != 0) { - // adds a new (u, insert) entry in the allIndexes and - // allSizes arrays - int[] newIndexes = new int[allIndexes.length + 1]; - int[] newSizes = new int[allSizes.length + 1]; - System.arraycopy(allIndexes, - 0, - newIndexes, - 0, - allIndexes.length); - System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); - newIndexes[allIndexes.length] = u; - newSizes[allSizes.length] = insert; - allIndexes = newIndexes; - allSizes = newSizes; - if (insert > 0) { - state = 3; - } - } - } - if (state < 3) { - --state; - } - } while (state != 0); - - // 2nd step: - // copies the bytecode of the method into a new bytevector, updates the - // offsets, and inserts (or removes) bytes as requested. - - ByteVector newCode = new ByteVector(code.length); - - u = 0; - while (u < code.length) { - int opcode = b[u] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { case ClassWriter.NOARG_INSN: case ClassWriter.IMPLVAR_INSN: - newCode.putByte(opcode); u += 1; break; case ClassWriter.LABEL_INSN: if (opcode > 201) { - // changes temporary opcodes 202 to 217 (inclusive), 218 - // and 219 to IFEQ ... JSR (inclusive), IFNULL and + // converts temporary opcodes 202 to 217, 218 and + // 219 to IFEQ ... JSR (inclusive), IFNULL and // IFNONNULL opcode = opcode < 218 ? opcode - 49 : opcode - 20; label = u + readUnsignedShort(b, u + 1); @@ -2335,100 +2205,78 @@ class MethodWriter extends MethodVisitor { label = u + readShort(b, u + 1); } newOffset = getNewOffset(allIndexes, allSizes, u, label); - if (resize[u]) { - // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx - // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is - // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) - // and where <l'> designates the instruction just after - // the GOTO_W. - if (opcode == Opcodes.GOTO) { - newCode.putByte(200); // GOTO_W - } else if (opcode == Opcodes.JSR) { - newCode.putByte(201); // JSR_W - } else { - newCode.putByte(opcode <= 166 - ? ((opcode + 1) ^ 1) - 1 - : opcode ^ 1); - newCode.putShort(8); // jump offset - newCode.putByte(200); // GOTO_W - // newOffset now computed from start of GOTO_W - newOffset -= 3; + if (newOffset < Short.MIN_VALUE + || newOffset > Short.MAX_VALUE) { + if (!resize[u]) { + if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { + // two additional bytes will be required to + // replace this GOTO or JSR instruction with + // a GOTO_W or a JSR_W + insert = 2; + } else { + // five additional bytes will be required to + // replace this IFxxx <l> instruction with + // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx + // is the "opposite" opcode of IFxxx (i.e., + // IFNE for IFEQ) and where <l'> designates + // the instruction just after the GOTO_W. + insert = 5; + } + resize[u] = true; } - newCode.putInt(newOffset); - } else { - newCode.putByte(opcode); - newCode.putShort(newOffset); } u += 3; break; case ClassWriter.LABELW_INSN: - label = u + readInt(b, u + 1); - newOffset = getNewOffset(allIndexes, allSizes, u, label); - newCode.putByte(opcode); - newCode.putInt(newOffset); u += 5; break; case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes - v = u; - u = u + 4 - (v & 3); - // reads and copies instruction - newCode.putByte(Opcodes.TABLESWITCH); - newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - j = readInt(b, u); - u += 4; - newCode.putInt(j); - j = readInt(b, u) - j + 1; - u += 4; - newCode.putInt(readInt(b, u - 4)); - for (; j > 0; --j) { - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); + if (state == 1) { + // true number of bytes to be added (or removed) + // from this instruction = (future number of padding + // bytes - current number of padding byte) - + // previously over estimated variation = + // = ((3 - newOffset%4) - (3 - u%4)) - u%4 + // = (-newOffset%4 + u%4) - u%4 + // = -(newOffset & 3) + newOffset = getNewOffset(allIndexes, allSizes, 0, u); + insert = -(newOffset & 3); + } else if (!resize[u]) { + // over estimation of the number of bytes to be + // added to this instruction = 3 - current number + // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3 + insert = u & 3; + resize[u] = true; } + // skips instruction + u = u + 4 - (u & 3); + u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; break; case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes - v = u; - u = u + 4 - (v & 3); - // reads and copies instruction - newCode.putByte(Opcodes.LOOKUPSWITCH); - newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - j = readInt(b, u); - u += 4; - newCode.putInt(j); - for (; j > 0; --j) { - newCode.putInt(readInt(b, u)); - u += 4; - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); + if (state == 1) { + // like TABL_INSN + newOffset = getNewOffset(allIndexes, allSizes, 0, u); + insert = -(newOffset & 3); + } else if (!resize[u]) { + // like TABL_INSN + insert = u & 3; + resize[u] = true; } + // skips instruction + u = u + 4 - (u & 3); + u += 8 * readInt(b, u + 4) + 8; break; case ClassWriter.WIDE_INSN: opcode = b[u + 1] & 0xFF; if (opcode == Opcodes.IINC) { - newCode.putByteArray(b, u, 6); u += 6; } else { - newCode.putByteArray(b, u, 4); u += 4; } break; case ClassWriter.VAR_INSN: case ClassWriter.SBYTE_INSN: case ClassWriter.LDC_INSN: - newCode.putByteArray(b, u, 2); u += 2; break; case ClassWriter.SHORT_INSN: @@ -2436,19 +2284,178 @@ class MethodWriter extends MethodVisitor { case ClassWriter.FIELDORMETH_INSN: case ClassWriter.TYPE_INSN: case ClassWriter.IINC_INSN: - newCode.putByteArray(b, u, 3); u += 3; break; case ClassWriter.ITFMETH_INSN: case ClassWriter.INDYMETH_INSN: - newCode.putByteArray(b, u, 5); u += 5; break; - // case MANA_INSN: + // case ClassWriter.MANA_INSN: default: - newCode.putByteArray(b, u, 4); u += 4; break; + } + if (insert != 0) { + // adds a new (u, insert) entry in the allIndexes and + // allSizes arrays + int[] newIndexes = new int[allIndexes.length + 1]; + int[] newSizes = new int[allSizes.length + 1]; + System.arraycopy(allIndexes, 0, newIndexes, 0, + allIndexes.length); + System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); + newIndexes[allIndexes.length] = u; + newSizes[allSizes.length] = insert; + allIndexes = newIndexes; + allSizes = newSizes; + if (insert > 0) { + state = 3; + } + } + } + if (state < 3) { + --state; + } + } while (state != 0); + + // 2nd step: + // copies the bytecode of the method into a new bytevector, updates the + // offsets, and inserts (or removes) bytes as requested. + + ByteVector newCode = new ByteVector(code.length); + + u = 0; + while (u < code.length) { + int opcode = b[u] & 0xFF; + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + case ClassWriter.IMPLVAR_INSN: + newCode.putByte(opcode); + u += 1; + break; + case ClassWriter.LABEL_INSN: + if (opcode > 201) { + // changes temporary opcodes 202 to 217 (inclusive), 218 + // and 219 to IFEQ ... JSR (inclusive), IFNULL and + // IFNONNULL + opcode = opcode < 218 ? opcode - 49 : opcode - 20; + label = u + readUnsignedShort(b, u + 1); + } else { + label = u + readShort(b, u + 1); + } + newOffset = getNewOffset(allIndexes, allSizes, u, label); + if (resize[u]) { + // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx + // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is + // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) + // and where <l'> designates the instruction just after + // the GOTO_W. + if (opcode == Opcodes.GOTO) { + newCode.putByte(200); // GOTO_W + } else if (opcode == Opcodes.JSR) { + newCode.putByte(201); // JSR_W + } else { + newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 + : opcode ^ 1); + newCode.putShort(8); // jump offset + newCode.putByte(200); // GOTO_W + // newOffset now computed from start of GOTO_W + newOffset -= 3; + } + newCode.putInt(newOffset); + } else { + newCode.putByte(opcode); + newCode.putShort(newOffset); + } + u += 3; + break; + case ClassWriter.LABELW_INSN: + label = u + readInt(b, u + 1); + newOffset = getNewOffset(allIndexes, allSizes, u, label); + newCode.putByte(opcode); + newCode.putInt(newOffset); + u += 5; + break; + case ClassWriter.TABL_INSN: + // skips 0 to 3 padding bytes + v = u; + u = u + 4 - (v & 3); + // reads and copies instruction + newCode.putByte(Opcodes.TABLESWITCH); + newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + j = readInt(b, u); + u += 4; + newCode.putInt(j); + j = readInt(b, u) - j + 1; + u += 4; + newCode.putInt(readInt(b, u - 4)); + for (; j > 0; --j) { + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + } + break; + case ClassWriter.LOOK_INSN: + // skips 0 to 3 padding bytes + v = u; + u = u + 4 - (v & 3); + // reads and copies instruction + newCode.putByte(Opcodes.LOOKUPSWITCH); + newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + j = readInt(b, u); + u += 4; + newCode.putInt(j); + for (; j > 0; --j) { + newCode.putInt(readInt(b, u)); + u += 4; + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + } + break; + case ClassWriter.WIDE_INSN: + opcode = b[u + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + newCode.putByteArray(b, u, 6); + u += 6; + } else { + newCode.putByteArray(b, u, 4); + u += 4; + } + break; + case ClassWriter.VAR_INSN: + case ClassWriter.SBYTE_INSN: + case ClassWriter.LDC_INSN: + newCode.putByteArray(b, u, 2); + u += 2; + break; + case ClassWriter.SHORT_INSN: + case ClassWriter.LDCW_INSN: + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.TYPE_INSN: + case ClassWriter.IINC_INSN: + newCode.putByteArray(b, u, 3); + u += 3; + break; + case ClassWriter.ITFMETH_INSN: + case ClassWriter.INDYMETH_INSN: + newCode.putByteArray(b, u, 5); + u += 5; + break; + // case MANA_INSN: + default: + newCode.putByteArray(b, u, 4); + u += 4; + break; } } @@ -2471,8 +2478,7 @@ class MethodWriter extends MethodVisitor { * must therefore never have been called for this label. */ u = l.position - 3; - if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) - { + if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) { getNewOffset(allIndexes, allSizes, l); // TODO update offsets in UNINITIALIZED values visitFrame(l.frame); @@ -2528,10 +2534,11 @@ class MethodWriter extends MethodVisitor { b = lineNumber.data; u = 0; while (u < lineNumber.length) { - writeShort(b, u, getNewOffset(allIndexes, - allSizes, - 0, - readUnsignedShort(b, u))); + writeShort( + b, + u, + getNewOffset(allIndexes, allSizes, 0, + readUnsignedShort(b, u))); u += 4; } } @@ -2554,8 +2561,10 @@ class MethodWriter extends MethodVisitor { /** * Reads an unsigned short value in the given byte array. * - * @param b a byte array. - * @param index the start index of the value to be read. + * @param b + * a byte array. + * @param index + * the start index of the value to be read. * @return the read value. */ static int readUnsignedShort(final byte[] b, final int index) { @@ -2565,8 +2574,10 @@ class MethodWriter extends MethodVisitor { /** * Reads a signed short value in the given byte array. * - * @param b a byte array. - * @param index the start index of the value to be read. + * @param b + * a byte array. + * @param index + * the start index of the value to be read. * @return the read value. */ static short readShort(final byte[] b, final int index) { @@ -2576,8 +2587,10 @@ class MethodWriter extends MethodVisitor { /** * Reads a signed int value in the given byte array. * - * @param b a byte array. - * @param index the start index of the value to be read. + * @param b + * a byte array. + * @param index + * the start index of the value to be read. * @return the read value. */ static int readInt(final byte[] b, final int index) { @@ -2588,9 +2601,12 @@ class MethodWriter extends MethodVisitor { /** * Writes a short value in the given byte array. * - * @param b a byte array. - * @param index where the first byte of the short value must be written. - * @param s the value to be written in the given byte array. + * @param b + * a byte array. + * @param index + * where the first byte of the short value must be written. + * @param s + * the value to be written in the given byte array. */ static void writeShort(final byte[] b, final int index, final int s) { b[index] = (byte) (s >>> 8); @@ -2598,32 +2614,34 @@ class MethodWriter extends MethodVisitor { } /** - * Computes the future value of a bytecode offset. <p> Note: it is possible - * to have several entries for the same instruction in the <tt>indexes</tt> - * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b') - * are equivalent to a single entry (index=a,size=b+b'). + * Computes the future value of a bytecode offset. + * <p> + * Note: it is possible to have several entries for the same instruction in + * the <tt>indexes</tt> and <tt>sizes</tt>: two entries (index=a,size=b) and + * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b'). * - * @param indexes current positions of the instructions to be resized. Each - * instruction must be designated by the index of its <i>last</i> - * byte, plus one (or, in other words, by the index of the <i>first</i> - * byte of the <i>next</i> instruction). - * @param sizes the number of bytes to be <i>added</i> to the above - * instructions. More precisely, for each i < <tt>len</tt>, - * <tt>sizes</tt>[i] bytes will be added at the end of the - * instruction designated by <tt>indexes</tt>[i] or, if - * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>| - * bytes of the instruction will be removed (the instruction size - * <i>must not</i> become negative or null). - * @param begin index of the first byte of the source instruction. - * @param end index of the first byte of the target instruction. + * @param indexes + * current positions of the instructions to be resized. Each + * instruction must be designated by the index of its <i>last</i> + * byte, plus one (or, in other words, by the index of the + * <i>first</i> byte of the <i>next</i> instruction). + * @param sizes + * the number of bytes to be <i>added</i> to the above + * instructions. More precisely, for each i < <tt>len</tt>, + * <tt>sizes</tt>[i] bytes will be added at the end of the + * instruction designated by <tt>indexes</tt>[i] or, if + * <tt>sizes</tt>[i] is negative, the <i>last</i> | + * <tt>sizes[i]</tt>| bytes of the instruction will be removed + * (the instruction size <i>must not</i> become negative or + * null). + * @param begin + * index of the first byte of the source instruction. + * @param end + * index of the first byte of the target instruction. * @return the future value of the given bytecode offset. */ - static int getNewOffset( - final int[] indexes, - final int[] sizes, - final int begin, - final int end) - { + static int getNewOffset(final int[] indexes, final int[] sizes, + final int begin, final int end) { int offset = end - begin; for (int i = 0; i < indexes.length; ++i) { if (begin < indexes[i] && indexes[i] <= end) { @@ -2640,24 +2658,25 @@ class MethodWriter extends MethodVisitor { /** * Updates the offset of the given label. * - * @param indexes current positions of the instructions to be resized. Each - * instruction must be designated by the index of its <i>last</i> - * byte, plus one (or, in other words, by the index of the <i>first</i> - * byte of the <i>next</i> instruction). - * @param sizes the number of bytes to be <i>added</i> to the above - * instructions. More precisely, for each i < <tt>len</tt>, - * <tt>sizes</tt>[i] bytes will be added at the end of the - * instruction designated by <tt>indexes</tt>[i] or, if - * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>| - * bytes of the instruction will be removed (the instruction size - * <i>must not</i> become negative or null). - * @param label the label whose offset must be updated. - */ - static void getNewOffset( - final int[] indexes, - final int[] sizes, - final Label label) - { + * @param indexes + * current positions of the instructions to be resized. Each + * instruction must be designated by the index of its <i>last</i> + * byte, plus one (or, in other words, by the index of the + * <i>first</i> byte of the <i>next</i> instruction). + * @param sizes + * the number of bytes to be <i>added</i> to the above + * instructions. More precisely, for each i < <tt>len</tt>, + * <tt>sizes</tt>[i] bytes will be added at the end of the + * instruction designated by <tt>indexes</tt>[i] or, if + * <tt>sizes</tt>[i] is negative, the <i>last</i> | + * <tt>sizes[i]</tt>| bytes of the instruction will be removed + * (the instruction size <i>must not</i> become negative or + * null). + * @param label + * the label whose offset must be updated. + */ + static void getNewOffset(final int[] indexes, final int[] sizes, + final Label label) { if ((label.status & Label.RESIZED) == 0) { label.position = getNewOffset(indexes, sizes, 0, label.position); label.status |= Label.RESIZED; diff --git a/src/asm/scala/tools/asm/Type.java b/src/asm/scala/tools/asm/Type.java index bf1107182a..7821a492e6 100644 --- a/src/asm/scala/tools/asm/Type.java +++ b/src/asm/scala/tools/asm/Type.java @@ -190,13 +190,16 @@ public class Type { /** * Constructs a reference type. * - * @param sort the sort of the reference type to be constructed. - * @param buf a buffer containing the descriptor of the previous type. - * @param off the offset of this descriptor in the previous buffer. - * @param len the length of this descriptor. - */ - private Type(final int sort, final char[] buf, final int off, final int len) - { + * @param sort + * the sort of the reference type to be constructed. + * @param buf + * a buffer containing the descriptor of the previous type. + * @param off + * the offset of this descriptor in the previous buffer. + * @param len + * the length of this descriptor. + */ + private Type(final int sort, final char[] buf, final int off, final int len) { this.sort = sort; this.buf = buf; this.off = off; @@ -206,7 +209,8 @@ public class Type { /** * Returns the Java type corresponding to the given type descriptor. * - * @param typeDescriptor a field or method type descriptor. + * @param typeDescriptor + * a field or method type descriptor. * @return the Java type corresponding to the given type descriptor. */ public static Type getType(final String typeDescriptor) { @@ -216,7 +220,8 @@ public class Type { /** * Returns the Java type corresponding to the given internal name. * - * @param internalName an internal name. + * @param internalName + * an internal name. * @return the Java type corresponding to the given internal name. */ public static Type getObjectType(final String internalName) { @@ -228,7 +233,8 @@ public class Type { * Returns the Java type corresponding to the given method descriptor. * Equivalent to <code>Type.getType(methodDescriptor)</code>. * - * @param methodDescriptor a method descriptor. + * @param methodDescriptor + * a method descriptor. * @return the Java type corresponding to the given method descriptor. */ public static Type getMethodType(final String methodDescriptor) { @@ -239,18 +245,23 @@ public class Type { * Returns the Java method type corresponding to the given argument and * return types. * - * @param returnType the return type of the method. - * @param argumentTypes the argument types of the method. - * @return the Java type corresponding to the given argument and return types. + * @param returnType + * the return type of the method. + * @param argumentTypes + * the argument types of the method. + * @return the Java type corresponding to the given argument and return + * types. */ - public static Type getMethodType(final Type returnType, final Type... argumentTypes) { + public static Type getMethodType(final Type returnType, + final Type... argumentTypes) { return getType(getMethodDescriptor(returnType, argumentTypes)); } /** * Returns the Java type corresponding to the given class. * - * @param c a class. + * @param c + * a class. * @return the Java type corresponding to the given class. */ public static Type getType(final Class<?> c) { @@ -282,7 +293,8 @@ public class Type { /** * Returns the Java method type corresponding to the given constructor. * - * @param c a {@link Constructor Constructor} object. + * @param c + * a {@link Constructor Constructor} object. * @return the Java method type corresponding to the given constructor. */ public static Type getType(final Constructor<?> c) { @@ -292,7 +304,8 @@ public class Type { /** * Returns the Java method type corresponding to the given method. * - * @param m a {@link Method Method} object. + * @param m + * a {@link Method Method} object. * @return the Java method type corresponding to the given method. */ public static Type getType(final Method m) { @@ -303,7 +316,8 @@ public class Type { * Returns the Java types corresponding to the argument types of the given * method descriptor. * - * @param methodDescriptor a method descriptor. + * @param methodDescriptor + * a method descriptor. * @return the Java types corresponding to the argument types of the given * method descriptor. */ @@ -338,7 +352,8 @@ public class Type { * Returns the Java types corresponding to the argument types of the given * method. * - * @param method a method. + * @param method + * a method. * @return the Java types corresponding to the argument types of the given * method. */ @@ -355,7 +370,8 @@ public class Type { * Returns the Java type corresponding to the return type of the given * method descriptor. * - * @param methodDescriptor a method descriptor. + * @param methodDescriptor + * a method descriptor. * @return the Java type corresponding to the return type of the given * method descriptor. */ @@ -368,7 +384,8 @@ public class Type { * Returns the Java type corresponding to the return type of the given * method. * - * @param method a method. + * @param method + * a method. * @return the Java type corresponding to the return type of the given * method. */ @@ -379,12 +396,13 @@ public class Type { /** * Computes the size of the arguments and of the return value of a method. * - * @param desc the descriptor of a method. + * @param desc + * the descriptor of a method. * @return the size of the arguments of the method (plus one for the * implicit this argument), argSize, and the size of its return * value, retSize, packed into a single int i = - * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal - * to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). + * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to + * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). */ public static int getArgumentsAndReturnSizes(final String desc) { int n = 1; @@ -419,52 +437,54 @@ public class Type { * method descriptors, buf is supposed to contain nothing more than the * descriptor itself. * - * @param buf a buffer containing a type descriptor. - * @param off the offset of this descriptor in the previous buffer. + * @param buf + * a buffer containing a type descriptor. + * @param off + * the offset of this descriptor in the previous buffer. * @return the Java type corresponding to the given type descriptor. */ private static Type getType(final char[] buf, final int off) { int len; switch (buf[off]) { - case 'V': - return VOID_TYPE; - case 'Z': - return BOOLEAN_TYPE; - case 'C': - return CHAR_TYPE; - case 'B': - return BYTE_TYPE; - case 'S': - return SHORT_TYPE; - case 'I': - return INT_TYPE; - case 'F': - return FLOAT_TYPE; - case 'J': - return LONG_TYPE; - case 'D': - return DOUBLE_TYPE; - case '[': - len = 1; - while (buf[off + len] == '[') { - ++len; - } - if (buf[off + len] == 'L') { - ++len; - while (buf[off + len] != ';') { - ++len; - } - } - return new Type(ARRAY, buf, off, len + 1); - case 'L': - len = 1; + case 'V': + return VOID_TYPE; + case 'Z': + return BOOLEAN_TYPE; + case 'C': + return CHAR_TYPE; + case 'B': + return BYTE_TYPE; + case 'S': + return SHORT_TYPE; + case 'I': + return INT_TYPE; + case 'F': + return FLOAT_TYPE; + case 'J': + return LONG_TYPE; + case 'D': + return DOUBLE_TYPE; + case '[': + len = 1; + while (buf[off + len] == '[') { + ++len; + } + if (buf[off + len] == 'L') { + ++len; while (buf[off + len] != ';') { ++len; } - return new Type(OBJECT, buf, off + 1, len - 1); + } + return new Type(ARRAY, buf, off, len + 1); + case 'L': + len = 1; + while (buf[off + len] != ';') { + ++len; + } + return new Type(OBJECT, buf, off + 1, len - 1); // case '(': - default: - return new Type(METHOD, buf, 0, buf.length); + default: + return new Type(METHOD, buf, off, buf.length - off); } } @@ -475,11 +495,11 @@ public class Type { /** * Returns the sort of this Java type. * - * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, - * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT}, - * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG}, - * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY}, - * {@link #OBJECT OBJECT} or {@link #METHOD METHOD}. + * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, + * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, + * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, + * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD + * METHOD}. */ public int getSort() { return sort; @@ -517,34 +537,34 @@ public class Type { */ public String getClassName() { switch (sort) { - case VOID: - return "void"; - case BOOLEAN: - return "boolean"; - case CHAR: - return "char"; - case BYTE: - return "byte"; - case SHORT: - return "short"; - case INT: - return "int"; - case FLOAT: - return "float"; - case LONG: - return "long"; - case DOUBLE: - return "double"; - case ARRAY: - StringBuffer b = new StringBuffer(getElementType().getClassName()); - for (int i = getDimensions(); i > 0; --i) { - b.append("[]"); - } - return b.toString(); - case OBJECT: - return new String(buf, off, len).replace('/', '.'); - default: - return null; + case VOID: + return "void"; + case BOOLEAN: + return "boolean"; + case CHAR: + return "char"; + case BYTE: + return "byte"; + case SHORT: + return "short"; + case INT: + return "int"; + case FLOAT: + return "float"; + case LONG: + return "long"; + case DOUBLE: + return "double"; + case ARRAY: + StringBuffer b = new StringBuffer(getElementType().getClassName()); + for (int i = getDimensions(); i > 0; --i) { + b.append("[]"); + } + return b.toString(); + case OBJECT: + return new String(buf, off, len).replace('/', '.'); + default: + return null; } } @@ -613,15 +633,15 @@ public class Type { * Returns the descriptor corresponding to the given argument and return * types. * - * @param returnType the return type of the method. - * @param argumentTypes the argument types of the method. + * @param returnType + * the return type of the method. + * @param argumentTypes + * the argument types of the method. * @return the descriptor corresponding to the given argument and return * types. */ - public static String getMethodDescriptor( - final Type returnType, - final Type... argumentTypes) - { + public static String getMethodDescriptor(final Type returnType, + final Type... argumentTypes) { StringBuffer buf = new StringBuffer(); buf.append('('); for (int i = 0; i < argumentTypes.length; ++i) { @@ -636,11 +656,13 @@ public class Type { * Appends the descriptor corresponding to this Java type to the given * string buffer. * - * @param buf the string buffer to which the descriptor must be appended. + * @param buf + * the string buffer to which the descriptor must be appended. */ private void getDescriptor(final StringBuffer buf) { if (this.buf == null) { - // descriptor is in byte 3 of 'off' for primitive types (buf == null) + // descriptor is in byte 3 of 'off' for primitive types (buf == + // null) buf.append((char) ((off & 0xFF000000) >>> 24)); } else if (sort == OBJECT) { buf.append('L'); @@ -661,7 +683,8 @@ public class Type { * class is its fully qualified name, as returned by Class.getName(), where * '.' are replaced by '/'. * - * @param c an object or array class. + * @param c + * an object or array class. * @return the internal name of the given class. */ public static String getInternalName(final Class<?> c) { @@ -671,7 +694,8 @@ public class Type { /** * Returns the descriptor corresponding to the given Java type. * - * @param c an object class, a primitive class or an array class. + * @param c + * an object class, a primitive class or an array class. * @return the descriptor corresponding to the given class. */ public static String getDescriptor(final Class<?> c) { @@ -683,7 +707,8 @@ public class Type { /** * Returns the descriptor corresponding to the given constructor. * - * @param c a {@link Constructor Constructor} object. + * @param c + * a {@link Constructor Constructor} object. * @return the descriptor of the given constructor. */ public static String getConstructorDescriptor(final Constructor<?> c) { @@ -699,7 +724,8 @@ public class Type { /** * Returns the descriptor corresponding to the given method. * - * @param m a {@link Method Method} object. + * @param m + * a {@link Method Method} object. * @return the descriptor of the given method. */ public static String getMethodDescriptor(final Method m) { @@ -717,8 +743,10 @@ public class Type { /** * Appends the descriptor of the given class to the given string buffer. * - * @param buf the string buffer to which the descriptor must be appended. - * @param c the class whose descriptor must be computed. + * @param buf + * the string buffer to which the descriptor must be appended. + * @param c + * the class whose descriptor must be computed. */ private static void getDescriptor(final StringBuffer buf, final Class<?> c) { Class<?> d = c; @@ -783,9 +811,10 @@ public class Type { * Returns a JVM instruction opcode adapted to this Java type. This method * must not be used for method types. * - * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD, - * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL, - * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. + * @param opcode + * a JVM instruction opcode. This opcode must be one of ILOAD, + * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, + * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. * @return an opcode that is similar to the given opcode, but adapted to * this Java type. For example, if this type is <tt>float</tt> and * <tt>opcode</tt> is IRETURN, this method returns FRETURN. @@ -809,7 +838,8 @@ public class Type { /** * Tests if the given object is equal to this type. * - * @param o the object to be compared to this type. + * @param o + * the object to be compared to this type. * @return <tt>true</tt> if the given object is equal to this type. */ @Override diff --git a/src/asm/scala/tools/asm/signature/SignatureReader.java b/src/asm/scala/tools/asm/signature/SignatureReader.java index 22e6427e63..9c7c3880d9 100644 --- a/src/asm/scala/tools/asm/signature/SignatureReader.java +++ b/src/asm/scala/tools/asm/signature/SignatureReader.java @@ -46,8 +46,9 @@ public class SignatureReader { /** * Constructs a {@link SignatureReader} for the given signature. * - * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, - * or <i>FieldTypeSignature</i>. + * @param signature + * A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or + * <i>FieldTypeSignature</i>. */ public SignatureReader(final String signature) { this.signature = signature; @@ -58,15 +59,15 @@ public class SignatureReader { * {@link SignatureReader}. This signature is the one specified in the * constructor (see {@link #SignatureReader(String) SignatureReader}). This * method is intended to be called on a {@link SignatureReader} that was - * created using a <i>ClassSignature</i> (such as the + * created using a <i>ClassSignature</i> (such as the <code>signature</code> + * parameter of the {@link scala.tools.asm.ClassVisitor#visit + * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the * <code>signature</code> parameter of the - * {@link org.objectweb.asm.ClassVisitor#visit ClassVisitor.visit} method) - * or a <i>MethodTypeSignature</i> (such as the <code>signature</code> - * parameter of the - * {@link org.objectweb.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod} - * method). + * {@link scala.tools.asm.ClassVisitor#visitMethod + * ClassVisitor.visitMethod} method). * - * @param v the visitor that must visit this signature. + * @param v + * the visitor that must visit this signature. */ public void accept(final SignatureVisitor v) { String signature = this.signature; @@ -118,12 +119,12 @@ public class SignatureReader { * method is intended to be called on a {@link SignatureReader} that was * created using a <i>FieldTypeSignature</i>, such as the * <code>signature</code> parameter of the - * {@link org.objectweb.asm.ClassVisitor#visitField - * ClassVisitor.visitField} or {@link - * org.objectweb.asm.MethodVisitor#visitLocalVariable + * {@link scala.tools.asm.ClassVisitor#visitField ClassVisitor.visitField} + * or {@link scala.tools.asm.MethodVisitor#visitLocalVariable * MethodVisitor.visitLocalVariable} methods. * - * @param v the visitor that must visit this signature. + * @param v + * the visitor that must visit this signature. */ public void acceptType(final SignatureVisitor v) { parseType(this.signature, 0, v); @@ -132,98 +133,96 @@ public class SignatureReader { /** * Parses a field type signature and makes the given visitor visit it. * - * @param signature a string containing the signature that must be parsed. - * @param pos index of the first character of the signature to parsed. - * @param v the visitor that must visit this signature. + * @param signature + * a string containing the signature that must be parsed. + * @param pos + * index of the first character of the signature to parsed. + * @param v + * the visitor that must visit this signature. * @return the index of the first character after the parsed signature. */ - private static int parseType( - final String signature, - int pos, - final SignatureVisitor v) - { + private static int parseType(final String signature, int pos, + final SignatureVisitor v) { char c; int start, end; boolean visited, inner; String name; switch (c = signature.charAt(pos++)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - case 'F': - case 'J': - case 'D': - case 'V': - v.visitBaseType(c); - return pos; + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + case 'F': + case 'J': + case 'D': + case 'V': + v.visitBaseType(c); + return pos; - case '[': - return parseType(signature, pos, v.visitArrayType()); + case '[': + return parseType(signature, pos, v.visitArrayType()); - case 'T': - end = signature.indexOf(';', pos); - v.visitTypeVariable(signature.substring(pos, end)); - return end + 1; + case 'T': + end = signature.indexOf(';', pos); + v.visitTypeVariable(signature.substring(pos, end)); + return end + 1; - default: // case 'L': - start = pos; - visited = false; - inner = false; - for (;;) { - switch (c = signature.charAt(pos++)) { - case '.': - case ';': - if (!visited) { - name = signature.substring(start, pos - 1); - if (inner) { - v.visitInnerClassType(name); - } else { - v.visitClassType(name); - } - } - if (c == ';') { - v.visitEnd(); - return pos; - } - start = pos; - visited = false; - inner = true; - break; + default: // case 'L': + start = pos; + visited = false; + inner = false; + for (;;) { + switch (c = signature.charAt(pos++)) { + case '.': + case ';': + if (!visited) { + name = signature.substring(start, pos - 1); + if (inner) { + v.visitInnerClassType(name); + } else { + v.visitClassType(name); + } + } + if (c == ';') { + v.visitEnd(); + return pos; + } + start = pos; + visited = false; + inner = true; + break; - case '<': - name = signature.substring(start, pos - 1); - if (inner) { - v.visitInnerClassType(name); - } else { - v.visitClassType(name); - } - visited = true; - top: for (;;) { - switch (c = signature.charAt(pos)) { - case '>': - break top; - case '*': - ++pos; - v.visitTypeArgument(); - break; - case '+': - case '-': - pos = parseType(signature, - pos + 1, - v.visitTypeArgument(c)); - break; - default: - pos = parseType(signature, - pos, - v.visitTypeArgument('=')); - break; - } - } + case '<': + name = signature.substring(start, pos - 1); + if (inner) { + v.visitInnerClassType(name); + } else { + v.visitClassType(name); + } + visited = true; + top: for (;;) { + switch (c = signature.charAt(pos)) { + case '>': + break top; + case '*': + ++pos; + v.visitTypeArgument(); + break; + case '+': + case '-': + pos = parseType(signature, pos + 1, + v.visitTypeArgument(c)); + break; + default: + pos = parseType(signature, pos, + v.visitTypeArgument('=')); + break; + } } } + } } } } diff --git a/src/asm/scala/tools/asm/signature/SignatureVisitor.java b/src/asm/scala/tools/asm/signature/SignatureVisitor.java index 2fc364e374..f38f81f53b 100644 --- a/src/asm/scala/tools/asm/signature/SignatureVisitor.java +++ b/src/asm/scala/tools/asm/signature/SignatureVisitor.java @@ -35,21 +35,21 @@ import scala.tools.asm.Opcodes; * A visitor to visit a generic signature. The methods of this interface must be * called in one of the three following orders (the last one is the only valid * order for a {@link SignatureVisitor} that is returned by a method of this - * interface): <ul> <li><i>ClassSignature</i> = ( - * <tt>visitFormalTypeParameter</tt> - * <tt>visitClassBound</tt>? - * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt> - * <tt>visitInterface</tt>* )</li> + * interface): + * <ul> + * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt> + * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* ( + * <tt>visitSuperClass</tt> <tt>visitInterface</tt>* )</li> * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt> - * <tt>visitClassBound</tt>? - * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>* - * <tt>visitReturnType</tt> - * <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> = - * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> | - * <tt>visitArrayType</tt> | ( + * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* ( + * <tt>visitParameterType</tt>* <tt>visitReturnType</tt> + * <tt>visitExceptionType</tt>* )</li> + * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> | + * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | ( * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* ( - * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* - * <tt>visitEnd</tt> ) )</li> </ul> + * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt> + * ) )</li> + * </ul> * * @author Thomas Hallgren * @author Eric Bruneton @@ -80,8 +80,9 @@ public abstract class SignatureVisitor { /** * Constructs a new {@link SignatureVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. */ public SignatureVisitor(final int api) { this.api = api; @@ -90,7 +91,8 @@ public abstract class SignatureVisitor { /** * Visits a formal type parameter. * - * @param name the name of the formal parameter. + * @param name + * the name of the formal parameter. */ public void visitFormalTypeParameter(String name) { } @@ -162,8 +164,9 @@ public abstract class SignatureVisitor { /** * Visits a signature corresponding to a primitive type. * - * @param descriptor the descriptor of the primitive type, or 'V' for - * <tt>void</tt>. + * @param descriptor + * the descriptor of the primitive type, or 'V' for <tt>void</tt> + * . */ public void visitBaseType(char descriptor) { } @@ -171,7 +174,8 @@ public abstract class SignatureVisitor { /** * Visits a signature corresponding to a type variable. * - * @param name the name of the type variable. + * @param name + * the name of the type variable. */ public void visitTypeVariable(String name) { } @@ -190,7 +194,8 @@ public abstract class SignatureVisitor { * Starts the visit of a signature corresponding to a class or interface * type. * - * @param name the internal name of the class or interface. + * @param name + * the internal name of the class or interface. */ public void visitClassType(String name) { } @@ -198,7 +203,8 @@ public abstract class SignatureVisitor { /** * Visits an inner class. * - * @param name the local name of the inner class in its enclosing class. + * @param name + * the local name of the inner class in its enclosing class. */ public void visitInnerClassType(String name) { } @@ -213,7 +219,8 @@ public abstract class SignatureVisitor { /** * Visits a type argument of the last visited class or inner class type. * - * @param wildcard '+', '-' or '='. + * @param wildcard + * '+', '-' or '='. * @return a non null visitor to visit the signature of the type argument. */ public SignatureVisitor visitTypeArgument(char wildcard) { diff --git a/src/asm/scala/tools/asm/signature/SignatureWriter.java b/src/asm/scala/tools/asm/signature/SignatureWriter.java index a59fdfde2b..ebf4fe07b4 100644 --- a/src/asm/scala/tools/asm/signature/SignatureWriter.java +++ b/src/asm/scala/tools/asm/signature/SignatureWriter.java @@ -224,4 +224,4 @@ public class SignatureWriter extends SignatureVisitor { } argumentStack /= 2; } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/AbstractInsnNode.java b/src/asm/scala/tools/asm/tree/AbstractInsnNode.java index 471f842ffc..411eead3c7 100644 --- a/src/asm/scala/tools/asm/tree/AbstractInsnNode.java +++ b/src/asm/scala/tools/asm/tree/AbstractInsnNode.java @@ -148,7 +148,8 @@ public abstract class AbstractInsnNode { /** * Constructs a new {@link AbstractInsnNode}. * - * @param opcode the opcode of the instruction to be constructed. + * @param opcode + * the opcode of the instruction to be constructed. */ protected AbstractInsnNode(final int opcode) { this.opcode = opcode; @@ -197,38 +198,47 @@ public abstract class AbstractInsnNode { /** * Makes the given code visitor visit this instruction. * - * @param cv a code visitor. + * @param cv + * a code visitor. */ public abstract void accept(final MethodVisitor cv); /** * Returns a copy of this instruction. * - * @param labels a map from LabelNodes to cloned LabelNodes. + * @param labels + * a map from LabelNodes to cloned LabelNodes. * @return a copy of this instruction. The returned instruction does not * belong to any {@link InsnList}. */ - public abstract AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels); + public abstract AbstractInsnNode clone( + final Map<LabelNode, LabelNode> labels); /** * Returns the clone of the given label. * - * @param label a label. - * @param map a map from LabelNodes to cloned LabelNodes. + * @param label + * a label. + * @param map + * a map from LabelNodes to cloned LabelNodes. * @return the clone of the given label. */ - static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> map) { + static LabelNode clone(final LabelNode label, + final Map<LabelNode, LabelNode> map) { return map.get(label); } /** * Returns the clones of the given labels. * - * @param labels a list of labels. - * @param map a map from LabelNodes to cloned LabelNodes. + * @param labels + * a list of labels. + * @param map + * a map from LabelNodes to cloned LabelNodes. * @return the clones of the given labels. */ - static LabelNode[] clone(final List<LabelNode> labels, final Map<LabelNode, LabelNode> map) { + static LabelNode[] clone(final List<LabelNode> labels, + final Map<LabelNode, LabelNode> map) { LabelNode[] clones = new LabelNode[labels.size()]; for (int i = 0; i < clones.length; ++i) { clones[i] = map.get(labels.get(i)); diff --git a/src/asm/scala/tools/asm/tree/AnnotationNode.java b/src/asm/scala/tools/asm/tree/AnnotationNode.java index 9f132550e6..1f4beef9f7 100644 --- a/src/asm/scala/tools/asm/tree/AnnotationNode.java +++ b/src/asm/scala/tools/asm/tree/AnnotationNode.java @@ -52,11 +52,11 @@ public class AnnotationNode extends AnnotationVisitor { * as two consecutive elements in the list. The name is a {@link String}, * and the value may be a {@link Byte}, {@link Boolean}, {@link Character}, * {@link Short}, {@link Integer}, {@link Long}, {@link Float}, - * {@link Double}, {@link String} or {@link org.objectweb.asm.Type}, or an + * {@link Double}, {@link String} or {@link scala.tools.asm.Type}, or an * two elements String array (for enumeration values), a * {@link AnnotationNode}, or a {@link List} of values of one of the - * preceding types. The list may be <tt>null</tt> if there is no name - * value pair. + * preceding types. The list may be <tt>null</tt> if there is no name value + * pair. */ public List<Object> values; @@ -65,7 +65,8 @@ public class AnnotationNode extends AnnotationVisitor { * constructor</i>. Instead, they must use the * {@link #AnnotationNode(int, String)} version. * - * @param desc the class descriptor of the annotation class. + * @param desc + * the class descriptor of the annotation class. */ public AnnotationNode(final String desc) { this(Opcodes.ASM4, desc); @@ -74,9 +75,11 @@ public class AnnotationNode extends AnnotationVisitor { /** * Constructs a new {@link AnnotationNode}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param desc the class descriptor of the annotation class. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param desc + * the class descriptor of the annotation class. */ public AnnotationNode(final int api, final String desc) { super(api); @@ -86,7 +89,8 @@ public class AnnotationNode extends AnnotationVisitor { /** * Constructs a new {@link AnnotationNode} to visit an array value. * - * @param values where the visited values must be stored. + * @param values + * where the visited values must be stored. */ AnnotationNode(final List<Object> values) { super(Opcodes.ASM4); @@ -109,11 +113,8 @@ public class AnnotationNode extends AnnotationVisitor { } @Override - public void visitEnum( - final String name, - final String desc, - final String value) - { + public void visitEnum(final String name, final String desc, + final String value) { if (values == null) { values = new ArrayList<Object>(this.desc != null ? 2 : 1); } @@ -124,10 +125,8 @@ public class AnnotationNode extends AnnotationVisitor { } @Override - public AnnotationVisitor visitAnnotation( - final String name, - final String desc) - { + public AnnotationVisitor visitAnnotation(final String name, + final String desc) { if (values == null) { values = new ArrayList<Object>(this.desc != null ? 2 : 1); } @@ -166,7 +165,8 @@ public class AnnotationNode extends AnnotationVisitor { * recursively, do not contain elements that were introduced in more recent * versions of the ASM API than the given version. * - * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}. + * @param api + * an ASM API version. Must be one of {@link Opcodes#ASM4}. */ public void check(final int api) { // nothing to do @@ -175,7 +175,8 @@ public class AnnotationNode extends AnnotationVisitor { /** * Makes the given visitor visit this annotation. * - * @param av an annotation visitor. Maybe <tt>null</tt>. + * @param av + * an annotation visitor. Maybe <tt>null</tt>. */ public void accept(final AnnotationVisitor av) { if (av != null) { @@ -193,15 +194,15 @@ public class AnnotationNode extends AnnotationVisitor { /** * Makes the given visitor visit a given annotation value. * - * @param av an annotation visitor. Maybe <tt>null</tt>. - * @param name the value name. - * @param value the actual value. + * @param av + * an annotation visitor. Maybe <tt>null</tt>. + * @param name + * the value name. + * @param value + * the actual value. */ - static void accept( - final AnnotationVisitor av, - final String name, - final Object value) - { + static void accept(final AnnotationVisitor av, final String name, + final Object value) { if (av != null) { if (value instanceof String[]) { String[] typeconst = (String[]) value; diff --git a/src/asm/scala/tools/asm/tree/ClassNode.java b/src/asm/scala/tools/asm/tree/ClassNode.java index 64effae698..c3d999985a 100644 --- a/src/asm/scala/tools/asm/tree/ClassNode.java +++ b/src/asm/scala/tools/asm/tree/ClassNode.java @@ -53,33 +53,33 @@ public class ClassNode extends ClassVisitor { public int version; /** - * The class's access flags (see {@link org.objectweb.asm.Opcodes}). This + * The class's access flags (see {@link scala.tools.asm.Opcodes}). This * field also indicates if the class is deprecated. */ public int access; /** * The internal name of the class (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + * {@link scala.tools.asm.Type#getInternalName() getInternalName}). */ public String name; /** - * The signature of the class. Mayt be <tt>null</tt>. + * The signature of the class. May be <tt>null</tt>. */ public String signature; /** * The internal of name of the super class (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). For - * interfaces, the super class is {@link Object}. May be <tt>null</tt>, - * but only for the {@link Object} class. + * {@link scala.tools.asm.Type#getInternalName() getInternalName}). For + * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but + * only for the {@link Object} class. */ public String superName; /** * The internal names of the class's interfaces (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). This + * {@link scala.tools.asm.Type#getInternalName() getInternalName}). This * list is a list of {@link String} objects. */ public List<String> interfaces; @@ -91,7 +91,7 @@ public class ClassNode extends ClassVisitor { public String sourceFile; /** - * Debug information to compute the correspondance between source and + * Debug information to compute the correspondence between source and * compiled elements of the class. May be <tt>null</tt>. */ public String sourceDebug; @@ -109,8 +109,8 @@ public class ClassNode extends ClassVisitor { public String outerMethod; /** - * The descriptor of the method that contains the class, or <tt>null</tt> - * if the class is not enclosed in a method. + * The descriptor of the method that contains the class, or <tt>null</tt> if + * the class is not enclosed in a method. */ public String outerMethodDesc; @@ -118,7 +118,7 @@ public class ClassNode extends ClassVisitor { * The runtime visible annotations of this class. This list is a list of * {@link AnnotationNode} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.tree.AnnotationNode + * @associates scala.tools.asm.tree.AnnotationNode * @label visible */ public List<AnnotationNode> visibleAnnotations; @@ -127,7 +127,7 @@ public class ClassNode extends ClassVisitor { * The runtime invisible annotations of this class. This list is a list of * {@link AnnotationNode} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.tree.AnnotationNode + * @associates scala.tools.asm.tree.AnnotationNode * @label invisible */ public List<AnnotationNode> invisibleAnnotations; @@ -136,7 +136,7 @@ public class ClassNode extends ClassVisitor { * The non standard attributes of this class. This list is a list of * {@link Attribute} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.Attribute + * @associates scala.tools.asm.Attribute */ public List<Attribute> attrs; @@ -144,7 +144,7 @@ public class ClassNode extends ClassVisitor { * Informations about the inner classes of this class. This list is a list * of {@link InnerClassNode} objects. * - * @associates org.objectweb.asm.tree.InnerClassNode + * @associates scala.tools.asm.tree.InnerClassNode */ public List<InnerClassNode> innerClasses; @@ -152,7 +152,7 @@ public class ClassNode extends ClassVisitor { * The fields of this class. This list is a list of {@link FieldNode} * objects. * - * @associates org.objectweb.asm.tree.FieldNode + * @associates scala.tools.asm.tree.FieldNode */ public List<FieldNode> fields; @@ -160,7 +160,7 @@ public class ClassNode extends ClassVisitor { * The methods of this class. This list is a list of {@link MethodNode} * objects. * - * @associates org.objectweb.asm.tree.MethodNode + * @associates scala.tools.asm.tree.MethodNode */ public List<MethodNode> methods; @@ -176,8 +176,9 @@ public class ClassNode extends ClassVisitor { /** * Constructs a new {@link ClassNode}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. */ public ClassNode(final int api) { super(api); @@ -192,14 +193,9 @@ public class ClassNode extends ClassVisitor { // ------------------------------------------------------------------------ @Override - public void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces) - { + public void visit(final int version, final int access, final String name, + final String signature, final String superName, + final String[] interfaces) { this.version = version; this.access = access; this.name = name; @@ -217,21 +213,16 @@ public class ClassNode extends ClassVisitor { } @Override - public void visitOuterClass( - final String owner, - final String name, - final String desc) - { + public void visitOuterClass(final String owner, final String name, + final String desc) { outerClass = owner; outerMethod = name; outerMethodDesc = desc; } @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { AnnotationNode an = new AnnotationNode(desc); if (visible) { if (visibleAnnotations == null) { @@ -256,44 +247,25 @@ public class ClassNode extends ClassVisitor { } @Override - public void visitInnerClass( - final String name, - final String outerName, - final String innerName, - final int access) - { - InnerClassNode icn = new InnerClassNode(name, - outerName, - innerName, + public void visitInnerClass(final String name, final String outerName, + final String innerName, final int access) { + InnerClassNode icn = new InnerClassNode(name, outerName, innerName, access); innerClasses.add(icn); } @Override - public FieldVisitor visitField( - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { + public FieldVisitor visitField(final int access, final String name, + final String desc, final String signature, final Object value) { FieldNode fn = new FieldNode(access, name, desc, signature, value); fields.add(fn); return fn; } @Override - public MethodVisitor visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { - MethodNode mn = new MethodNode(access, - name, - desc, - signature, + public MethodVisitor visitMethod(final int access, final String name, + final String desc, final String signature, final String[] exceptions) { + MethodNode mn = new MethodNode(access, name, desc, signature, exceptions); methods.add(mn); return mn; @@ -313,7 +285,8 @@ public class ClassNode extends ClassVisitor { * contain elements that were introduced in more recent versions of the ASM * API than the given version. * - * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}. + * @param api + * an ASM API version. Must be one of {@link Opcodes#ASM4}. */ public void check(final int api) { // nothing to do @@ -322,7 +295,8 @@ public class ClassNode extends ClassVisitor { /** * Makes the given class visitor visit this class. * - * @param cv a class visitor. + * @param cv + * a class visitor. */ public void accept(final ClassVisitor cv) { // visits header diff --git a/src/asm/scala/tools/asm/tree/FieldInsnNode.java b/src/asm/scala/tools/asm/tree/FieldInsnNode.java index 6b7a6a142a..0c94f18adf 100644 --- a/src/asm/scala/tools/asm/tree/FieldInsnNode.java +++ b/src/asm/scala/tools/asm/tree/FieldInsnNode.java @@ -43,7 +43,7 @@ public class FieldInsnNode extends AbstractInsnNode { /** * The internal name of the field's owner class (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + * {@link scala.tools.asm.Type#getInternalName() getInternalName}). */ public String owner; @@ -53,26 +53,27 @@ public class FieldInsnNode extends AbstractInsnNode { public String name; /** - * The field's descriptor (see {@link org.objectweb.asm.Type}). + * The field's descriptor (see {@link scala.tools.asm.Type}). */ public String desc; /** * Constructs a new {@link FieldInsnNode}. * - * @param opcode the opcode of the type instruction to be constructed. This - * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. - * @param owner the internal name of the field's owner class (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). - * @param name the field's name. - * @param desc the field's descriptor (see {@link org.objectweb.asm.Type}). + * @param opcode + * the opcode of the type instruction to be constructed. This + * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. + * @param owner + * the internal name of the field's owner class (see + * {@link scala.tools.asm.Type#getInternalName() + * getInternalName}). + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link scala.tools.asm.Type}). */ - public FieldInsnNode( - final int opcode, - final String owner, - final String name, - final String desc) - { + public FieldInsnNode(final int opcode, final String owner, + final String name, final String desc) { super(opcode); this.owner = owner; this.name = name; @@ -82,8 +83,9 @@ public class FieldInsnNode extends AbstractInsnNode { /** * Sets the opcode of this instruction. * - * @param opcode the new instruction opcode. This opcode must be GETSTATIC, - * PUTSTATIC, GETFIELD or PUTFIELD. + * @param opcode + * the new instruction opcode. This opcode must be GETSTATIC, + * PUTSTATIC, GETFIELD or PUTFIELD. */ public void setOpcode(final int opcode) { this.opcode = opcode; diff --git a/src/asm/scala/tools/asm/tree/FieldNode.java b/src/asm/scala/tools/asm/tree/FieldNode.java index 9a1e17033c..61b614ec59 100644 --- a/src/asm/scala/tools/asm/tree/FieldNode.java +++ b/src/asm/scala/tools/asm/tree/FieldNode.java @@ -46,7 +46,7 @@ import scala.tools.asm.Opcodes; public class FieldNode extends FieldVisitor { /** - * The field's access flags (see {@link org.objectweb.asm.Opcodes}). This + * The field's access flags (see {@link scala.tools.asm.Opcodes}). This * field also indicates if the field is synthetic and/or deprecated. */ public int access; @@ -57,7 +57,7 @@ public class FieldNode extends FieldVisitor { public String name; /** - * The field's descriptor (see {@link org.objectweb.asm.Type}). + * The field's descriptor (see {@link scala.tools.asm.Type}). */ public String desc; @@ -67,8 +67,8 @@ public class FieldNode extends FieldVisitor { public String signature; /** - * The field's initial value. This field, which may be <tt>null</tt> if - * the field does not have an initial value, must be an {@link Integer}, a + * The field's initial value. This field, which may be <tt>null</tt> if the + * field does not have an initial value, must be an {@link Integer}, a * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}. */ public Object value; @@ -77,7 +77,7 @@ public class FieldNode extends FieldVisitor { * The runtime visible annotations of this field. This list is a list of * {@link AnnotationNode} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.tree.AnnotationNode + * @associates scala.tools.asm.tree.AnnotationNode * @label visible */ public List<AnnotationNode> visibleAnnotations; @@ -86,7 +86,7 @@ public class FieldNode extends FieldVisitor { * The runtime invisible annotations of this field. This list is a list of * {@link AnnotationNode} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.tree.AnnotationNode + * @associates scala.tools.asm.tree.AnnotationNode * @label invisible */ public List<AnnotationNode> invisibleAnnotations; @@ -95,7 +95,7 @@ public class FieldNode extends FieldVisitor { * The non standard attributes of this field. This list is a list of * {@link Attribute} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.Attribute + * @associates scala.tools.asm.Attribute */ public List<Attribute> attrs; @@ -104,25 +104,25 @@ public class FieldNode extends FieldVisitor { * constructor</i>. Instead, they must use the * {@link #FieldNode(int, int, String, String, String, Object)} version. * - * @param access the field's access flags (see - * {@link org.objectweb.asm.Opcodes}). This parameter also indicates - * if the field is synthetic and/or deprecated. - * @param name the field's name. - * @param desc the field's descriptor (see {@link org.objectweb.asm.Type - * Type}). - * @param signature the field's signature. - * @param value the field's initial value. This parameter, which may be - * <tt>null</tt> if the field does not have an initial value, must be - * an {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double} or a {@link String}. + * @param access + * the field's access flags (see + * {@link scala.tools.asm.Opcodes}). This parameter also + * indicates if the field is synthetic and/or deprecated. + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link scala.tools.asm.Type + * Type}). + * @param signature + * the field's signature. + * @param value + * the field's initial value. This parameter, which may be + * <tt>null</tt> if the field does not have an initial value, + * must be an {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} or a {@link String}. */ - public FieldNode( - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { + public FieldNode(final int access, final String name, final String desc, + final String signature, final Object value) { this(Opcodes.ASM4, access, name, desc, signature, value); } @@ -131,28 +131,28 @@ public class FieldNode extends FieldVisitor { * constructor</i>. Instead, they must use the * {@link #FieldNode(int, int, String, String, String, Object)} version. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param access the field's access flags (see - * {@link org.objectweb.asm.Opcodes}). This parameter also indicates - * if the field is synthetic and/or deprecated. - * @param name the field's name. - * @param desc the field's descriptor (see {@link org.objectweb.asm.Type - * Type}). - * @param signature the field's signature. - * @param value the field's initial value. This parameter, which may be - * <tt>null</tt> if the field does not have an initial value, must be - * an {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double} or a {@link String}. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param access + * the field's access flags (see + * {@link scala.tools.asm.Opcodes}). This parameter also + * indicates if the field is synthetic and/or deprecated. + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link scala.tools.asm.Type + * Type}). + * @param signature + * the field's signature. + * @param value + * the field's initial value. This parameter, which may be + * <tt>null</tt> if the field does not have an initial value, + * must be an {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} or a {@link String}. */ - public FieldNode( - final int api, - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { + public FieldNode(final int api, final int access, final String name, + final String desc, final String signature, final Object value) { super(api); this.access = access; this.name = name; @@ -166,10 +166,8 @@ public class FieldNode extends FieldVisitor { // ------------------------------------------------------------------------ @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { AnnotationNode an = new AnnotationNode(desc); if (visible) { if (visibleAnnotations == null) { @@ -207,7 +205,8 @@ public class FieldNode extends FieldVisitor { * contain elements that were introduced in more recent versions of the ASM * API than the given version. * - * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}. + * @param api + * an ASM API version. Must be one of {@link Opcodes#ASM4}. */ public void check(final int api) { // nothing to do @@ -216,7 +215,8 @@ public class FieldNode extends FieldVisitor { /** * Makes the given class visitor visit this field. * - * @param cv a class visitor. + * @param cv + * a class visitor. */ public void accept(final ClassVisitor cv) { FieldVisitor fv = cv.visitField(access, name, desc, signature, value); diff --git a/src/asm/scala/tools/asm/tree/FrameNode.java b/src/asm/scala/tools/asm/tree/FrameNode.java index 66825de0ac..f13fc66749 100644 --- a/src/asm/scala/tools/asm/tree/FrameNode.java +++ b/src/asm/scala/tools/asm/tree/FrameNode.java @@ -45,8 +45,9 @@ import scala.tools.asm.Opcodes; * the target of a jump instruction, or that starts an exception handler block. * The stack map frame types must describe the values of the local variables and * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br> - * <br> (*) this is mandatory only for classes whose version is greater than or - * equal to {@link Opcodes#V1_6 V1_6}. + * <br> + * (*) this is mandatory only for classes whose version is greater than or equal + * to {@link Opcodes#V1_6 V1_6}. * * @author Eric Bruneton */ @@ -83,48 +84,48 @@ public class FrameNode extends AbstractInsnNode { /** * Constructs a new {@link FrameNode}. * - * @param type the type of this frame. Must be {@link Opcodes#F_NEW} for - * expanded frames, or {@link Opcodes#F_FULL}, - * {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, - * {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, - * {@link Opcodes#F_SAME1} for compressed frames. - * @param nLocal number of local variables of this stack map frame. - * @param local the types of the local variables of this stack map frame. - * Elements of this list can be Integer, String or LabelNode objects - * (for primitive, reference and uninitialized types respectively - - * see {@link MethodVisitor}). - * @param nStack number of operand stack elements of this stack map frame. - * @param stack the types of the operand stack elements of this stack map - * frame. Elements of this list can be Integer, String or LabelNode - * objects (for primitive, reference and uninitialized types - * respectively - see {@link MethodVisitor}). + * @param type + * the type of this frame. Must be {@link Opcodes#F_NEW} for + * expanded frames, or {@link Opcodes#F_FULL}, + * {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, + * {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, + * {@link Opcodes#F_SAME1} for compressed frames. + * @param nLocal + * number of local variables of this stack map frame. + * @param local + * the types of the local variables of this stack map frame. + * Elements of this list can be Integer, String or LabelNode + * objects (for primitive, reference and uninitialized types + * respectively - see {@link MethodVisitor}). + * @param nStack + * number of operand stack elements of this stack map frame. + * @param stack + * the types of the operand stack elements of this stack map + * frame. Elements of this list can be Integer, String or + * LabelNode objects (for primitive, reference and uninitialized + * types respectively - see {@link MethodVisitor}). */ - public FrameNode( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) - { + public FrameNode(final int type, final int nLocal, final Object[] local, + final int nStack, final Object[] stack) { super(-1); this.type = type; switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - this.local = asList(nLocal, local); - this.stack = asList(nStack, stack); - break; - case Opcodes.F_APPEND: - this.local = asList(nLocal, local); - break; - case Opcodes.F_CHOP: - this.local = Arrays.asList(new Object[nLocal]); - break; - case Opcodes.F_SAME: - break; - case Opcodes.F_SAME1: - this.stack = asList(1, stack); - break; + case Opcodes.F_NEW: + case Opcodes.F_FULL: + this.local = asList(nLocal, local); + this.stack = asList(nStack, stack); + break; + case Opcodes.F_APPEND: + this.local = asList(nLocal, local); + break; + case Opcodes.F_CHOP: + this.local = Arrays.asList(new Object[nLocal]); + break; + case Opcodes.F_SAME: + break; + case Opcodes.F_SAME1: + this.stack = asList(1, stack); + break; } } @@ -136,31 +137,29 @@ public class FrameNode extends AbstractInsnNode { /** * Makes the given visitor visit this stack map frame. * - * @param mv a method visitor. + * @param mv + * a method visitor. */ @Override public void accept(final MethodVisitor mv) { switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - mv.visitFrame(type, - local.size(), - asArray(local), - stack.size(), - asArray(stack)); - break; - case Opcodes.F_APPEND: - mv.visitFrame(type, local.size(), asArray(local), 0, null); - break; - case Opcodes.F_CHOP: - mv.visitFrame(type, local.size(), null, 0, null); - break; - case Opcodes.F_SAME: - mv.visitFrame(type, 0, null, 0, null); - break; - case Opcodes.F_SAME1: - mv.visitFrame(type, 0, null, 1, asArray(stack)); - break; + case Opcodes.F_NEW: + case Opcodes.F_FULL: + mv.visitFrame(type, local.size(), asArray(local), stack.size(), + asArray(stack)); + break; + case Opcodes.F_APPEND: + mv.visitFrame(type, local.size(), asArray(local), 0, null); + break; + case Opcodes.F_CHOP: + mv.visitFrame(type, local.size(), null, 0, null); + break; + case Opcodes.F_SAME: + mv.visitFrame(type, 0, null, 0, null); + break; + case Opcodes.F_SAME1: + mv.visitFrame(type, 0, null, 1, asArray(stack)); + break; } } diff --git a/src/asm/scala/tools/asm/tree/IincInsnNode.java b/src/asm/scala/tools/asm/tree/IincInsnNode.java index 75ac40884d..f9adf2e38c 100644 --- a/src/asm/scala/tools/asm/tree/IincInsnNode.java +++ b/src/asm/scala/tools/asm/tree/IincInsnNode.java @@ -54,8 +54,10 @@ public class IincInsnNode extends AbstractInsnNode { /** * Constructs a new {@link IincInsnNode}. * - * @param var index of the local variable to be incremented. - * @param incr increment amount to increment the local variable by. + * @param var + * index of the local variable to be incremented. + * @param incr + * increment amount to increment the local variable by. */ public IincInsnNode(final int var, final int incr) { super(Opcodes.IINC); @@ -77,4 +79,4 @@ public class IincInsnNode extends AbstractInsnNode { public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { return new IincInsnNode(var, incr); } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/InnerClassNode.java b/src/asm/scala/tools/asm/tree/InnerClassNode.java index 4579488921..aa3810c759 100644 --- a/src/asm/scala/tools/asm/tree/InnerClassNode.java +++ b/src/asm/scala/tools/asm/tree/InnerClassNode.java @@ -40,14 +40,14 @@ public class InnerClassNode { /** * The internal name of an inner class (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + * {@link scala.tools.asm.Type#getInternalName() getInternalName}). */ public String name; /** * The internal name of the class to which the inner class belongs (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). May - * be <tt>null</tt>. + * {@link scala.tools.asm.Type#getInternalName() getInternalName}). May be + * <tt>null</tt>. */ public String outerName; @@ -66,24 +66,23 @@ public class InnerClassNode { /** * Constructs a new {@link InnerClassNode}. * - * @param name the internal name of an inner class (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). - * @param outerName the internal name of the class to which the inner class - * belongs (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). - * May be <tt>null</tt>. - * @param innerName the (simple) name of the inner class inside its - * enclosing class. May be <tt>null</tt> for anonymous inner - * classes. - * @param access the access flags of the inner class as originally declared - * in the enclosing class. + * @param name + * the internal name of an inner class (see + * {@link scala.tools.asm.Type#getInternalName() + * getInternalName}). + * @param outerName + * the internal name of the class to which the inner class + * belongs (see {@link scala.tools.asm.Type#getInternalName() + * getInternalName}). May be <tt>null</tt>. + * @param innerName + * the (simple) name of the inner class inside its enclosing + * class. May be <tt>null</tt> for anonymous inner classes. + * @param access + * the access flags of the inner class as originally declared in + * the enclosing class. */ - public InnerClassNode( - final String name, - final String outerName, - final String innerName, - final int access) - { + public InnerClassNode(final String name, final String outerName, + final String innerName, final int access) { this.name = name; this.outerName = outerName; this.innerName = innerName; @@ -93,7 +92,8 @@ public class InnerClassNode { /** * Makes the given class visitor visit this inner class. * - * @param cv a class visitor. + * @param cv + * a class visitor. */ public void accept(final ClassVisitor cv) { cv.visitInnerClass(name, outerName, innerName, access); diff --git a/src/asm/scala/tools/asm/tree/InsnList.java b/src/asm/scala/tools/asm/tree/InsnList.java index dedd3bba73..b1e2d97c6f 100644 --- a/src/asm/scala/tools/asm/tree/InsnList.java +++ b/src/asm/scala/tools/asm/tree/InsnList.java @@ -73,8 +73,8 @@ public class InsnList { /** * Returns the first instruction in this list. * - * @return the first instruction in this list, or <tt>null</tt> if the - * list is empty. + * @return the first instruction in this list, or <tt>null</tt> if the list + * is empty. */ public AbstractInsnNode getFirst() { return first; @@ -96,9 +96,11 @@ public class InsnList { * time it is called. Once the cache is built, this method run in constant * time. This cache is invalidated by all the methods that modify the list. * - * @param index the index of the instruction that must be returned. + * @param index + * the index of the instruction that must be returned. * @return the instruction whose index is given. - * @throws IndexOutOfBoundsException if (index < 0 || index >= size()). + * @throws IndexOutOfBoundsException + * if (index < 0 || index >= size()). */ public AbstractInsnNode get(final int index) { if (index < 0 || index >= size) { @@ -111,11 +113,12 @@ public class InsnList { } /** - * Returns <tt>true</tt> if the given instruction belongs to this list. - * This method always scans the instructions of this list until it finds the + * Returns <tt>true</tt> if the given instruction belongs to this list. This + * method always scans the instructions of this list until it finds the * given instruction or reaches the end of the list. * - * @param insn an instruction. + * @param insn + * an instruction. * @return <tt>true</tt> if the given instruction belongs to this list. */ public boolean contains(final AbstractInsnNode insn) { @@ -133,7 +136,8 @@ public class InsnList { * constant time. The cache is invalidated by all the methods that modify * the list. * - * @param insn an instruction <i>of this list</i>. + * @param insn + * an instruction <i>of this list</i>. * @return the index of the given instruction in this list. <i>The result of * this method is undefined if the given instruction does not belong * to this list</i>. Use {@link #contains contains} to test if an @@ -149,7 +153,8 @@ public class InsnList { /** * Makes the given visitor visit all of the instructions in this list. * - * @param mv the method visitor that must visit the instructions. + * @param mv + * the method visitor that must visit the instructions. */ public void accept(final MethodVisitor mv) { AbstractInsnNode insn = first; @@ -198,9 +203,11 @@ public class InsnList { /** * Replaces an instruction of this list with another instruction. * - * @param location an instruction <i>of this list</i>. - * @param insn another instruction, <i>which must not belong to any - * {@link InsnList}</i>. + * @param location + * an instruction <i>of this list</i>. + * @param insn + * another instruction, <i>which must not belong to any + * {@link InsnList}</i>. */ public void set(final AbstractInsnNode location, final AbstractInsnNode insn) { AbstractInsnNode next = location.next; @@ -232,10 +239,19 @@ public class InsnList { /** * Adds the given instruction to the end of this list. * - * @param insn an instruction, <i>which must not belong to any - * {@link InsnList}</i>. + * @param insn + * an instruction, <i>which must not belong to any + * {@link InsnList}</i>. */ public void add(final AbstractInsnNode insn) { + if(insn.prev != null || insn.next != null) { + // Adding an instruction that still refers to others (in the same or another InsnList) leads to hard to debug bugs. + // Initially everything may look ok (e.g. iteration follows `next` thus a stale `prev` isn't noticed). + // However, a stale link brings the doubly-linked into disarray e.g. upon removing an element, + // which results in the `next` of a stale `prev` being updated, among other failure scenarios. + // Better fail early. + throw new RuntimeException("Instruction " + insn + " already belongs to some InsnList."); + } ++size; if (last == null) { first = insn; @@ -252,8 +268,9 @@ public class InsnList { /** * Adds the given instructions to the end of this list. * - * @param insns an instruction list, which is cleared during the process. - * This list must be different from 'this'. + * @param insns + * an instruction list, which is cleared during the process. This + * list must be different from 'this'. */ public void add(final InsnList insns) { if (insns.size == 0) { @@ -276,8 +293,9 @@ public class InsnList { /** * Inserts the given instruction at the begining of this list. * - * @param insn an instruction, <i>which must not belong to any - * {@link InsnList}</i>. + * @param insn + * an instruction, <i>which must not belong to any + * {@link InsnList}</i>. */ public void insert(final AbstractInsnNode insn) { ++size; @@ -296,8 +314,9 @@ public class InsnList { /** * Inserts the given instructions at the begining of this list. * - * @param insns an instruction list, which is cleared during the process. - * This list must be different from 'this'. + * @param insns + * an instruction list, which is cleared during the process. This + * list must be different from 'this'. */ public void insert(final InsnList insns) { if (insns.size == 0) { @@ -320,12 +339,15 @@ public class InsnList { /** * Inserts the given instruction after the specified instruction. * - * @param location an instruction <i>of this list</i> after which insn must be - * inserted. - * @param insn the instruction to be inserted, <i>which must not belong to - * any {@link InsnList}</i>. + * @param location + * an instruction <i>of this list</i> after which insn must be + * inserted. + * @param insn + * the instruction to be inserted, <i>which must not belong to + * any {@link InsnList}</i>. */ - public void insert(final AbstractInsnNode location, final AbstractInsnNode insn) { + public void insert(final AbstractInsnNode location, + final AbstractInsnNode insn) { ++size; AbstractInsnNode next = location.next; if (next == null) { @@ -343,10 +365,12 @@ public class InsnList { /** * Inserts the given instructions after the specified instruction. * - * @param location an instruction <i>of this list</i> after which the - * instructions must be inserted. - * @param insns the instruction list to be inserted, which is cleared during - * the process. This list must be different from 'this'. + * @param location + * an instruction <i>of this list</i> after which the + * instructions must be inserted. + * @param insns + * the instruction list to be inserted, which is cleared during + * the process. This list must be different from 'this'. */ public void insert(final AbstractInsnNode location, final InsnList insns) { if (insns.size == 0) { @@ -371,12 +395,15 @@ public class InsnList { /** * Inserts the given instruction before the specified instruction. * - * @param location an instruction <i>of this list</i> before which insn must be - * inserted. - * @param insn the instruction to be inserted, <i>which must not belong to - * any {@link InsnList}</i>. + * @param location + * an instruction <i>of this list</i> before which insn must be + * inserted. + * @param insn + * the instruction to be inserted, <i>which must not belong to + * any {@link InsnList}</i>. */ - public void insertBefore(final AbstractInsnNode location, final AbstractInsnNode insn) { + public void insertBefore(final AbstractInsnNode location, + final AbstractInsnNode insn) { ++size; AbstractInsnNode prev = location.prev; if (prev == null) { @@ -394,37 +421,39 @@ public class InsnList { /** * Inserts the given instructions before the specified instruction. * - * @param location an instruction <i>of this list</i> before which the instructions - * must be inserted. - * @param insns the instruction list to be inserted, which is cleared during - * the process. This list must be different from 'this'. + * @param location + * an instruction <i>of this list</i> before which the + * instructions must be inserted. + * @param insns + * the instruction list to be inserted, which is cleared during + * the process. This list must be different from 'this'. */ - public void insertBefore(final AbstractInsnNode location, final InsnList insns) { + public void insertBefore(final AbstractInsnNode location, + final InsnList insns) { if (insns.size == 0) { return; } size += insns.size; AbstractInsnNode ifirst = insns.first; AbstractInsnNode ilast = insns.last; - AbstractInsnNode prev = location .prev; + AbstractInsnNode prev = location.prev; if (prev == null) { first = ifirst; } else { prev.next = ifirst; } - location .prev = ilast; - ilast.next = location ; + location.prev = ilast; + ilast.next = location; ifirst.prev = prev; cache = null; insns.removeAll(false); } - - /** * Removes the given instruction from this list. * - * @param insn the instruction <i>of this list</i> that must be removed. + * @param insn + * the instruction <i>of this list</i> that must be removed. */ public void remove(final AbstractInsnNode insn) { --size; @@ -456,8 +485,9 @@ public class InsnList { /** * Removes all of the instructions of this list. * - * @param mark if the instructions must be marked as no longer belonging to - * any {@link InsnList}. + * @param mark + * if the instructions must be marked as no longer belonging to + * any {@link InsnList}. */ void removeAll(final boolean mark) { if (mark) { @@ -499,14 +529,14 @@ public class InsnList { } // this class is not generified because it will create bridges - private final class InsnListIterator implements ListIterator/*<AbstractInsnNode>*/ { + private final class InsnListIterator implements ListIterator { AbstractInsnNode next; AbstractInsnNode prev; InsnListIterator(int index) { - if(index==size()) { + if (index == size()) { next = null; prev = getLast(); } else { diff --git a/src/asm/scala/tools/asm/tree/InsnNode.java b/src/asm/scala/tools/asm/tree/InsnNode.java index d4664d23c2..4d5288cafa 100644 --- a/src/asm/scala/tools/asm/tree/InsnNode.java +++ b/src/asm/scala/tools/asm/tree/InsnNode.java @@ -43,20 +43,22 @@ public class InsnNode extends AbstractInsnNode { /** * Constructs a new {@link InsnNode}. * - * @param opcode the opcode of the instruction to be constructed. This - * opcode must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, - * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, - * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, - * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, - * FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, - * DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, - * FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, - * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, - * ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, - * LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, - * I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, - * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, - * MONITORENTER, or MONITOREXIT. + * @param opcode + * the opcode of the instruction to be constructed. This opcode + * must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, + * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, + * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, + * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, + * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, + * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, + * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, + * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, + * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, + * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, + * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, + * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, + * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, + * or MONITOREXIT. */ public InsnNode(final int opcode) { super(opcode); @@ -70,7 +72,8 @@ public class InsnNode extends AbstractInsnNode { /** * Makes the given visitor visit this instruction. * - * @param mv a method visitor. + * @param mv + * a method visitor. */ @Override public void accept(final MethodVisitor mv) { diff --git a/src/asm/scala/tools/asm/tree/IntInsnNode.java b/src/asm/scala/tools/asm/tree/IntInsnNode.java index b61270c786..e0aeed4bc8 100644 --- a/src/asm/scala/tools/asm/tree/IntInsnNode.java +++ b/src/asm/scala/tools/asm/tree/IntInsnNode.java @@ -48,9 +48,11 @@ public class IntInsnNode extends AbstractInsnNode { /** * Constructs a new {@link IntInsnNode}. * - * @param opcode the opcode of the instruction to be constructed. This - * opcode must be BIPUSH, SIPUSH or NEWARRAY. - * @param operand the operand of the instruction to be constructed. + * @param opcode + * the opcode of the instruction to be constructed. This opcode + * must be BIPUSH, SIPUSH or NEWARRAY. + * @param operand + * the operand of the instruction to be constructed. */ public IntInsnNode(final int opcode, final int operand) { super(opcode); @@ -60,8 +62,9 @@ public class IntInsnNode extends AbstractInsnNode { /** * Sets the opcode of this instruction. * - * @param opcode the new instruction opcode. This opcode must be BIPUSH, - * SIPUSH or NEWARRAY. + * @param opcode + * the new instruction opcode. This opcode must be BIPUSH, SIPUSH + * or NEWARRAY. */ public void setOpcode(final int opcode) { this.opcode = opcode; diff --git a/src/asm/scala/tools/asm/tree/InvokeDynamicInsnNode.java b/src/asm/scala/tools/asm/tree/InvokeDynamicInsnNode.java index d993b5a054..7ee84b875b 100644 --- a/src/asm/scala/tools/asm/tree/InvokeDynamicInsnNode.java +++ b/src/asm/scala/tools/asm/tree/InvokeDynamicInsnNode.java @@ -65,17 +65,17 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode { /** * Constructs a new {@link InvokeDynamicInsnNode}. * - * @param name invokedynamic name. - * @param desc invokedynamic descriptor (see {@link org.objectweb.asm.Type}). - * @param bsm the bootstrap method. - * @param bsmArgs the boostrap constant arguments. + * @param name + * invokedynamic name. + * @param desc + * invokedynamic descriptor (see {@link scala.tools.asm.Type}). + * @param bsm + * the bootstrap method. + * @param bsmArgs + * the boostrap constant arguments. */ - public InvokeDynamicInsnNode( - final String name, - final String desc, - final Handle bsm, - final Object... bsmArgs) - { + public InvokeDynamicInsnNode(final String name, final String desc, + final Handle bsm, final Object... bsmArgs) { super(Opcodes.INVOKEDYNAMIC); this.name = name; this.desc = desc; @@ -97,4 +97,4 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode { public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs); } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/JumpInsnNode.java b/src/asm/scala/tools/asm/tree/JumpInsnNode.java index 339ebbd2d0..81e1e09deb 100644 --- a/src/asm/scala/tools/asm/tree/JumpInsnNode.java +++ b/src/asm/scala/tools/asm/tree/JumpInsnNode.java @@ -50,13 +50,15 @@ public class JumpInsnNode extends AbstractInsnNode { /** * Constructs a new {@link JumpInsnNode}. * - * @param opcode the opcode of the type instruction to be constructed. This - * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, - * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, - * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. - * @param label the operand of the instruction to be constructed. This - * operand is a label that designates the instruction to which the - * jump instruction may jump. + * @param opcode + * the opcode of the type instruction to be constructed. This + * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, + * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, + * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. + * @param label + * the operand of the instruction to be constructed. This operand + * is a label that designates the instruction to which the jump + * instruction may jump. */ public JumpInsnNode(final int opcode, final LabelNode label) { super(opcode); @@ -66,10 +68,11 @@ public class JumpInsnNode extends AbstractInsnNode { /** * Sets the opcode of this instruction. * - * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE, - * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, - * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, - * IFNULL or IFNONNULL. + * @param opcode + * the new instruction opcode. This opcode must be IFEQ, IFNE, + * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, + * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, + * JSR, IFNULL or IFNONNULL. */ public void setOpcode(final int opcode) { this.opcode = opcode; diff --git a/src/asm/scala/tools/asm/tree/LabelNode.java b/src/asm/scala/tools/asm/tree/LabelNode.java index 523a8d6442..44c48c1160 100644 --- a/src/asm/scala/tools/asm/tree/LabelNode.java +++ b/src/asm/scala/tools/asm/tree/LabelNode.java @@ -75,4 +75,4 @@ public class LabelNode extends AbstractInsnNode { public void resetLabel() { label = null; } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/LdcInsnNode.java b/src/asm/scala/tools/asm/tree/LdcInsnNode.java index f8d115acd5..4e328f9b39 100644 --- a/src/asm/scala/tools/asm/tree/LdcInsnNode.java +++ b/src/asm/scala/tools/asm/tree/LdcInsnNode.java @@ -44,16 +44,17 @@ public class LdcInsnNode extends AbstractInsnNode { /** * The constant to be loaded on the stack. This parameter must be a non null * {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a - * {@link String} or a {@link org.objectweb.asm.Type}. + * {@link String} or a {@link scala.tools.asm.Type}. */ public Object cst; /** * Constructs a new {@link LdcInsnNode}. * - * @param cst the constant to be loaded on the stack. This parameter must be - * a non null {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double} or a {@link String}. + * @param cst + * the constant to be loaded on the stack. This parameter must be + * a non null {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} or a {@link String}. */ public LdcInsnNode(final Object cst) { super(Opcodes.LDC); @@ -74,4 +75,4 @@ public class LdcInsnNode extends AbstractInsnNode { public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { return new LdcInsnNode(cst); } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/LineNumberNode.java b/src/asm/scala/tools/asm/tree/LineNumberNode.java index acc83c8d30..9947aa70a9 100644 --- a/src/asm/scala/tools/asm/tree/LineNumberNode.java +++ b/src/asm/scala/tools/asm/tree/LineNumberNode.java @@ -55,9 +55,11 @@ public class LineNumberNode extends AbstractInsnNode { /** * Constructs a new {@link LineNumberNode}. * - * @param line a line number. This number refers to the source file from - * which the class was compiled. - * @param start the first instruction corresponding to this line number. + * @param line + * a line number. This number refers to the source file from + * which the class was compiled. + * @param start + * the first instruction corresponding to this line number. */ public LineNumberNode(final int line, final LabelNode start) { super(-1); diff --git a/src/asm/scala/tools/asm/tree/LocalVariableNode.java b/src/asm/scala/tools/asm/tree/LocalVariableNode.java index 51cbd3ca00..0d8e27356f 100644 --- a/src/asm/scala/tools/asm/tree/LocalVariableNode.java +++ b/src/asm/scala/tools/asm/tree/LocalVariableNode.java @@ -73,24 +73,24 @@ public class LocalVariableNode { /** * Constructs a new {@link LocalVariableNode}. * - * @param name the name of a local variable. - * @param desc the type descriptor of this local variable. - * @param signature the signature of this local variable. May be - * <tt>null</tt>. - * @param start the first instruction corresponding to the scope of this - * local variable (inclusive). - * @param end the last instruction corresponding to the scope of this local - * variable (exclusive). - * @param index the local variable's index. + * @param name + * the name of a local variable. + * @param desc + * the type descriptor of this local variable. + * @param signature + * the signature of this local variable. May be <tt>null</tt>. + * @param start + * the first instruction corresponding to the scope of this local + * variable (inclusive). + * @param end + * the last instruction corresponding to the scope of this local + * variable (exclusive). + * @param index + * the local variable's index. */ - public LocalVariableNode( - final String name, - final String desc, - final String signature, - final LabelNode start, - final LabelNode end, - final int index) - { + public LocalVariableNode(final String name, final String desc, + final String signature, final LabelNode start, final LabelNode end, + final int index) { this.name = name; this.desc = desc; this.signature = signature; @@ -102,14 +102,11 @@ public class LocalVariableNode { /** * Makes the given visitor visit this local variable declaration. * - * @param mv a method visitor. + * @param mv + * a method visitor. */ public void accept(final MethodVisitor mv) { - mv.visitLocalVariable(name, - desc, - signature, - start.getLabel(), - end.getLabel(), - index); + mv.visitLocalVariable(name, desc, signature, start.getLabel(), + end.getLabel(), index); } } diff --git a/src/asm/scala/tools/asm/tree/LookupSwitchInsnNode.java b/src/asm/scala/tools/asm/tree/LookupSwitchInsnNode.java index 6d0f971c29..d2479b4814 100644 --- a/src/asm/scala/tools/asm/tree/LookupSwitchInsnNode.java +++ b/src/asm/scala/tools/asm/tree/LookupSwitchInsnNode.java @@ -64,20 +64,21 @@ public class LookupSwitchInsnNode extends AbstractInsnNode { /** * Constructs a new {@link LookupSwitchInsnNode}. * - * @param dflt beginning of the default handler block. - * @param keys the values of the keys. - * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is - * the beginning of the handler block for the <tt>keys[i]</tt> key. + * @param dflt + * beginning of the default handler block. + * @param keys + * the values of the keys. + * @param labels + * beginnings of the handler blocks. <tt>labels[i]</tt> is the + * beginning of the handler block for the <tt>keys[i]</tt> key. */ - public LookupSwitchInsnNode( - final LabelNode dflt, - final int[] keys, - final LabelNode[] labels) - { + public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys, + final LabelNode[] labels) { super(Opcodes.LOOKUPSWITCH); this.dflt = dflt; this.keys = new ArrayList<Integer>(keys == null ? 0 : keys.length); - this.labels = new ArrayList<LabelNode>(labels == null ? 0 : labels.length); + this.labels = new ArrayList<LabelNode>(labels == null ? 0 + : labels.length); if (keys != null) { for (int i = 0; i < keys.length; ++i) { this.keys.add(new Integer(keys[i])); diff --git a/src/asm/scala/tools/asm/tree/MethodInsnNode.java b/src/asm/scala/tools/asm/tree/MethodInsnNode.java index c3036bc6b4..bf09f556d8 100644 --- a/src/asm/scala/tools/asm/tree/MethodInsnNode.java +++ b/src/asm/scala/tools/asm/tree/MethodInsnNode.java @@ -43,7 +43,7 @@ public class MethodInsnNode extends AbstractInsnNode { /** * The internal name of the method's owner class (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + * {@link scala.tools.asm.Type#getInternalName() getInternalName}). */ public String owner; @@ -53,27 +53,28 @@ public class MethodInsnNode extends AbstractInsnNode { public String name; /** - * The method's descriptor (see {@link org.objectweb.asm.Type}). + * The method's descriptor (see {@link scala.tools.asm.Type}). */ public String desc; /** * Constructs a new {@link MethodInsnNode}. * - * @param opcode the opcode of the type instruction to be constructed. This - * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or - * INVOKEINTERFACE. - * @param owner the internal name of the method's owner class (see - * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). - * @param name the method's name. - * @param desc the method's descriptor (see {@link org.objectweb.asm.Type}). + * @param opcode + * the opcode of the type instruction to be constructed. This + * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner + * the internal name of the method's owner class (see + * {@link scala.tools.asm.Type#getInternalName() + * getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link scala.tools.asm.Type}). */ - public MethodInsnNode( - final int opcode, - final String owner, - final String name, - final String desc) - { + public MethodInsnNode(final int opcode, final String owner, + final String name, final String desc) { super(opcode); this.owner = owner; this.name = name; @@ -83,8 +84,9 @@ public class MethodInsnNode extends AbstractInsnNode { /** * Sets the opcode of this instruction. * - * @param opcode the new instruction opcode. This opcode must be - * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE. + * @param opcode + * the new instruction opcode. This opcode must be INVOKEVIRTUAL, + * INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE. */ public void setOpcode(final int opcode) { this.opcode = opcode; @@ -104,4 +106,4 @@ public class MethodInsnNode extends AbstractInsnNode { public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { return new MethodInsnNode(opcode, owner, name, desc); } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/MethodNode.java b/src/asm/scala/tools/asm/tree/MethodNode.java index 70ec39e058..5f9c778e0c 100644 --- a/src/asm/scala/tools/asm/tree/MethodNode.java +++ b/src/asm/scala/tools/asm/tree/MethodNode.java @@ -81,7 +81,7 @@ public class MethodNode extends MethodVisitor { * The runtime visible annotations of this method. This list is a list of * {@link AnnotationNode} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.tree.AnnotationNode + * @associates scala.tools.asm.tree.AnnotationNode * @label visible */ public List<AnnotationNode> visibleAnnotations; @@ -90,7 +90,7 @@ public class MethodNode extends MethodVisitor { * The runtime invisible annotations of this method. This list is a list of * {@link AnnotationNode} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.tree.AnnotationNode + * @associates scala.tools.asm.tree.AnnotationNode * @label invisible */ public List<AnnotationNode> invisibleAnnotations; @@ -99,7 +99,7 @@ public class MethodNode extends MethodVisitor { * The non standard attributes of this method. This list is a list of * {@link Attribute} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.Attribute + * @associates scala.tools.asm.Attribute */ public List<Attribute> attrs; @@ -117,7 +117,7 @@ public class MethodNode extends MethodVisitor { * The runtime visible parameter annotations of this method. These lists are * lists of {@link AnnotationNode} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.tree.AnnotationNode + * @associates scala.tools.asm.tree.AnnotationNode * @label invisible parameters */ public List<AnnotationNode>[] visibleParameterAnnotations; @@ -126,7 +126,7 @@ public class MethodNode extends MethodVisitor { * The runtime invisible parameter annotations of this method. These lists * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>. * - * @associates org.objectweb.asm.tree.AnnotationNode + * @associates scala.tools.asm.tree.AnnotationNode * @label visible parameters */ public List<AnnotationNode>[] invisibleParameterAnnotations; @@ -135,7 +135,7 @@ public class MethodNode extends MethodVisitor { * The instructions of this method. This list is a list of * {@link AbstractInsnNode} objects. * - * @associates org.objectweb.asm.tree.AbstractInsnNode + * @associates scala.tools.asm.tree.AbstractInsnNode * @label instructions */ public InsnList instructions; @@ -144,7 +144,7 @@ public class MethodNode extends MethodVisitor { * The try catch blocks of this method. This list is a list of * {@link TryCatchBlockNode} objects. * - * @associates org.objectweb.asm.tree.TryCatchBlockNode + * @associates scala.tools.asm.tree.TryCatchBlockNode */ public List<TryCatchBlockNode> tryCatchBlocks; @@ -162,7 +162,7 @@ public class MethodNode extends MethodVisitor { * The local variables of this method. This list is a list of * {@link LocalVariableNode} objects. May be <tt>null</tt> * - * @associates org.objectweb.asm.tree.LocalVariableNode + * @associates scala.tools.asm.tree.LocalVariableNode */ public List<LocalVariableNode> localVariables; @@ -170,7 +170,7 @@ public class MethodNode extends MethodVisitor { * If the accept method has been called on this object. */ private boolean visited; - + /** * Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not * use this constructor</i>. Instead, they must use the @@ -183,8 +183,9 @@ public class MethodNode extends MethodVisitor { /** * Constructs an uninitialized {@link MethodNode}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. */ public MethodNode(final int api) { super(api); @@ -196,56 +197,55 @@ public class MethodNode extends MethodVisitor { * constructor</i>. Instead, they must use the * {@link #MethodNode(int, int, String, String, String, String[])} version. * - * @param access the method's access flags (see {@link Opcodes}). This - * parameter also indicates if the method is synthetic and/or - * deprecated. - * @param name the method's name. - * @param desc the method's descriptor (see {@link Type}). - * @param signature the method's signature. May be <tt>null</tt>. - * @param exceptions the internal names of the method's exception classes - * (see {@link Type#getInternalName() getInternalName}). May be - * <tt>null</tt>. + * @param access + * the method's access flags (see {@link Opcodes}). This + * parameter also indicates if the method is synthetic and/or + * deprecated. + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type}). + * @param signature + * the method's signature. May be <tt>null</tt>. + * @param exceptions + * the internal names of the method's exception classes (see + * {@link Type#getInternalName() getInternalName}). May be + * <tt>null</tt>. */ - public MethodNode( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { + public MethodNode(final int access, final String name, final String desc, + final String signature, final String[] exceptions) { this(Opcodes.ASM4, access, name, desc, signature, exceptions); } /** * Constructs a new {@link MethodNode}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param access the method's access flags (see {@link Opcodes}). This - * parameter also indicates if the method is synthetic and/or - * deprecated. - * @param name the method's name. - * @param desc the method's descriptor (see {@link Type}). - * @param signature the method's signature. May be <tt>null</tt>. - * @param exceptions the internal names of the method's exception classes - * (see {@link Type#getInternalName() getInternalName}). May be - * <tt>null</tt>. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param access + * the method's access flags (see {@link Opcodes}). This + * parameter also indicates if the method is synthetic and/or + * deprecated. + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type}). + * @param signature + * the method's signature. May be <tt>null</tt>. + * @param exceptions + * the internal names of the method's exception classes (see + * {@link Type#getInternalName() getInternalName}). May be + * <tt>null</tt>. */ - public MethodNode( - final int api, - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { + public MethodNode(final int api, final int access, final String name, + final String desc, final String signature, final String[] exceptions) { super(api); this.access = access; this.name = name; this.desc = desc; this.signature = signature; - this.exceptions = new ArrayList<String>(exceptions == null - ? 0 + this.exceptions = new ArrayList<String>(exceptions == null ? 0 : exceptions.length); boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0; if (!isAbstract) { @@ -274,10 +274,8 @@ public class MethodNode extends MethodVisitor { } @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { AnnotationNode an = new AnnotationNode(desc); if (visible) { if (visibleAnnotations == null) { @@ -294,28 +292,27 @@ public class MethodNode extends MethodVisitor { } @Override - public AnnotationVisitor visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) - { + public AnnotationVisitor visitParameterAnnotation(final int parameter, + final String desc, final boolean visible) { AnnotationNode an = new AnnotationNode(desc); if (visible) { if (visibleParameterAnnotations == null) { int params = Type.getArgumentTypes(this.desc).length; - visibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params]; + visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; } if (visibleParameterAnnotations[parameter] == null) { - visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1); + visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>( + 1); } visibleParameterAnnotations[parameter].add(an); } else { if (invisibleParameterAnnotations == null) { int params = Type.getArgumentTypes(this.desc).length; - invisibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params]; + invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; } if (invisibleParameterAnnotations[parameter] == null) { - invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1); + invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>( + 1); } invisibleParameterAnnotations[parameter].add(an); } @@ -335,17 +332,10 @@ public class MethodNode extends MethodVisitor { } @Override - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) - { - instructions.add(new FrameNode(type, nLocal, local == null - ? null - : getLabelNodes(local), nStack, stack == null - ? null + public void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack) { + instructions.add(new FrameNode(type, nLocal, local == null ? null + : getLabelNodes(local), nStack, stack == null ? null : getLabelNodes(stack))); } @@ -370,32 +360,20 @@ public class MethodNode extends MethodVisitor { } @Override - public void visitFieldInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc) { instructions.add(new FieldInsnNode(opcode, owner, name, desc)); } @Override - public void visitMethodInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { instructions.add(new MethodInsnNode(opcode, owner, name, desc)); } @Override - public void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs) - { + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)); } @@ -420,26 +398,16 @@ public class MethodNode extends MethodVisitor { } @Override - public void visitTableSwitchInsn( - final int min, - final int max, - final Label dflt, - final Label... labels) - { - instructions.add(new TableSwitchInsnNode(min, - max, - getLabelNode(dflt), + public void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels) { + instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt), getLabelNodes(labels))); } @Override - public void visitLookupSwitchInsn( - final Label dflt, - final int[] keys, - final Label[] labels) - { - instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), - keys, + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, + final Label[] labels) { + instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys, getLabelNodes(labels))); } @@ -449,33 +417,18 @@ public class MethodNode extends MethodVisitor { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type) { tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start), - getLabelNode(end), - getLabelNode(handler), - type)); + getLabelNode(end), getLabelNode(handler), type)); } @Override - public void visitLocalVariable( - final String name, - final String desc, - final String signature, - final Label start, - final Label end, - final int index) - { - localVariables.add(new LocalVariableNode(name, - desc, - signature, - getLabelNode(start), - getLabelNode(end), - index)); + public void visitLocalVariable(final String name, final String desc, + final String signature, final Label start, final Label end, + final int index) { + localVariables.add(new LocalVariableNode(name, desc, signature, + getLabelNode(start), getLabelNode(end), index)); } @Override @@ -499,12 +452,13 @@ public class MethodNode extends MethodVisitor { * the {@link Label#info} field to store associations between labels and * label nodes. * - * @param l a Label. + * @param l + * a Label. * @return the LabelNode corresponding to l. */ protected LabelNode getLabelNode(final Label l) { if (!(l.info instanceof LabelNode)) { - l.info = new LabelNode(l); + l.info = new LabelNode(); } return (LabelNode) l.info; } @@ -539,7 +493,8 @@ public class MethodNode extends MethodVisitor { * recursively, do not contain elements that were introduced in more recent * versions of the ASM API than the given version. * - * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}. + * @param api + * an ASM API version. Must be one of {@link Opcodes#ASM4}. */ public void check(final int api) { // nothing to do @@ -548,15 +503,13 @@ public class MethodNode extends MethodVisitor { /** * Makes the given class visitor visit this method. * - * @param cv a class visitor. + * @param cv + * a class visitor. */ public void accept(final ClassVisitor cv) { String[] exceptions = new String[this.exceptions.size()]; this.exceptions.toArray(exceptions); - MethodVisitor mv = cv.visitMethod(access, - name, - desc, - signature, + MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); if (mv != null) { accept(mv); @@ -566,7 +519,8 @@ public class MethodNode extends MethodVisitor { /** * Makes the given method visitor visit this method. * - * @param mv a method visitor. + * @param mv + * a method visitor. */ public void accept(final MethodVisitor mv) { // visits the method attributes @@ -588,8 +542,7 @@ public class MethodNode extends MethodVisitor { AnnotationNode an = invisibleAnnotations.get(i); an.accept(mv.visitAnnotation(an.desc, false)); } - n = visibleParameterAnnotations == null - ? 0 + n = visibleParameterAnnotations == null ? 0 : visibleParameterAnnotations.length; for (i = 0; i < n; ++i) { List<?> l = visibleParameterAnnotations[i]; @@ -601,8 +554,7 @@ public class MethodNode extends MethodVisitor { an.accept(mv.visitParameterAnnotation(i, an.desc, true)); } } - n = invisibleParameterAnnotations == null - ? 0 + n = invisibleParameterAnnotations == null ? 0 : invisibleParameterAnnotations.length; for (i = 0; i < n; ++i) { List<?> l = invisibleParameterAnnotations[i]; diff --git a/src/asm/scala/tools/asm/tree/MultiANewArrayInsnNode.java b/src/asm/scala/tools/asm/tree/MultiANewArrayInsnNode.java index 9dfba77335..fe5e8832b3 100644 --- a/src/asm/scala/tools/asm/tree/MultiANewArrayInsnNode.java +++ b/src/asm/scala/tools/asm/tree/MultiANewArrayInsnNode.java @@ -42,7 +42,7 @@ import scala.tools.asm.Opcodes; public class MultiANewArrayInsnNode extends AbstractInsnNode { /** - * An array type descriptor (see {@link org.objectweb.asm.Type}). + * An array type descriptor (see {@link scala.tools.asm.Type}). */ public String desc; @@ -54,8 +54,10 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode { /** * Constructs a new {@link MultiANewArrayInsnNode}. * - * @param desc an array type descriptor (see {@link org.objectweb.asm.Type}). - * @param dims number of dimensions of the array to allocate. + * @param desc + * an array type descriptor (see {@link scala.tools.asm.Type}). + * @param dims + * number of dimensions of the array to allocate. */ public MultiANewArrayInsnNode(final String desc, final int dims) { super(Opcodes.MULTIANEWARRAY); @@ -78,4 +80,4 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode { return new MultiANewArrayInsnNode(desc, dims); } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/TableSwitchInsnNode.java b/src/asm/scala/tools/asm/tree/TableSwitchInsnNode.java index 929ad9b32b..9b3c2a3437 100644 --- a/src/asm/scala/tools/asm/tree/TableSwitchInsnNode.java +++ b/src/asm/scala/tools/asm/tree/TableSwitchInsnNode.java @@ -69,18 +69,18 @@ public class TableSwitchInsnNode extends AbstractInsnNode { /** * Constructs a new {@link TableSwitchInsnNode}. * - * @param min the minimum key value. - * @param max the maximum key value. - * @param dflt beginning of the default handler block. - * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is - * the beginning of the handler block for the <tt>min + i</tt> key. + * @param min + * the minimum key value. + * @param max + * the maximum key value. + * @param dflt + * beginning of the default handler block. + * @param labels + * beginnings of the handler blocks. <tt>labels[i]</tt> is the + * beginning of the handler block for the <tt>min + i</tt> key. */ - public TableSwitchInsnNode( - final int min, - final int max, - final LabelNode dflt, - final LabelNode... labels) - { + public TableSwitchInsnNode(final int min, final int max, + final LabelNode dflt, final LabelNode... labels) { super(Opcodes.TABLESWITCH); this.min = min; this.max = max; @@ -107,9 +107,7 @@ public class TableSwitchInsnNode extends AbstractInsnNode { @Override public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new TableSwitchInsnNode(min, - max, - clone(dflt, labels), - clone(this.labels, labels)); + return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone( + this.labels, labels)); } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/TryCatchBlockNode.java b/src/asm/scala/tools/asm/tree/TryCatchBlockNode.java index 375b4cfcb9..ab4fa97c34 100644 --- a/src/asm/scala/tools/asm/tree/TryCatchBlockNode.java +++ b/src/asm/scala/tools/asm/tree/TryCatchBlockNode.java @@ -62,19 +62,19 @@ public class TryCatchBlockNode { /** * Constructs a new {@link TryCatchBlockNode}. * - * @param start beginning of the exception handler's scope (inclusive). - * @param end end of the exception handler's scope (exclusive). - * @param handler beginning of the exception handler's code. - * @param type internal name of the type of exceptions handled by the - * handler, or <tt>null</tt> to catch any exceptions (for "finally" - * blocks). + * @param start + * beginning of the exception handler's scope (inclusive). + * @param end + * end of the exception handler's scope (exclusive). + * @param handler + * beginning of the exception handler's code. + * @param type + * internal name of the type of exceptions handled by the + * handler, or <tt>null</tt> to catch any exceptions (for + * "finally" blocks). */ - public TryCatchBlockNode( - final LabelNode start, - final LabelNode end, - final LabelNode handler, - final String type) - { + public TryCatchBlockNode(final LabelNode start, final LabelNode end, + final LabelNode handler, final String type) { this.start = start; this.end = end; this.handler = handler; @@ -84,11 +84,11 @@ public class TryCatchBlockNode { /** * Makes the given visitor visit this try catch block. * - * @param mv a method visitor. + * @param mv + * a method visitor. */ public void accept(final MethodVisitor mv) { - mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), handler == null - ? null - : handler.getLabel(), type); + mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), + handler == null ? null : handler.getLabel(), type); } } diff --git a/src/asm/scala/tools/asm/tree/TypeInsnNode.java b/src/asm/scala/tools/asm/tree/TypeInsnNode.java index 0b2666c498..3210dd60e6 100644 --- a/src/asm/scala/tools/asm/tree/TypeInsnNode.java +++ b/src/asm/scala/tools/asm/tree/TypeInsnNode.java @@ -43,17 +43,19 @@ public class TypeInsnNode extends AbstractInsnNode { /** * The operand of this instruction. This operand is an internal name (see - * {@link org.objectweb.asm.Type}). + * {@link scala.tools.asm.Type}). */ public String desc; /** * Constructs a new {@link TypeInsnNode}. * - * @param opcode the opcode of the type instruction to be constructed. This - * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. - * @param desc the operand of the instruction to be constructed. This - * operand is an internal name (see {@link org.objectweb.asm.Type}). + * @param opcode + * the opcode of the type instruction to be constructed. This + * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. + * @param desc + * the operand of the instruction to be constructed. This operand + * is an internal name (see {@link scala.tools.asm.Type}). */ public TypeInsnNode(final int opcode, final String desc) { super(opcode); @@ -63,8 +65,9 @@ public class TypeInsnNode extends AbstractInsnNode { /** * Sets the opcode of this instruction. * - * @param opcode the new instruction opcode. This opcode must be NEW, - * ANEWARRAY, CHECKCAST or INSTANCEOF. + * @param opcode + * the new instruction opcode. This opcode must be NEW, + * ANEWARRAY, CHECKCAST or INSTANCEOF. */ public void setOpcode(final int opcode) { this.opcode = opcode; @@ -84,4 +87,4 @@ public class TypeInsnNode extends AbstractInsnNode { public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { return new TypeInsnNode(opcode, desc); } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/VarInsnNode.java b/src/asm/scala/tools/asm/tree/VarInsnNode.java index 89f572db59..5dd9ef6726 100644 --- a/src/asm/scala/tools/asm/tree/VarInsnNode.java +++ b/src/asm/scala/tools/asm/tree/VarInsnNode.java @@ -51,11 +51,13 @@ public class VarInsnNode extends AbstractInsnNode { /** * Constructs a new {@link VarInsnNode}. * - * @param opcode the opcode of the local variable instruction to be - * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD, - * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. - * @param var the operand of the instruction to be constructed. This operand - * is the index of a local variable. + * @param opcode + * the opcode of the local variable instruction to be + * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD, + * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. + * @param var + * the operand of the instruction to be constructed. This operand + * is the index of a local variable. */ public VarInsnNode(final int opcode, final int var) { super(opcode); @@ -65,9 +67,10 @@ public class VarInsnNode extends AbstractInsnNode { /** * Sets the opcode of this instruction. * - * @param opcode the new instruction opcode. This opcode must be ILOAD, - * LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE - * or RET. + * @param opcode + * the new instruction opcode. This opcode must be ILOAD, LLOAD, + * FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or + * RET. */ public void setOpcode(final int opcode) { this.opcode = opcode; @@ -87,4 +90,4 @@ public class VarInsnNode extends AbstractInsnNode { public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { return new VarInsnNode(opcode, var); } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/tree/analysis/Analyzer.java b/src/asm/scala/tools/asm/tree/analysis/Analyzer.java index df387b0b8e..0134555f10 100644 --- a/src/asm/scala/tools/asm/tree/analysis/Analyzer.java +++ b/src/asm/scala/tools/asm/tree/analysis/Analyzer.java @@ -51,9 +51,10 @@ import scala.tools.asm.tree.VarInsnNode; * A semantic bytecode analyzer. <i>This class does not fully check that JSR and * RET instructions are valid.</i> * - * @param <V> type of the Value used for the analysis. + * @param <V> + * type of the Value used for the analysis. * - * @author Eric Bruneton + * @author Eric Bruneton */ public class Analyzer<V extends Value> implements Opcodes { @@ -78,8 +79,9 @@ public class Analyzer<V extends Value> implements Opcodes { /** * Constructs a new {@link Analyzer}. * - * @param interpreter the interpreter to be used to symbolically interpret - * the bytecode instructions. + * @param interpreter + * the interpreter to be used to symbolically interpret the + * bytecode instructions. */ public Analyzer(final Interpreter<V> interpreter) { this.interpreter = interpreter; @@ -88,26 +90,28 @@ public class Analyzer<V extends Value> implements Opcodes { /** * Analyzes the given method. * - * @param owner the internal name of the class to which the method belongs. - * @param m the method to be analyzed. + * @param owner + * the internal name of the class to which the method belongs. + * @param m + * the method to be analyzed. * @return the symbolic state of the execution stack frame at each bytecode * instruction of the method. The size of the returned array is * equal to the number of instructions (and labels) of the method. A * given frame is <tt>null</tt> if and only if the corresponding * instruction cannot be reached (dead code). - * @throws AnalyzerException if a problem occurs during the analysis. + * @throws AnalyzerException + * if a problem occurs during the analysis. */ public Frame<V>[] analyze(final String owner, final MethodNode m) - throws AnalyzerException - { + throws AnalyzerException { if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) { - frames = (Frame<V>[])new Frame<?>[0]; + frames = (Frame<V>[]) new Frame<?>[0]; return frames; } n = m.instructions.size(); insns = m.instructions; - handlers = (List<TryCatchBlockNode>[])new List<?>[n]; - frames = (Frame<V>[])new Frame<?>[n]; + handlers = (List<TryCatchBlockNode>[]) new List<?>[n]; + frames = (Frame<V>[]) new Frame<?>[n]; subroutines = new Subroutine[n]; queued = new boolean[n]; queue = new int[n]; @@ -188,8 +192,7 @@ public class Analyzer<V extends Value> implements Opcodes { if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE - || insnType == AbstractInsnNode.FRAME) - { + || insnType == AbstractInsnNode.FRAME) { merge(insn + 1, f, subroutine); newControlFlowEdge(insn, insn + 1); } else { @@ -205,8 +208,7 @@ public class Analyzer<V extends Value> implements Opcodes { int jump = insns.indexOf(j.label); if (insnOpcode == JSR) { merge(jump, current, new Subroutine(j.label, - m.maxLocals, - j)); + m.maxLocals, j)); } else { merge(jump, current, subroutine); } @@ -235,31 +237,27 @@ public class Analyzer<V extends Value> implements Opcodes { } } else if (insnOpcode == RET) { if (subroutine == null) { - throw new AnalyzerException(insnNode, "RET instruction outside of a sub routine"); + throw new AnalyzerException(insnNode, + "RET instruction outside of a sub routine"); } for (int i = 0; i < subroutine.callers.size(); ++i) { JumpInsnNode caller = subroutine.callers.get(i); int call = insns.indexOf(caller); if (frames[call] != null) { - merge(call + 1, - frames[call], - current, - subroutines[call], - subroutine.access); + merge(call + 1, frames[call], current, + subroutines[call], subroutine.access); newControlFlowEdge(insn, call + 1); } } } else if (insnOpcode != ATHROW - && (insnOpcode < IRETURN || insnOpcode > RETURN)) - { + && (insnOpcode < IRETURN || insnOpcode > RETURN)) { if (subroutine != null) { if (insnNode instanceof VarInsnNode) { int var = ((VarInsnNode) insnNode).var; subroutine.access[var] = true; if (insnOpcode == LLOAD || insnOpcode == DLOAD || insnOpcode == LSTORE - || insnOpcode == DSTORE) - { + || insnOpcode == DSTORE) { subroutine.access[var + 1] = true; } } else if (insnNode instanceof IincInsnNode) { @@ -292,23 +290,23 @@ public class Analyzer<V extends Value> implements Opcodes { } } } catch (AnalyzerException e) { - throw new AnalyzerException(e.node, "Error at instruction " + insn - + ": " + e.getMessage(), e); + throw new AnalyzerException(e.node, "Error at instruction " + + insn + ": " + e.getMessage(), e); } catch (Exception e) { - throw new AnalyzerException(insnNode, "Error at instruction " + insn - + ": " + e.getMessage(), e); + throw new AnalyzerException(insnNode, "Error at instruction " + + insn + ": " + e.getMessage(), e); } } return frames; } - private void findSubroutine(int insn, final Subroutine sub, final List<AbstractInsnNode> calls) - throws AnalyzerException - { + private void findSubroutine(int insn, final Subroutine sub, + final List<AbstractInsnNode> calls) throws AnalyzerException { while (true) { if (insn < 0 || insn >= n) { - throw new AnalyzerException(null, "Execution can fall off end of the code"); + throw new AnalyzerException(null, + "Execution can fall off end of the code"); } if (subroutines[insn] != null) { return; @@ -352,18 +350,18 @@ public class Analyzer<V extends Value> implements Opcodes { // if insn does not falls through to the next instruction, return. switch (node.getOpcode()) { - case GOTO: - case RET: - case TABLESWITCH: - case LOOKUPSWITCH: - case IRETURN: - case LRETURN: - case FRETURN: - case DRETURN: - case ARETURN: - case RETURN: - case ATHROW: - return; + case GOTO: + case RET: + case TABLESWITCH: + case LOOKUPSWITCH: + case IRETURN: + case LRETURN: + case FRETURN: + case DRETURN: + case ARETURN: + case RETURN: + case ATHROW: + return; } insn++; } @@ -387,8 +385,9 @@ public class Analyzer<V extends Value> implements Opcodes { /** * Returns the exception handlers for the given instruction. * - * @param insn the index of an instruction of the last recently analyzed - * method. + * @param insn + * the index of an instruction of the last recently analyzed + * method. * @return a list of {@link TryCatchBlockNode} objects. */ public List<TryCatchBlockNode> getHandlers(final int insn) { @@ -400,9 +399,12 @@ public class Analyzer<V extends Value> implements Opcodes { * execution of control flow analysis loop in #analyze. The default * implementation of this method does nothing. * - * @param owner the internal name of the class to which the method belongs. - * @param m the method to be analyzed. - * @throws AnalyzerException if a problem occurs. + * @param owner + * the internal name of the class to which the method belongs. + * @param m + * the method to be analyzed. + * @throws AnalyzerException + * if a problem occurs. */ protected void init(String owner, MethodNode m) throws AnalyzerException { } @@ -410,8 +412,10 @@ public class Analyzer<V extends Value> implements Opcodes { /** * Constructs a new frame with the given size. * - * @param nLocals the maximum number of local variables of the frame. - * @param nStack the maximum stack size of the frame. + * @param nLocals + * the maximum number of local variables of the frame. + * @param nStack + * the maximum stack size of the frame. * @return the created frame. */ protected Frame<V> newFrame(final int nLocals, final int nStack) { @@ -421,7 +425,8 @@ public class Analyzer<V extends Value> implements Opcodes { /** * Constructs a new frame that is identical to the given frame. * - * @param src a frame. + * @param src + * a frame. * @return the created frame. */ protected Frame<V> newFrame(final Frame<? extends V> src) { @@ -434,8 +439,10 @@ public class Analyzer<V extends Value> implements Opcodes { * control flow graph of a method (this method is called by the * {@link #analyze analyze} method during its visit of the method's code). * - * @param insn an instruction index. - * @param successor index of a successor instruction. + * @param insn + * an instruction index. + * @param successor + * index of a successor instruction. */ protected void newControlFlowEdge(final int insn, final int successor) { } @@ -447,16 +454,16 @@ public class Analyzer<V extends Value> implements Opcodes { * method is called by the {@link #analyze analyze} method during its visit * of the method's code). * - * @param insn an instruction index. - * @param successor index of a successor instruction. + * @param insn + * an instruction index. + * @param successor + * index of a successor instruction. * @return true if this edge must be considered in the data flow analysis * performed by this analyzer, or false otherwise. The default * implementation of this method always returns true. */ - protected boolean newControlFlowExceptionEdge( - final int insn, - final int successor) - { + protected boolean newControlFlowExceptionEdge(final int insn, + final int successor) { return true; } @@ -469,28 +476,25 @@ public class Analyzer<V extends Value> implements Opcodes { * the {@link #analyze analyze} method during its visit of the method's * code). * - * @param insn an instruction index. - * @param tcb TryCatchBlockNode corresponding to this edge. + * @param insn + * an instruction index. + * @param tcb + * TryCatchBlockNode corresponding to this edge. * @return true if this edge must be considered in the data flow analysis * performed by this analyzer, or false otherwise. The default * implementation of this method delegates to * {@link #newControlFlowExceptionEdge(int, int) * newControlFlowExceptionEdge(int, int)}. */ - protected boolean newControlFlowExceptionEdge( - final int insn, - final TryCatchBlockNode tcb) - { + protected boolean newControlFlowExceptionEdge(final int insn, + final TryCatchBlockNode tcb) { return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler)); } // ------------------------------------------------------------------------- - private void merge( - final int insn, - final Frame<V> frame, - final Subroutine subroutine) throws AnalyzerException - { + private void merge(final int insn, final Frame<V> frame, + final Subroutine subroutine) throws AnalyzerException { Frame<V> oldFrame = frames[insn]; Subroutine oldSubroutine = subroutines[insn]; boolean changes; @@ -518,13 +522,9 @@ public class Analyzer<V extends Value> implements Opcodes { } } - private void merge( - final int insn, - final Frame<V> beforeJSR, - final Frame<V> afterRET, - final Subroutine subroutineBeforeJSR, - final boolean[] access) throws AnalyzerException - { + private void merge(final int insn, final Frame<V> beforeJSR, + final Frame<V> afterRET, final Subroutine subroutineBeforeJSR, + final boolean[] access) throws AnalyzerException { Frame<V> oldFrame = frames[insn]; Subroutine oldSubroutine = subroutines[insn]; boolean changes; diff --git a/src/asm/scala/tools/asm/tree/analysis/AnalyzerException.java b/src/asm/scala/tools/asm/tree/analysis/AnalyzerException.java index a89bb3513f..5e3f51f21a 100644 --- a/src/asm/scala/tools/asm/tree/analysis/AnalyzerException.java +++ b/src/asm/scala/tools/asm/tree/analysis/AnalyzerException.java @@ -46,17 +46,14 @@ public class AnalyzerException extends Exception { this.node = node; } - public AnalyzerException(final AbstractInsnNode node, final String msg, final Throwable exception) { + public AnalyzerException(final AbstractInsnNode node, final String msg, + final Throwable exception) { super(msg, exception); this.node = node; } - public AnalyzerException( - final AbstractInsnNode node, - final String msg, - final Object expected, - final Value encountered) - { + public AnalyzerException(final AbstractInsnNode node, final String msg, + final Object expected, final Value encountered) { super((msg == null ? "Expected " : msg + ": expected ") + expected + ", but found " + encountered); this.node = node; diff --git a/src/asm/scala/tools/asm/tree/analysis/BasicInterpreter.java b/src/asm/scala/tools/asm/tree/analysis/BasicInterpreter.java index 64ddcc11e6..8d6653c1c5 100644 --- a/src/asm/scala/tools/asm/tree/analysis/BasicInterpreter.java +++ b/src/asm/scala/tools/asm/tree/analysis/BasicInterpreter.java @@ -50,8 +50,7 @@ import scala.tools.asm.tree.TypeInsnNode; * @author Bing Ran */ public class BasicInterpreter extends Interpreter<BasicValue> implements - Opcodes -{ + Opcodes { public BasicInterpreter() { super(ASM4); @@ -67,292 +66,286 @@ public class BasicInterpreter extends Interpreter<BasicValue> implements return BasicValue.UNINITIALIZED_VALUE; } switch (type.getSort()) { - case Type.VOID: - return null; - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - case Type.INT: - return BasicValue.INT_VALUE; - case Type.FLOAT: - return BasicValue.FLOAT_VALUE; - case Type.LONG: - return BasicValue.LONG_VALUE; - case Type.DOUBLE: - return BasicValue.DOUBLE_VALUE; - case Type.ARRAY: - case Type.OBJECT: - return BasicValue.REFERENCE_VALUE; - default: - throw new Error("Internal error"); + case Type.VOID: + return null; + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + case Type.INT: + return BasicValue.INT_VALUE; + case Type.FLOAT: + return BasicValue.FLOAT_VALUE; + case Type.LONG: + return BasicValue.LONG_VALUE; + case Type.DOUBLE: + return BasicValue.DOUBLE_VALUE; + case Type.ARRAY: + case Type.OBJECT: + return BasicValue.REFERENCE_VALUE; + default: + throw new Error("Internal error"); } } @Override public BasicValue newOperation(final AbstractInsnNode insn) - throws AnalyzerException - { + throws AnalyzerException { switch (insn.getOpcode()) { - case ACONST_NULL: - return newValue(Type.getObjectType("null")); - case ICONST_M1: - case ICONST_0: - case ICONST_1: - case ICONST_2: - case ICONST_3: - case ICONST_4: - case ICONST_5: + case ACONST_NULL: + return newValue(Type.getObjectType("null")); + case ICONST_M1: + case ICONST_0: + case ICONST_1: + case ICONST_2: + case ICONST_3: + case ICONST_4: + case ICONST_5: + return BasicValue.INT_VALUE; + case LCONST_0: + case LCONST_1: + return BasicValue.LONG_VALUE; + case FCONST_0: + case FCONST_1: + case FCONST_2: + return BasicValue.FLOAT_VALUE; + case DCONST_0: + case DCONST_1: + return BasicValue.DOUBLE_VALUE; + case BIPUSH: + case SIPUSH: + return BasicValue.INT_VALUE; + case LDC: + Object cst = ((LdcInsnNode) insn).cst; + if (cst instanceof Integer) { return BasicValue.INT_VALUE; - case LCONST_0: - case LCONST_1: - return BasicValue.LONG_VALUE; - case FCONST_0: - case FCONST_1: - case FCONST_2: + } else if (cst instanceof Float) { return BasicValue.FLOAT_VALUE; - case DCONST_0: - case DCONST_1: + } else if (cst instanceof Long) { + return BasicValue.LONG_VALUE; + } else if (cst instanceof Double) { return BasicValue.DOUBLE_VALUE; - case BIPUSH: - case SIPUSH: - return BasicValue.INT_VALUE; - case LDC: - Object cst = ((LdcInsnNode) insn).cst; - if (cst instanceof Integer) { - return BasicValue.INT_VALUE; - } else if (cst instanceof Float) { - return BasicValue.FLOAT_VALUE; - } else if (cst instanceof Long) { - return BasicValue.LONG_VALUE; - } else if (cst instanceof Double) { - return BasicValue.DOUBLE_VALUE; - } else if (cst instanceof String) { - return newValue(Type.getObjectType("java/lang/String")); - } else if (cst instanceof Type) { - int sort = ((Type) cst).getSort(); - if (sort == Type.OBJECT || sort == Type.ARRAY) { - return newValue(Type.getObjectType("java/lang/Class")); - } else if (sort == Type.METHOD) { - return newValue(Type.getObjectType("java/lang/invoke/MethodType")); - } else { - throw new IllegalArgumentException("Illegal LDC constant " + cst); - } - } else if (cst instanceof Handle) { - return newValue(Type.getObjectType("java/lang/invoke/MethodHandle")); + } else if (cst instanceof String) { + return newValue(Type.getObjectType("java/lang/String")); + } else if (cst instanceof Type) { + int sort = ((Type) cst).getSort(); + if (sort == Type.OBJECT || sort == Type.ARRAY) { + return newValue(Type.getObjectType("java/lang/Class")); + } else if (sort == Type.METHOD) { + return newValue(Type + .getObjectType("java/lang/invoke/MethodType")); } else { - throw new IllegalArgumentException("Illegal LDC constant " + cst); + throw new IllegalArgumentException("Illegal LDC constant " + + cst); } - case JSR: - return BasicValue.RETURNADDRESS_VALUE; - case GETSTATIC: - return newValue(Type.getType(((FieldInsnNode) insn).desc)); - case NEW: - return newValue(Type.getObjectType(((TypeInsnNode) insn).desc)); - default: - throw new Error("Internal error."); + } else if (cst instanceof Handle) { + return newValue(Type + .getObjectType("java/lang/invoke/MethodHandle")); + } else { + throw new IllegalArgumentException("Illegal LDC constant " + + cst); + } + case JSR: + return BasicValue.RETURNADDRESS_VALUE; + case GETSTATIC: + return newValue(Type.getType(((FieldInsnNode) insn).desc)); + case NEW: + return newValue(Type.getObjectType(((TypeInsnNode) insn).desc)); + default: + throw new Error("Internal error."); } } @Override - public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value) - throws AnalyzerException - { + public BasicValue copyOperation(final AbstractInsnNode insn, + final BasicValue value) throws AnalyzerException { return value; } @Override - public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value) - throws AnalyzerException - { + public BasicValue unaryOperation(final AbstractInsnNode insn, + final BasicValue value) throws AnalyzerException { switch (insn.getOpcode()) { - case INEG: - case IINC: - case L2I: - case F2I: - case D2I: - case I2B: - case I2C: - case I2S: - return BasicValue.INT_VALUE; - case FNEG: - case I2F: - case L2F: - case D2F: - return BasicValue.FLOAT_VALUE; - case LNEG: - case I2L: - case F2L: - case D2L: - return BasicValue.LONG_VALUE; - case DNEG: - case I2D: - case L2D: - case F2D: - return BasicValue.DOUBLE_VALUE; - case IFEQ: - case IFNE: - case IFLT: - case IFGE: - case IFGT: - case IFLE: - case TABLESWITCH: - case LOOKUPSWITCH: - case IRETURN: - case LRETURN: - case FRETURN: - case DRETURN: - case ARETURN: - case PUTSTATIC: - return null; - case GETFIELD: - return newValue(Type.getType(((FieldInsnNode) insn).desc)); - case NEWARRAY: - switch (((IntInsnNode) insn).operand) { - case T_BOOLEAN: - return newValue(Type.getType("[Z")); - case T_CHAR: - return newValue(Type.getType("[C")); - case T_BYTE: - return newValue(Type.getType("[B")); - case T_SHORT: - return newValue(Type.getType("[S")); - case T_INT: - return newValue(Type.getType("[I")); - case T_FLOAT: - return newValue(Type.getType("[F")); - case T_DOUBLE: - return newValue(Type.getType("[D")); - case T_LONG: - return newValue(Type.getType("[J")); - default: - throw new AnalyzerException(insn, "Invalid array type"); - } - case ANEWARRAY: - String desc = ((TypeInsnNode) insn).desc; - return newValue(Type.getType("[" + Type.getObjectType(desc))); - case ARRAYLENGTH: - return BasicValue.INT_VALUE; - case ATHROW: - return null; - case CHECKCAST: - desc = ((TypeInsnNode) insn).desc; - return newValue(Type.getObjectType(desc)); - case INSTANCEOF: - return BasicValue.INT_VALUE; - case MONITORENTER: - case MONITOREXIT: - case IFNULL: - case IFNONNULL: - return null; + case INEG: + case IINC: + case L2I: + case F2I: + case D2I: + case I2B: + case I2C: + case I2S: + return BasicValue.INT_VALUE; + case FNEG: + case I2F: + case L2F: + case D2F: + return BasicValue.FLOAT_VALUE; + case LNEG: + case I2L: + case F2L: + case D2L: + return BasicValue.LONG_VALUE; + case DNEG: + case I2D: + case L2D: + case F2D: + return BasicValue.DOUBLE_VALUE; + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case TABLESWITCH: + case LOOKUPSWITCH: + case IRETURN: + case LRETURN: + case FRETURN: + case DRETURN: + case ARETURN: + case PUTSTATIC: + return null; + case GETFIELD: + return newValue(Type.getType(((FieldInsnNode) insn).desc)); + case NEWARRAY: + switch (((IntInsnNode) insn).operand) { + case T_BOOLEAN: + return newValue(Type.getType("[Z")); + case T_CHAR: + return newValue(Type.getType("[C")); + case T_BYTE: + return newValue(Type.getType("[B")); + case T_SHORT: + return newValue(Type.getType("[S")); + case T_INT: + return newValue(Type.getType("[I")); + case T_FLOAT: + return newValue(Type.getType("[F")); + case T_DOUBLE: + return newValue(Type.getType("[D")); + case T_LONG: + return newValue(Type.getType("[J")); default: - throw new Error("Internal error."); + throw new AnalyzerException(insn, "Invalid array type"); + } + case ANEWARRAY: + String desc = ((TypeInsnNode) insn).desc; + return newValue(Type.getType("[" + Type.getObjectType(desc))); + case ARRAYLENGTH: + return BasicValue.INT_VALUE; + case ATHROW: + return null; + case CHECKCAST: + desc = ((TypeInsnNode) insn).desc; + return newValue(Type.getObjectType(desc)); + case INSTANCEOF: + return BasicValue.INT_VALUE; + case MONITORENTER: + case MONITOREXIT: + case IFNULL: + case IFNONNULL: + return null; + default: + throw new Error("Internal error."); } } @Override - public BasicValue binaryOperation( - final AbstractInsnNode insn, - final BasicValue value1, - final BasicValue value2) throws AnalyzerException - { + public BasicValue binaryOperation(final AbstractInsnNode insn, + final BasicValue value1, final BasicValue value2) + throws AnalyzerException { switch (insn.getOpcode()) { - case IALOAD: - case BALOAD: - case CALOAD: - case SALOAD: - case IADD: - case ISUB: - case IMUL: - case IDIV: - case IREM: - case ISHL: - case ISHR: - case IUSHR: - case IAND: - case IOR: - case IXOR: - return BasicValue.INT_VALUE; - case FALOAD: - case FADD: - case FSUB: - case FMUL: - case FDIV: - case FREM: - return BasicValue.FLOAT_VALUE; - case LALOAD: - case LADD: - case LSUB: - case LMUL: - case LDIV: - case LREM: - case LSHL: - case LSHR: - case LUSHR: - case LAND: - case LOR: - case LXOR: - return BasicValue.LONG_VALUE; - case DALOAD: - case DADD: - case DSUB: - case DMUL: - case DDIV: - case DREM: - return BasicValue.DOUBLE_VALUE; - case AALOAD: - return BasicValue.REFERENCE_VALUE; - case LCMP: - case FCMPL: - case FCMPG: - case DCMPL: - case DCMPG: - return BasicValue.INT_VALUE; - case IF_ICMPEQ: - case IF_ICMPNE: - case IF_ICMPLT: - case IF_ICMPGE: - case IF_ICMPGT: - case IF_ICMPLE: - case IF_ACMPEQ: - case IF_ACMPNE: - case PUTFIELD: - return null; - default: - throw new Error("Internal error."); + case IALOAD: + case BALOAD: + case CALOAD: + case SALOAD: + case IADD: + case ISUB: + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + return BasicValue.INT_VALUE; + case FALOAD: + case FADD: + case FSUB: + case FMUL: + case FDIV: + case FREM: + return BasicValue.FLOAT_VALUE; + case LALOAD: + case LADD: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LSHL: + case LSHR: + case LUSHR: + case LAND: + case LOR: + case LXOR: + return BasicValue.LONG_VALUE; + case DALOAD: + case DADD: + case DSUB: + case DMUL: + case DDIV: + case DREM: + return BasicValue.DOUBLE_VALUE; + case AALOAD: + return BasicValue.REFERENCE_VALUE; + case LCMP: + case FCMPL: + case FCMPG: + case DCMPL: + case DCMPG: + return BasicValue.INT_VALUE; + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ACMPEQ: + case IF_ACMPNE: + case PUTFIELD: + return null; + default: + throw new Error("Internal error."); } } @Override - public BasicValue ternaryOperation( - final AbstractInsnNode insn, - final BasicValue value1, - final BasicValue value2, - final BasicValue value3) throws AnalyzerException - { + public BasicValue ternaryOperation(final AbstractInsnNode insn, + final BasicValue value1, final BasicValue value2, + final BasicValue value3) throws AnalyzerException { return null; } @Override - public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) - throws AnalyzerException - { + public BasicValue naryOperation(final AbstractInsnNode insn, + final List<? extends BasicValue> values) throws AnalyzerException { int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); - } else if (opcode == INVOKEDYNAMIC){ - return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc)); + } else if (opcode == INVOKEDYNAMIC) { + return newValue(Type + .getReturnType(((InvokeDynamicInsnNode) insn).desc)); } else { return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); } } @Override - public void returnOperation( - final AbstractInsnNode insn, - final BasicValue value, - final BasicValue expected) throws AnalyzerException - { + public void returnOperation(final AbstractInsnNode insn, + final BasicValue value, final BasicValue expected) + throws AnalyzerException { } @Override diff --git a/src/asm/scala/tools/asm/tree/analysis/BasicValue.java b/src/asm/scala/tools/asm/tree/analysis/BasicValue.java index 6c449db9b0..439941fb9f 100644 --- a/src/asm/scala/tools/asm/tree/analysis/BasicValue.java +++ b/src/asm/scala/tools/asm/tree/analysis/BasicValue.java @@ -48,11 +48,14 @@ public class BasicValue implements Value { public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE); - public static final BasicValue DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE); + public static final BasicValue DOUBLE_VALUE = new BasicValue( + Type.DOUBLE_TYPE); - public static final BasicValue REFERENCE_VALUE = new BasicValue(Type.getObjectType("java/lang/Object")); + public static final BasicValue REFERENCE_VALUE = new BasicValue( + Type.getObjectType("java/lang/Object")); - public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(Type.VOID_TYPE); + public static final BasicValue RETURNADDRESS_VALUE = new BasicValue( + Type.VOID_TYPE); private final Type type; diff --git a/src/asm/scala/tools/asm/tree/analysis/BasicVerifier.java b/src/asm/scala/tools/asm/tree/analysis/BasicVerifier.java index 9297dd9294..71666edb74 100644 --- a/src/asm/scala/tools/asm/tree/analysis/BasicVerifier.java +++ b/src/asm/scala/tools/asm/tree/analysis/BasicVerifier.java @@ -55,47 +55,41 @@ public class BasicVerifier extends BasicInterpreter { } @Override - public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value) - throws AnalyzerException - { + public BasicValue copyOperation(final AbstractInsnNode insn, + final BasicValue value) throws AnalyzerException { Value expected; switch (insn.getOpcode()) { - case ILOAD: - case ISTORE: - expected = BasicValue.INT_VALUE; - break; - case FLOAD: - case FSTORE: - expected = BasicValue.FLOAT_VALUE; - break; - case LLOAD: - case LSTORE: - expected = BasicValue.LONG_VALUE; - break; - case DLOAD: - case DSTORE: - expected = BasicValue.DOUBLE_VALUE; - break; - case ALOAD: - if (!value.isReference()) { - throw new AnalyzerException(insn, - null, - "an object reference", - value); - } - return value; - case ASTORE: - if (!value.isReference() - && !BasicValue.RETURNADDRESS_VALUE.equals(value)) - { - throw new AnalyzerException(insn, - null, - "an object reference or a return address", - value); - } - return value; - default: - return value; + case ILOAD: + case ISTORE: + expected = BasicValue.INT_VALUE; + break; + case FLOAD: + case FSTORE: + expected = BasicValue.FLOAT_VALUE; + break; + case LLOAD: + case LSTORE: + expected = BasicValue.LONG_VALUE; + break; + case DLOAD: + case DSTORE: + expected = BasicValue.DOUBLE_VALUE; + break; + case ALOAD: + if (!value.isReference()) { + throw new AnalyzerException(insn, null, "an object reference", + value); + } + return value; + case ASTORE: + if (!value.isReference() + && !BasicValue.RETURNADDRESS_VALUE.equals(value)) { + throw new AnalyzerException(insn, null, + "an object reference or a return address", value); + } + return value; + default: + return value; } if (!expected.equals(value)) { throw new AnalyzerException(insn, null, expected, value); @@ -104,91 +98,85 @@ public class BasicVerifier extends BasicInterpreter { } @Override - public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value) - throws AnalyzerException - { + public BasicValue unaryOperation(final AbstractInsnNode insn, + final BasicValue value) throws AnalyzerException { BasicValue expected; switch (insn.getOpcode()) { - case INEG: - case IINC: - case I2F: - case I2L: - case I2D: - case I2B: - case I2C: - case I2S: - case IFEQ: - case IFNE: - case IFLT: - case IFGE: - case IFGT: - case IFLE: - case TABLESWITCH: - case LOOKUPSWITCH: - case IRETURN: - case NEWARRAY: - case ANEWARRAY: - expected = BasicValue.INT_VALUE; - break; - case FNEG: - case F2I: - case F2L: - case F2D: - case FRETURN: - expected = BasicValue.FLOAT_VALUE; - break; - case LNEG: - case L2I: - case L2F: - case L2D: - case LRETURN: - expected = BasicValue.LONG_VALUE; - break; - case DNEG: - case D2I: - case D2F: - case D2L: - case DRETURN: - expected = BasicValue.DOUBLE_VALUE; - break; - case GETFIELD: - expected = newValue(Type.getObjectType(((FieldInsnNode) insn).owner)); - break; - case CHECKCAST: - if (!value.isReference()) { - throw new AnalyzerException(insn, - null, - "an object reference", - value); - } - return super.unaryOperation(insn, value); - case ARRAYLENGTH: - if (!isArrayValue(value)) { - throw new AnalyzerException(insn, - null, - "an array reference", - value); - } - return super.unaryOperation(insn, value); - case ARETURN: - case ATHROW: - case INSTANCEOF: - case MONITORENTER: - case MONITOREXIT: - case IFNULL: - case IFNONNULL: - if (!value.isReference()) { - throw new AnalyzerException(insn, - null, - "an object reference", - value); - } - return super.unaryOperation(insn, value); - case PUTSTATIC: - expected = newValue(Type.getType(((FieldInsnNode) insn).desc)); - break; - default: - throw new Error("Internal error."); + case INEG: + case IINC: + case I2F: + case I2L: + case I2D: + case I2B: + case I2C: + case I2S: + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case TABLESWITCH: + case LOOKUPSWITCH: + case IRETURN: + case NEWARRAY: + case ANEWARRAY: + expected = BasicValue.INT_VALUE; + break; + case FNEG: + case F2I: + case F2L: + case F2D: + case FRETURN: + expected = BasicValue.FLOAT_VALUE; + break; + case LNEG: + case L2I: + case L2F: + case L2D: + case LRETURN: + expected = BasicValue.LONG_VALUE; + break; + case DNEG: + case D2I: + case D2F: + case D2L: + case DRETURN: + expected = BasicValue.DOUBLE_VALUE; + break; + case GETFIELD: + expected = newValue(Type + .getObjectType(((FieldInsnNode) insn).owner)); + break; + case CHECKCAST: + if (!value.isReference()) { + throw new AnalyzerException(insn, null, "an object reference", + value); + } + return super.unaryOperation(insn, value); + case ARRAYLENGTH: + if (!isArrayValue(value)) { + throw new AnalyzerException(insn, null, "an array reference", + value); + } + return super.unaryOperation(insn, value); + case ARETURN: + case ATHROW: + case INSTANCEOF: + case MONITORENTER: + case MONITOREXIT: + case IFNULL: + case IFNONNULL: + if (!value.isReference()) { + throw new AnalyzerException(insn, null, "an object reference", + value); + } + return super.unaryOperation(insn, value); + case PUTSTATIC: + expected = newValue(Type.getType(((FieldInsnNode) insn).desc)); + break; + default: + throw new Error("Internal error."); } if (!isSubTypeOf(value, expected)) { throw new AnalyzerException(insn, null, expected, value); @@ -197,125 +185,125 @@ public class BasicVerifier extends BasicInterpreter { } @Override - public BasicValue binaryOperation( - final AbstractInsnNode insn, - final BasicValue value1, - final BasicValue value2) throws AnalyzerException - { + public BasicValue binaryOperation(final AbstractInsnNode insn, + final BasicValue value1, final BasicValue value2) + throws AnalyzerException { BasicValue expected1; BasicValue expected2; switch (insn.getOpcode()) { - case IALOAD: - expected1 = newValue(Type.getType("[I")); - expected2 = BasicValue.INT_VALUE; - break; - case BALOAD: - if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) { - expected1 = newValue(Type.getType("[Z")); - } else { - expected1 = newValue(Type.getType("[B")); - } - expected2 = BasicValue.INT_VALUE; - break; - case CALOAD: - expected1 = newValue(Type.getType("[C")); - expected2 = BasicValue.INT_VALUE; - break; - case SALOAD: - expected1 = newValue(Type.getType("[S")); - expected2 = BasicValue.INT_VALUE; - break; - case LALOAD: - expected1 = newValue(Type.getType("[J")); - expected2 = BasicValue.INT_VALUE; - break; - case FALOAD: - expected1 = newValue(Type.getType("[F")); - expected2 = BasicValue.INT_VALUE; - break; - case DALOAD: - expected1 = newValue(Type.getType("[D")); - expected2 = BasicValue.INT_VALUE; - break; - case AALOAD: - expected1 = newValue(Type.getType("[Ljava/lang/Object;")); - expected2 = BasicValue.INT_VALUE; - break; - case IADD: - case ISUB: - case IMUL: - case IDIV: - case IREM: - case ISHL: - case ISHR: - case IUSHR: - case IAND: - case IOR: - case IXOR: - case IF_ICMPEQ: - case IF_ICMPNE: - case IF_ICMPLT: - case IF_ICMPGE: - case IF_ICMPGT: - case IF_ICMPLE: - expected1 = BasicValue.INT_VALUE; - expected2 = BasicValue.INT_VALUE; - break; - case FADD: - case FSUB: - case FMUL: - case FDIV: - case FREM: - case FCMPL: - case FCMPG: - expected1 = BasicValue.FLOAT_VALUE; - expected2 = BasicValue.FLOAT_VALUE; - break; - case LADD: - case LSUB: - case LMUL: - case LDIV: - case LREM: - case LAND: - case LOR: - case LXOR: - case LCMP: - expected1 = BasicValue.LONG_VALUE; - expected2 = BasicValue.LONG_VALUE; - break; - case LSHL: - case LSHR: - case LUSHR: - expected1 = BasicValue.LONG_VALUE; - expected2 = BasicValue.INT_VALUE; - break; - case DADD: - case DSUB: - case DMUL: - case DDIV: - case DREM: - case DCMPL: - case DCMPG: - expected1 = BasicValue.DOUBLE_VALUE; - expected2 = BasicValue.DOUBLE_VALUE; - break; - case IF_ACMPEQ: - case IF_ACMPNE: - expected1 = BasicValue.REFERENCE_VALUE; - expected2 = BasicValue.REFERENCE_VALUE; - break; - case PUTFIELD: - FieldInsnNode fin = (FieldInsnNode) insn; - expected1 = newValue(Type.getObjectType(fin.owner)); - expected2 = newValue(Type.getType(fin.desc)); - break; - default: - throw new Error("Internal error."); + case IALOAD: + expected1 = newValue(Type.getType("[I")); + expected2 = BasicValue.INT_VALUE; + break; + case BALOAD: + if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) { + expected1 = newValue(Type.getType("[Z")); + } else { + expected1 = newValue(Type.getType("[B")); + } + expected2 = BasicValue.INT_VALUE; + break; + case CALOAD: + expected1 = newValue(Type.getType("[C")); + expected2 = BasicValue.INT_VALUE; + break; + case SALOAD: + expected1 = newValue(Type.getType("[S")); + expected2 = BasicValue.INT_VALUE; + break; + case LALOAD: + expected1 = newValue(Type.getType("[J")); + expected2 = BasicValue.INT_VALUE; + break; + case FALOAD: + expected1 = newValue(Type.getType("[F")); + expected2 = BasicValue.INT_VALUE; + break; + case DALOAD: + expected1 = newValue(Type.getType("[D")); + expected2 = BasicValue.INT_VALUE; + break; + case AALOAD: + expected1 = newValue(Type.getType("[Ljava/lang/Object;")); + expected2 = BasicValue.INT_VALUE; + break; + case IADD: + case ISUB: + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + expected1 = BasicValue.INT_VALUE; + expected2 = BasicValue.INT_VALUE; + break; + case FADD: + case FSUB: + case FMUL: + case FDIV: + case FREM: + case FCMPL: + case FCMPG: + expected1 = BasicValue.FLOAT_VALUE; + expected2 = BasicValue.FLOAT_VALUE; + break; + case LADD: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LAND: + case LOR: + case LXOR: + case LCMP: + expected1 = BasicValue.LONG_VALUE; + expected2 = BasicValue.LONG_VALUE; + break; + case LSHL: + case LSHR: + case LUSHR: + expected1 = BasicValue.LONG_VALUE; + expected2 = BasicValue.INT_VALUE; + break; + case DADD: + case DSUB: + case DMUL: + case DDIV: + case DREM: + case DCMPL: + case DCMPG: + expected1 = BasicValue.DOUBLE_VALUE; + expected2 = BasicValue.DOUBLE_VALUE; + break; + case IF_ACMPEQ: + case IF_ACMPNE: + expected1 = BasicValue.REFERENCE_VALUE; + expected2 = BasicValue.REFERENCE_VALUE; + break; + case PUTFIELD: + FieldInsnNode fin = (FieldInsnNode) insn; + expected1 = newValue(Type.getObjectType(fin.owner)); + expected2 = newValue(Type.getType(fin.desc)); + break; + default: + throw new Error("Internal error."); } if (!isSubTypeOf(value1, expected1)) { - throw new AnalyzerException(insn, "First argument", expected1, value1); + throw new AnalyzerException(insn, "First argument", expected1, + value1); } else if (!isSubTypeOf(value2, expected2)) { - throw new AnalyzerException(insn, "Second argument", expected2, value2); + throw new AnalyzerException(insn, "Second argument", expected2, + value2); } if (insn.getOpcode() == AALOAD) { return getElementValue(value1); @@ -325,79 +313,73 @@ public class BasicVerifier extends BasicInterpreter { } @Override - public BasicValue ternaryOperation( - final AbstractInsnNode insn, - final BasicValue value1, - final BasicValue value2, - final BasicValue value3) throws AnalyzerException - { + public BasicValue ternaryOperation(final AbstractInsnNode insn, + final BasicValue value1, final BasicValue value2, + final BasicValue value3) throws AnalyzerException { BasicValue expected1; BasicValue expected3; switch (insn.getOpcode()) { - case IASTORE: - expected1 = newValue(Type.getType("[I")); - expected3 = BasicValue.INT_VALUE; - break; - case BASTORE: - if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) { - expected1 = newValue(Type.getType("[Z")); - } else { - expected1 = newValue(Type.getType("[B")); - } - expected3 = BasicValue.INT_VALUE; - break; - case CASTORE: - expected1 = newValue(Type.getType("[C")); - expected3 = BasicValue.INT_VALUE; - break; - case SASTORE: - expected1 = newValue(Type.getType("[S")); - expected3 = BasicValue.INT_VALUE; - break; - case LASTORE: - expected1 = newValue(Type.getType("[J")); - expected3 = BasicValue.LONG_VALUE; - break; - case FASTORE: - expected1 = newValue(Type.getType("[F")); - expected3 = BasicValue.FLOAT_VALUE; - break; - case DASTORE: - expected1 = newValue(Type.getType("[D")); - expected3 = BasicValue.DOUBLE_VALUE; - break; - case AASTORE: - expected1 = value1; - expected3 = BasicValue.REFERENCE_VALUE; - break; - default: - throw new Error("Internal error."); + case IASTORE: + expected1 = newValue(Type.getType("[I")); + expected3 = BasicValue.INT_VALUE; + break; + case BASTORE: + if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) { + expected1 = newValue(Type.getType("[Z")); + } else { + expected1 = newValue(Type.getType("[B")); + } + expected3 = BasicValue.INT_VALUE; + break; + case CASTORE: + expected1 = newValue(Type.getType("[C")); + expected3 = BasicValue.INT_VALUE; + break; + case SASTORE: + expected1 = newValue(Type.getType("[S")); + expected3 = BasicValue.INT_VALUE; + break; + case LASTORE: + expected1 = newValue(Type.getType("[J")); + expected3 = BasicValue.LONG_VALUE; + break; + case FASTORE: + expected1 = newValue(Type.getType("[F")); + expected3 = BasicValue.FLOAT_VALUE; + break; + case DASTORE: + expected1 = newValue(Type.getType("[D")); + expected3 = BasicValue.DOUBLE_VALUE; + break; + case AASTORE: + expected1 = value1; + expected3 = BasicValue.REFERENCE_VALUE; + break; + default: + throw new Error("Internal error."); } if (!isSubTypeOf(value1, expected1)) { - throw new AnalyzerException(insn, "First argument", "a " + expected1 - + " array reference", value1); + throw new AnalyzerException(insn, "First argument", "a " + + expected1 + " array reference", value1); } else if (!BasicValue.INT_VALUE.equals(value2)) { throw new AnalyzerException(insn, "Second argument", - BasicValue.INT_VALUE, - value2); + BasicValue.INT_VALUE, value2); } else if (!isSubTypeOf(value3, expected3)) { - throw new AnalyzerException(insn, "Third argument", expected3, value3); + throw new AnalyzerException(insn, "Third argument", expected3, + value3); } return null; } @Override - public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) - throws AnalyzerException - { + public BasicValue naryOperation(final AbstractInsnNode insn, + final List<? extends BasicValue> values) throws AnalyzerException { int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { for (int i = 0; i < values.size(); ++i) { if (!BasicValue.INT_VALUE.equals(values.get(i))) { - throw new AnalyzerException(insn, - null, - BasicValue.INT_VALUE, - values.get(i)); + throw new AnalyzerException(insn, null, + BasicValue.INT_VALUE, values.get(i)); } } } else { @@ -407,22 +389,18 @@ public class BasicVerifier extends BasicInterpreter { Type owner = Type.getObjectType(((MethodInsnNode) insn).owner); if (!isSubTypeOf(values.get(i++), newValue(owner))) { throw new AnalyzerException(insn, "Method owner", - newValue(owner), - values.get(0)); + newValue(owner), values.get(0)); } } - String desc = (opcode == INVOKEDYNAMIC)? - ((InvokeDynamicInsnNode) insn).desc: - ((MethodInsnNode) insn).desc; + String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc + : ((MethodInsnNode) insn).desc; Type[] args = Type.getArgumentTypes(desc); while (i < values.size()) { BasicValue expected = newValue(args[j++]); BasicValue encountered = values.get(i++); if (!isSubTypeOf(encountered, expected)) { - throw new AnalyzerException(insn, - "Argument " + j, - expected, - encountered); + throw new AnalyzerException(insn, "Argument " + j, + expected, encountered); } } } @@ -430,16 +408,12 @@ public class BasicVerifier extends BasicInterpreter { } @Override - public void returnOperation( - final AbstractInsnNode insn, - final BasicValue value, - final BasicValue expected) throws AnalyzerException - { + public void returnOperation(final AbstractInsnNode insn, + final BasicValue value, final BasicValue expected) + throws AnalyzerException { if (!isSubTypeOf(value, expected)) { - throw new AnalyzerException(insn, - "Incompatible return type", - expected, - value); + throw new AnalyzerException(insn, "Incompatible return type", + expected, value); } } @@ -448,12 +422,12 @@ public class BasicVerifier extends BasicInterpreter { } protected BasicValue getElementValue(final BasicValue objectArrayValue) - throws AnalyzerException - { + throws AnalyzerException { return BasicValue.REFERENCE_VALUE; } - protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) { + protected boolean isSubTypeOf(final BasicValue value, + final BasicValue expected) { return value.equals(expected); } } diff --git a/src/asm/scala/tools/asm/tree/analysis/Frame.java b/src/asm/scala/tools/asm/tree/analysis/Frame.java index fe19c2c9ae..0d92edc4d6 100644 --- a/src/asm/scala/tools/asm/tree/analysis/Frame.java +++ b/src/asm/scala/tools/asm/tree/analysis/Frame.java @@ -44,10 +44,11 @@ import scala.tools.asm.tree.VarInsnNode; /** * A symbolic execution stack frame. A stack frame contains a set of local * variable slots, and an operand stack. Warning: long and double values are - * represented by <i>two</i> slots in local variables, and by <i>one</i> slot - * in the operand stack. + * represented by <i>two</i> slots in local variables, and by <i>one</i> slot in + * the operand stack. * - * @param <V> type of the Value used for the analysis. + * @param <V> + * type of the Value used for the analysis. * * @author Eric Bruneton */ @@ -77,8 +78,10 @@ public class Frame<V extends Value> { /** * Constructs a new frame with the given size. * - * @param nLocals the maximum number of local variables of the frame. - * @param nStack the maximum stack size of the frame. + * @param nLocals + * the maximum number of local variables of the frame. + * @param nStack + * the maximum stack size of the frame. */ public Frame(final int nLocals, final int nStack) { this.values = (V[]) new Value[nLocals + nStack]; @@ -88,7 +91,8 @@ public class Frame<V extends Value> { /** * Constructs a new frame that is identical to the given frame. * - * @param src a frame. + * @param src + * a frame. */ public Frame(final Frame<? extends V> src) { this(src.locals, src.values.length - src.locals); @@ -98,7 +102,8 @@ public class Frame<V extends Value> { /** * Copies the state of the given frame into this frame. * - * @param src a frame. + * @param src + * a frame. * @return this frame. */ public Frame<V> init(final Frame<? extends V> src) { @@ -111,8 +116,9 @@ public class Frame<V extends Value> { /** * Sets the expected return type of the analyzed method. * - * @param v the expected return type of the analyzed method, or - * <tt>null</tt> if the method returns void. + * @param v + * the expected return type of the analyzed method, or + * <tt>null</tt> if the method returns void. */ public void setReturn(final V v) { returnValue = v; @@ -130,13 +136,16 @@ public class Frame<V extends Value> { /** * Returns the value of the given local variable. * - * @param i a local variable index. + * @param i + * a local variable index. * @return the value of the given local variable. - * @throws IndexOutOfBoundsException if the variable does not exist. + * @throws IndexOutOfBoundsException + * if the variable does not exist. */ public V getLocal(final int i) throws IndexOutOfBoundsException { if (i >= locals) { - throw new IndexOutOfBoundsException("Trying to access an inexistant local variable"); + throw new IndexOutOfBoundsException( + "Trying to access an inexistant local variable"); } return values[i]; } @@ -144,15 +153,18 @@ public class Frame<V extends Value> { /** * Sets the value of the given local variable. * - * @param i a local variable index. - * @param value the new value of this local variable. - * @throws IndexOutOfBoundsException if the variable does not exist. + * @param i + * a local variable index. + * @param value + * the new value of this local variable. + * @throws IndexOutOfBoundsException + * if the variable does not exist. */ public void setLocal(final int i, final V value) - throws IndexOutOfBoundsException - { + throws IndexOutOfBoundsException { if (i >= locals) { - throw new IndexOutOfBoundsException("Trying to access an inexistant local variable "+i); + throw new IndexOutOfBoundsException( + "Trying to access an inexistant local variable " + i); } values[i] = value; } @@ -170,10 +182,11 @@ public class Frame<V extends Value> { /** * Returns the value of the given operand stack slot. * - * @param i the index of an operand stack slot. + * @param i + * the index of an operand stack slot. * @return the value of the given operand stack slot. - * @throws IndexOutOfBoundsException if the operand stack slot does not - * exist. + * @throws IndexOutOfBoundsException + * if the operand stack slot does not exist. */ public V getStack(final int i) throws IndexOutOfBoundsException { return values[i + locals]; @@ -190,11 +203,13 @@ public class Frame<V extends Value> { * Pops a value from the operand stack of this frame. * * @return the value that has been popped from the stack. - * @throws IndexOutOfBoundsException if the operand stack is empty. + * @throws IndexOutOfBoundsException + * if the operand stack is empty. */ public V pop() throws IndexOutOfBoundsException { if (top == 0) { - throw new IndexOutOfBoundsException("Cannot pop operand off an empty stack."); + throw new IndexOutOfBoundsException( + "Cannot pop operand off an empty stack."); } return values[--top + locals]; } @@ -202,466 +217,469 @@ public class Frame<V extends Value> { /** * Pushes a value into the operand stack of this frame. * - * @param value the value that must be pushed into the stack. - * @throws IndexOutOfBoundsException if the operand stack is full. + * @param value + * the value that must be pushed into the stack. + * @throws IndexOutOfBoundsException + * if the operand stack is full. */ public void push(final V value) throws IndexOutOfBoundsException { if (top + locals >= values.length) { - throw new IndexOutOfBoundsException("Insufficient maximum stack size."); + throw new IndexOutOfBoundsException( + "Insufficient maximum stack size."); } values[top++ + locals] = value; } - public void execute( - final AbstractInsnNode insn, - final Interpreter<V> interpreter) throws AnalyzerException - { + public void execute(final AbstractInsnNode insn, + final Interpreter<V> interpreter) throws AnalyzerException { V value1, value2, value3, value4; List<V> values; int var; switch (insn.getOpcode()) { - case Opcodes.NOP: - break; - case Opcodes.ACONST_NULL: - case Opcodes.ICONST_M1: - case Opcodes.ICONST_0: - case Opcodes.ICONST_1: - case Opcodes.ICONST_2: - case Opcodes.ICONST_3: - case Opcodes.ICONST_4: - case Opcodes.ICONST_5: - case Opcodes.LCONST_0: - case Opcodes.LCONST_1: - case Opcodes.FCONST_0: - case Opcodes.FCONST_1: - case Opcodes.FCONST_2: - case Opcodes.DCONST_0: - case Opcodes.DCONST_1: - case Opcodes.BIPUSH: - case Opcodes.SIPUSH: - case Opcodes.LDC: - push(interpreter.newOperation(insn)); - break; - case Opcodes.ILOAD: - case Opcodes.LLOAD: - case Opcodes.FLOAD: - case Opcodes.DLOAD: - case Opcodes.ALOAD: - push(interpreter.copyOperation(insn, - getLocal(((VarInsnNode) insn).var))); - break; - case Opcodes.IALOAD: - case Opcodes.LALOAD: - case Opcodes.FALOAD: - case Opcodes.DALOAD: - case Opcodes.AALOAD: - case Opcodes.BALOAD: - case Opcodes.CALOAD: - case Opcodes.SALOAD: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.ISTORE: - case Opcodes.LSTORE: - case Opcodes.FSTORE: - case Opcodes.DSTORE: - case Opcodes.ASTORE: - value1 = interpreter.copyOperation(insn, pop()); - var = ((VarInsnNode) insn).var; - setLocal(var, value1); - if (value1.getSize() == 2) { - setLocal(var + 1, interpreter.newValue(null)); + case Opcodes.NOP: + break; + case Opcodes.ACONST_NULL: + case Opcodes.ICONST_M1: + case Opcodes.ICONST_0: + case Opcodes.ICONST_1: + case Opcodes.ICONST_2: + case Opcodes.ICONST_3: + case Opcodes.ICONST_4: + case Opcodes.ICONST_5: + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + case Opcodes.BIPUSH: + case Opcodes.SIPUSH: + case Opcodes.LDC: + push(interpreter.newOperation(insn)); + break; + case Opcodes.ILOAD: + case Opcodes.LLOAD: + case Opcodes.FLOAD: + case Opcodes.DLOAD: + case Opcodes.ALOAD: + push(interpreter.copyOperation(insn, + getLocal(((VarInsnNode) insn).var))); + break; + case Opcodes.IALOAD: + case Opcodes.LALOAD: + case Opcodes.FALOAD: + case Opcodes.DALOAD: + case Opcodes.AALOAD: + case Opcodes.BALOAD: + case Opcodes.CALOAD: + case Opcodes.SALOAD: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.ISTORE: + case Opcodes.LSTORE: + case Opcodes.FSTORE: + case Opcodes.DSTORE: + case Opcodes.ASTORE: + value1 = interpreter.copyOperation(insn, pop()); + var = ((VarInsnNode) insn).var; + setLocal(var, value1); + if (value1.getSize() == 2) { + setLocal(var + 1, interpreter.newValue(null)); + } + if (var > 0) { + Value local = getLocal(var - 1); + if (local != null && local.getSize() == 2) { + setLocal(var - 1, interpreter.newValue(null)); } - if (var > 0) { - Value local = getLocal(var - 1); - if (local != null && local.getSize() == 2) { - setLocal(var - 1, interpreter.newValue(null)); - } + } + break; + case Opcodes.IASTORE: + case Opcodes.LASTORE: + case Opcodes.FASTORE: + case Opcodes.DASTORE: + case Opcodes.AASTORE: + case Opcodes.BASTORE: + case Opcodes.CASTORE: + case Opcodes.SASTORE: + value3 = pop(); + value2 = pop(); + value1 = pop(); + interpreter.ternaryOperation(insn, value1, value2, value3); + break; + case Opcodes.POP: + if (pop().getSize() == 2) { + throw new AnalyzerException(insn, "Illegal use of POP"); + } + break; + case Opcodes.POP2: + if (pop().getSize() == 1) { + if (pop().getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of POP2"); } - break; - case Opcodes.IASTORE: - case Opcodes.LASTORE: - case Opcodes.FASTORE: - case Opcodes.DASTORE: - case Opcodes.AASTORE: - case Opcodes.BASTORE: - case Opcodes.CASTORE: - case Opcodes.SASTORE: - value3 = pop(); + } + break; + case Opcodes.DUP: + value1 = pop(); + if (value1.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of DUP"); + } + push(value1); + push(interpreter.copyOperation(insn, value1)); + break; + case Opcodes.DUP_X1: + value1 = pop(); + value2 = pop(); + if (value1.getSize() != 1 || value2.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of DUP_X1"); + } + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + case Opcodes.DUP_X2: + value1 = pop(); + if (value1.getSize() == 1) { value2 = pop(); - value1 = pop(); - interpreter.ternaryOperation(insn, value1, value2, value3); - break; - case Opcodes.POP: - if (pop().getSize() == 2) { - throw new AnalyzerException(insn, "Illegal use of POP"); - } - break; - case Opcodes.POP2: - if (pop().getSize() == 1) { - if (pop().getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of POP2"); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; } + } else { + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; } - break; - case Opcodes.DUP: - value1 = pop(); - if (value1.getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of DUP"); + } + throw new AnalyzerException(insn, "Illegal use of DUP_X2"); + case Opcodes.DUP2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + push(value2); + push(value1); + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + break; } + } else { push(value1); push(interpreter.copyOperation(insn, value1)); break; - case Opcodes.DUP_X1: - value1 = pop(); + } + throw new AnalyzerException(insn, "Illegal use of DUP2"); + case Opcodes.DUP2_X1: + value1 = pop(); + if (value1.getSize() == 1) { value2 = pop(); - if (value1.getSize() != 1 || value2.getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of DUP_X1"); - } - push(interpreter.copyOperation(insn, value1)); - push(value2); - push(value1); - break; - case Opcodes.DUP_X2: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } else { + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value2)); push(interpreter.copyOperation(insn, value1)); + push(value3); push(value2); push(value1); break; } } - throw new AnalyzerException(insn, "Illegal use of DUP_X2"); - case Opcodes.DUP2: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - push(value2); - push(value1); - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - break; - } - } else { - push(value1); + } else { + value2 = pop(); + if (value2.getSize() == 1) { push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); break; } - throw new AnalyzerException(insn, "Illegal use of DUP2"); - case Opcodes.DUP2_X1: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { + } + throw new AnalyzerException(insn, "Illegal use of DUP2_X1"); + case Opcodes.DUP2_X2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + value4 = pop(); + if (value4.getSize() == 1) { push(interpreter.copyOperation(insn, value2)); push(interpreter.copyOperation(insn, value1)); + push(value4); push(value3); push(value2); push(value1); break; } - } - } else { - value2 = pop(); - if (value2.getSize() == 1) { + } else { + push(interpreter.copyOperation(insn, value2)); push(interpreter.copyOperation(insn, value1)); + push(value3); push(value2); push(value1); break; } } - throw new AnalyzerException(insn, "Illegal use of DUP2_X1"); - case Opcodes.DUP2_X2: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - value4 = pop(); - if (value4.getSize() == 1) { - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - push(value4); - push(value3); - push(value2); - push(value1); - break; - } - } else { - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } - } else { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } else { + } else { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { push(interpreter.copyOperation(insn, value1)); + push(value3); push(value2); push(value1); break; } - } - throw new AnalyzerException(insn, "Illegal use of DUP2_X2"); - case Opcodes.SWAP: - value2 = pop(); - value1 = pop(); - if (value1.getSize() != 1 || value2.getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of SWAP"); - } - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - break; - case Opcodes.IADD: - case Opcodes.LADD: - case Opcodes.FADD: - case Opcodes.DADD: - case Opcodes.ISUB: - case Opcodes.LSUB: - case Opcodes.FSUB: - case Opcodes.DSUB: - case Opcodes.IMUL: - case Opcodes.LMUL: - case Opcodes.FMUL: - case Opcodes.DMUL: - case Opcodes.IDIV: - case Opcodes.LDIV: - case Opcodes.FDIV: - case Opcodes.DDIV: - case Opcodes.IREM: - case Opcodes.LREM: - case Opcodes.FREM: - case Opcodes.DREM: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.INEG: - case Opcodes.LNEG: - case Opcodes.FNEG: - case Opcodes.DNEG: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.ISHL: - case Opcodes.LSHL: - case Opcodes.ISHR: - case Opcodes.LSHR: - case Opcodes.IUSHR: - case Opcodes.LUSHR: - case Opcodes.IAND: - case Opcodes.LAND: - case Opcodes.IOR: - case Opcodes.LOR: - case Opcodes.IXOR: - case Opcodes.LXOR: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.IINC: - var = ((IincInsnNode) insn).var; - setLocal(var, interpreter.unaryOperation(insn, getLocal(var))); - break; - case Opcodes.I2L: - case Opcodes.I2F: - case Opcodes.I2D: - case Opcodes.L2I: - case Opcodes.L2F: - case Opcodes.L2D: - case Opcodes.F2I: - case Opcodes.F2L: - case Opcodes.F2D: - case Opcodes.D2I: - case Opcodes.D2L: - case Opcodes.D2F: - case Opcodes.I2B: - case Opcodes.I2C: - case Opcodes.I2S: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.LCMP: - case Opcodes.FCMPL: - case Opcodes.FCMPG: - case Opcodes.DCMPL: - case Opcodes.DCMPG: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.IFEQ: - case Opcodes.IFNE: - case Opcodes.IFLT: - case Opcodes.IFGE: - case Opcodes.IFGT: - case Opcodes.IFLE: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.IF_ICMPEQ: - case Opcodes.IF_ICMPNE: - case Opcodes.IF_ICMPLT: - case Opcodes.IF_ICMPGE: - case Opcodes.IF_ICMPGT: - case Opcodes.IF_ICMPLE: - case Opcodes.IF_ACMPEQ: - case Opcodes.IF_ACMPNE: - value2 = pop(); - value1 = pop(); - interpreter.binaryOperation(insn, value1, value2); - break; - case Opcodes.GOTO: - break; - case Opcodes.JSR: - push(interpreter.newOperation(insn)); - break; - case Opcodes.RET: - break; - case Opcodes.TABLESWITCH: - case Opcodes.LOOKUPSWITCH: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.IRETURN: - case Opcodes.LRETURN: - case Opcodes.FRETURN: - case Opcodes.DRETURN: - case Opcodes.ARETURN: - value1 = pop(); - interpreter.unaryOperation(insn, value1); - interpreter.returnOperation(insn, value1, returnValue); - break; - case Opcodes.RETURN: - if (returnValue != null) { - throw new AnalyzerException(insn, "Incompatible return type"); - } - break; - case Opcodes.GETSTATIC: - push(interpreter.newOperation(insn)); - break; - case Opcodes.PUTSTATIC: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.GETFIELD: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.PUTFIELD: - value2 = pop(); - value1 = pop(); - interpreter.binaryOperation(insn, value1, value2); - break; - case Opcodes.INVOKEVIRTUAL: - case Opcodes.INVOKESPECIAL: - case Opcodes.INVOKESTATIC: - case Opcodes.INVOKEINTERFACE: { - values = new ArrayList<V>(); - String desc = ((MethodInsnNode) insn).desc; - for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { - values.add(0, pop()); - } - if (insn.getOpcode() != Opcodes.INVOKESTATIC) { - values.add(0, pop()); - } - if (Type.getReturnType(desc) == Type.VOID_TYPE) { - interpreter.naryOperation(insn, values); } else { - push(interpreter.naryOperation(insn, values)); + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; } - break; } - case Opcodes.INVOKEDYNAMIC: { - values = new ArrayList<V>(); - String desc = ((InvokeDynamicInsnNode) insn).desc; - for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { - values.add(0, pop()); - } - if (Type.getReturnType(desc) == Type.VOID_TYPE) { - interpreter.naryOperation(insn, values); - } else { - push(interpreter.naryOperation(insn, values)); - } - break; + throw new AnalyzerException(insn, "Illegal use of DUP2_X2"); + case Opcodes.SWAP: + value2 = pop(); + value1 = pop(); + if (value1.getSize() != 1 || value2.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of SWAP"); } - case Opcodes.NEW: - push(interpreter.newOperation(insn)); - break; - case Opcodes.NEWARRAY: - case Opcodes.ANEWARRAY: - case Opcodes.ARRAYLENGTH: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.ATHROW: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.CHECKCAST: - case Opcodes.INSTANCEOF: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.MONITORENTER: - case Opcodes.MONITOREXIT: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.MULTIANEWARRAY: - values = new ArrayList<V>(); - for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) { - values.add(0, pop()); - } + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + break; + case Opcodes.IADD: + case Opcodes.LADD: + case Opcodes.FADD: + case Opcodes.DADD: + case Opcodes.ISUB: + case Opcodes.LSUB: + case Opcodes.FSUB: + case Opcodes.DSUB: + case Opcodes.IMUL: + case Opcodes.LMUL: + case Opcodes.FMUL: + case Opcodes.DMUL: + case Opcodes.IDIV: + case Opcodes.LDIV: + case Opcodes.FDIV: + case Opcodes.DDIV: + case Opcodes.IREM: + case Opcodes.LREM: + case Opcodes.FREM: + case Opcodes.DREM: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.INEG: + case Opcodes.LNEG: + case Opcodes.FNEG: + case Opcodes.DNEG: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.ISHL: + case Opcodes.LSHL: + case Opcodes.ISHR: + case Opcodes.LSHR: + case Opcodes.IUSHR: + case Opcodes.LUSHR: + case Opcodes.IAND: + case Opcodes.LAND: + case Opcodes.IOR: + case Opcodes.LOR: + case Opcodes.IXOR: + case Opcodes.LXOR: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.IINC: + var = ((IincInsnNode) insn).var; + setLocal(var, interpreter.unaryOperation(insn, getLocal(var))); + break; + case Opcodes.I2L: + case Opcodes.I2F: + case Opcodes.I2D: + case Opcodes.L2I: + case Opcodes.L2F: + case Opcodes.L2D: + case Opcodes.F2I: + case Opcodes.F2L: + case Opcodes.F2D: + case Opcodes.D2I: + case Opcodes.D2L: + case Opcodes.D2F: + case Opcodes.I2B: + case Opcodes.I2C: + case Opcodes.I2S: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.LCMP: + case Opcodes.FCMPL: + case Opcodes.FCMPG: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.IFEQ: + case Opcodes.IFNE: + case Opcodes.IFLT: + case Opcodes.IFGE: + case Opcodes.IFGT: + case Opcodes.IFLE: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.IF_ICMPEQ: + case Opcodes.IF_ICMPNE: + case Opcodes.IF_ICMPLT: + case Opcodes.IF_ICMPGE: + case Opcodes.IF_ICMPGT: + case Opcodes.IF_ICMPLE: + case Opcodes.IF_ACMPEQ: + case Opcodes.IF_ACMPNE: + value2 = pop(); + value1 = pop(); + interpreter.binaryOperation(insn, value1, value2); + break; + case Opcodes.GOTO: + break; + case Opcodes.JSR: + push(interpreter.newOperation(insn)); + break; + case Opcodes.RET: + break; + case Opcodes.TABLESWITCH: + case Opcodes.LOOKUPSWITCH: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.IRETURN: + case Opcodes.LRETURN: + case Opcodes.FRETURN: + case Opcodes.DRETURN: + case Opcodes.ARETURN: + value1 = pop(); + interpreter.unaryOperation(insn, value1); + interpreter.returnOperation(insn, value1, returnValue); + break; + case Opcodes.RETURN: + if (returnValue != null) { + throw new AnalyzerException(insn, "Incompatible return type"); + } + break; + case Opcodes.GETSTATIC: + push(interpreter.newOperation(insn)); + break; + case Opcodes.PUTSTATIC: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.GETFIELD: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.PUTFIELD: + value2 = pop(); + value1 = pop(); + interpreter.binaryOperation(insn, value1, value2); + break; + case Opcodes.INVOKEVIRTUAL: + case Opcodes.INVOKESPECIAL: + case Opcodes.INVOKESTATIC: + case Opcodes.INVOKEINTERFACE: { + values = new ArrayList<V>(); + String desc = ((MethodInsnNode) insn).desc; + for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { + values.add(0, pop()); + } + if (insn.getOpcode() != Opcodes.INVOKESTATIC) { + values.add(0, pop()); + } + if (Type.getReturnType(desc) == Type.VOID_TYPE) { + interpreter.naryOperation(insn, values); + } else { push(interpreter.naryOperation(insn, values)); - break; - case Opcodes.IFNULL: - case Opcodes.IFNONNULL: - interpreter.unaryOperation(insn, pop()); - break; - default: - throw new RuntimeException("Illegal opcode "+insn.getOpcode()); + } + break; + } + case Opcodes.INVOKEDYNAMIC: { + values = new ArrayList<V>(); + String desc = ((InvokeDynamicInsnNode) insn).desc; + for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { + values.add(0, pop()); + } + if (Type.getReturnType(desc) == Type.VOID_TYPE) { + interpreter.naryOperation(insn, values); + } else { + push(interpreter.naryOperation(insn, values)); + } + break; + } + case Opcodes.NEW: + push(interpreter.newOperation(insn)); + break; + case Opcodes.NEWARRAY: + case Opcodes.ANEWARRAY: + case Opcodes.ARRAYLENGTH: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.ATHROW: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.CHECKCAST: + case Opcodes.INSTANCEOF: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.MONITORENTER: + case Opcodes.MONITOREXIT: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.MULTIANEWARRAY: + values = new ArrayList<V>(); + for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) { + values.add(0, pop()); + } + push(interpreter.naryOperation(insn, values)); + break; + case Opcodes.IFNULL: + case Opcodes.IFNONNULL: + interpreter.unaryOperation(insn, pop()); + break; + default: + throw new RuntimeException("Illegal opcode " + insn.getOpcode()); } } /** * Merges this frame with the given frame. * - * @param frame a frame. - * @param interpreter the interpreter used to merge values. + * @param frame + * a frame. + * @param interpreter + * the interpreter used to merge values. * @return <tt>true</tt> if this frame has been changed as a result of the * merge operation, or <tt>false</tt> otherwise. - * @throws AnalyzerException if the frames have incompatible sizes. + * @throws AnalyzerException + * if the frames have incompatible sizes. */ - public boolean merge(final Frame<? extends V> frame, final Interpreter<V> interpreter) - throws AnalyzerException - { + public boolean merge(final Frame<? extends V> frame, + final Interpreter<V> interpreter) throws AnalyzerException { if (top != frame.top) { throw new AnalyzerException(null, "Incompatible stack heights"); } boolean changes = false; for (int i = 0; i < locals + top; ++i) { V v = interpreter.merge(values[i], frame.values[i]); - if (v != values[i]) { + if (!v.equals(values[i])) { values[i] = v; changes = true; } @@ -672,9 +690,11 @@ public class Frame<V extends Value> { /** * Merges this frame with the given frame (case of a RET instruction). * - * @param frame a frame - * @param access the local variables that have been accessed by the - * subroutine to which the RET instruction corresponds. + * @param frame + * a frame + * @param access + * the local variables that have been accessed by the subroutine + * to which the RET instruction corresponds. * @return <tt>true</tt> if this frame has been changed as a result of the * merge operation, or <tt>false</tt> otherwise. */ diff --git a/src/asm/scala/tools/asm/tree/analysis/Interpreter.java b/src/asm/scala/tools/asm/tree/analysis/Interpreter.java index 930c8f4af8..56f4bedc00 100644 --- a/src/asm/scala/tools/asm/tree/analysis/Interpreter.java +++ b/src/asm/scala/tools/asm/tree/analysis/Interpreter.java @@ -42,7 +42,8 @@ import scala.tools.asm.tree.AbstractInsnNode; * various semantic interpreters, without needing to duplicate the code to * simulate the transfer of values. * - * @param <V> type of the Value used for the analysis. + * @param <V> + * type of the Value used for the analysis. * * @author Eric Bruneton */ @@ -57,12 +58,13 @@ public abstract class Interpreter<V extends Value> { /** * Creates a new value that represents the given type. * - * Called for method parameters (including <code>this</code>), - * exception handler variable and with <code>null</code> type - * for variables reserved by long and double types. + * Called for method parameters (including <code>this</code>), exception + * handler variable and with <code>null</code> type for variables reserved + * by long and double types. * - * @param type a primitive or reference type, or <tt>null</tt> to - * represent an uninitialized value. + * @param type + * a primitive or reference type, or <tt>null</tt> to represent + * an uninitialized value. * @return a value that represents the given type. The size of the returned * value must be equal to the size of the given type. */ @@ -76,9 +78,11 @@ public abstract class Interpreter<V extends Value> { * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW * - * @param insn the bytecode instruction to be interpreted. + * @param insn + * the bytecode instruction to be interpreted. * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException if an error occured during the interpretation. + * @throws AnalyzerException + * if an error occured during the interpretation. */ public abstract V newOperation(AbstractInsnNode insn) throws AnalyzerException; @@ -90,11 +94,14 @@ public abstract class Interpreter<V extends Value> { * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP * - * @param insn the bytecode instruction to be interpreted. - * @param value the value that must be moved by the instruction. + * @param insn + * the bytecode instruction to be interpreted. + * @param value + * the value that must be moved by the instruction. * @return the result of the interpretation of the given instruction. The * returned value must be <tt>equal</tt> to the given value. - * @throws AnalyzerException if an error occured during the interpretation. + * @throws AnalyzerException + * if an error occured during the interpretation. */ public abstract V copyOperation(AbstractInsnNode insn, V value) throws AnalyzerException; @@ -109,10 +116,13 @@ public abstract class Interpreter<V extends Value> { * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST, * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL * - * @param insn the bytecode instruction to be interpreted. - * @param value the argument of the instruction to be interpreted. + * @param insn + * the bytecode instruction to be interpreted. + * @param value + * the argument of the instruction to be interpreted. * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException if an error occured during the interpretation. + * @throws AnalyzerException + * if an error occured during the interpretation. */ public abstract V unaryOperation(AbstractInsnNode insn, V value) throws AnalyzerException; @@ -128,11 +138,15 @@ public abstract class Interpreter<V extends Value> { * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, * IF_ACMPEQ, IF_ACMPNE, PUTFIELD * - * @param insn the bytecode instruction to be interpreted. - * @param value1 the first argument of the instruction to be interpreted. - * @param value2 the second argument of the instruction to be interpreted. + * @param insn + * the bytecode instruction to be interpreted. + * @param value1 + * the first argument of the instruction to be interpreted. + * @param value2 + * the second argument of the instruction to be interpreted. * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException if an error occured during the interpretation. + * @throws AnalyzerException + * if an error occured during the interpretation. */ public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2) throws AnalyzerException; @@ -143,18 +157,20 @@ public abstract class Interpreter<V extends Value> { * * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE * - * @param insn the bytecode instruction to be interpreted. - * @param value1 the first argument of the instruction to be interpreted. - * @param value2 the second argument of the instruction to be interpreted. - * @param value3 the third argument of the instruction to be interpreted. + * @param insn + * the bytecode instruction to be interpreted. + * @param value1 + * the first argument of the instruction to be interpreted. + * @param value2 + * the second argument of the instruction to be interpreted. + * @param value3 + * the third argument of the instruction to be interpreted. * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException if an error occured during the interpretation. + * @throws AnalyzerException + * if an error occured during the interpretation. */ - public abstract V ternaryOperation( - AbstractInsnNode insn, - V value1, - V value2, - V value3) throws AnalyzerException; + public abstract V ternaryOperation(AbstractInsnNode insn, V value1, + V value2, V value3) throws AnalyzerException; /** * Interprets a bytecode instruction with a variable number of arguments. @@ -163,14 +179,16 @@ public abstract class Interpreter<V extends Value> { * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE, * MULTIANEWARRAY and INVOKEDYNAMIC * - * @param insn the bytecode instruction to be interpreted. - * @param values the arguments of the instruction to be interpreted. + * @param insn + * the bytecode instruction to be interpreted. + * @param values + * the arguments of the instruction to be interpreted. * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException if an error occured during the interpretation. + * @throws AnalyzerException + * if an error occured during the interpretation. */ - public abstract V naryOperation( - AbstractInsnNode insn, - List< ? extends V> values) throws AnalyzerException; + public abstract V naryOperation(AbstractInsnNode insn, + List<? extends V> values) throws AnalyzerException; /** * Interprets a bytecode return instruction. This method is called for the @@ -178,15 +196,17 @@ public abstract class Interpreter<V extends Value> { * * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN * - * @param insn the bytecode instruction to be interpreted. - * @param value the argument of the instruction to be interpreted. - * @param expected the expected return type of the analyzed method. - * @throws AnalyzerException if an error occured during the interpretation. + * @param insn + * the bytecode instruction to be interpreted. + * @param value + * the argument of the instruction to be interpreted. + * @param expected + * the expected return type of the analyzed method. + * @throws AnalyzerException + * if an error occured during the interpretation. */ - public abstract void returnOperation( - AbstractInsnNode insn, - V value, - V expected) throws AnalyzerException; + public abstract void returnOperation(AbstractInsnNode insn, V value, + V expected) throws AnalyzerException; /** * Merges two values. The merge operation must return a value that @@ -195,8 +215,10 @@ public abstract class Interpreter<V extends Value> { * values are integer intervals, the merged value must be an interval that * contains the previous ones. Likewise for other types of values). * - * @param v a value. - * @param w another value. + * @param v + * a value. + * @param w + * another value. * @return the merged value. If the merged value is equal to <tt>v</tt>, * this method <i>must</i> return <tt>v</tt>. */ diff --git a/src/asm/scala/tools/asm/tree/analysis/SimpleVerifier.java b/src/asm/scala/tools/asm/tree/analysis/SimpleVerifier.java index c4f515d328..eaecd057ea 100644 --- a/src/asm/scala/tools/asm/tree/analysis/SimpleVerifier.java +++ b/src/asm/scala/tools/asm/tree/analysis/SimpleVerifier.java @@ -79,15 +79,15 @@ public class SimpleVerifier extends BasicVerifier { * Constructs a new {@link SimpleVerifier} to verify a specific class. This * class will not be loaded into the JVM since it may be incorrect. * - * @param currentClass the class that is verified. - * @param currentSuperClass the super class of the class that is verified. - * @param isInterface if the class that is verified is an interface. + * @param currentClass + * the class that is verified. + * @param currentSuperClass + * the super class of the class that is verified. + * @param isInterface + * if the class that is verified is an interface. */ - public SimpleVerifier( - final Type currentClass, - final Type currentSuperClass, - final boolean isInterface) - { + public SimpleVerifier(final Type currentClass, + final Type currentSuperClass, final boolean isInterface) { this(currentClass, currentSuperClass, null, isInterface); } @@ -95,32 +95,25 @@ public class SimpleVerifier extends BasicVerifier { * Constructs a new {@link SimpleVerifier} to verify a specific class. This * class will not be loaded into the JVM since it may be incorrect. * - * @param currentClass the class that is verified. - * @param currentSuperClass the super class of the class that is verified. - * @param currentClassInterfaces the interfaces implemented by the class - * that is verified. - * @param isInterface if the class that is verified is an interface. + * @param currentClass + * the class that is verified. + * @param currentSuperClass + * the super class of the class that is verified. + * @param currentClassInterfaces + * the interfaces implemented by the class that is verified. + * @param isInterface + * if the class that is verified is an interface. */ - public SimpleVerifier( - final Type currentClass, - final Type currentSuperClass, - final List<Type> currentClassInterfaces, - final boolean isInterface) - { - this(ASM4, - currentClass, - currentSuperClass, - currentClassInterfaces, + public SimpleVerifier(final Type currentClass, + final Type currentSuperClass, + final List<Type> currentClassInterfaces, final boolean isInterface) { + this(ASM4, currentClass, currentSuperClass, currentClassInterfaces, isInterface); } - protected SimpleVerifier( - final int api, - final Type currentClass, - final Type currentSuperClass, - final List<Type> currentClassInterfaces, - final boolean isInterface) - { + protected SimpleVerifier(final int api, final Type currentClass, + final Type currentSuperClass, + final List<Type> currentClassInterfaces, final boolean isInterface) { super(api); this.currentClass = currentClass; this.currentSuperClass = currentSuperClass; @@ -133,7 +126,8 @@ public class SimpleVerifier extends BasicVerifier { * classes. This is useful if you are verifying multiple interdependent * classes. * - * @param loader a <code>ClassLoader</code> to use + * @param loader + * a <code>ClassLoader</code> to use */ public void setClassLoader(final ClassLoader loader) { this.loader = loader; @@ -148,11 +142,11 @@ public class SimpleVerifier extends BasicVerifier { boolean isArray = type.getSort() == Type.ARRAY; if (isArray) { switch (type.getElementType().getSort()) { - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - return new BasicValue(type); + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + return new BasicValue(type); } } @@ -181,8 +175,7 @@ public class SimpleVerifier extends BasicVerifier { @Override protected BasicValue getElementValue(final BasicValue objectArrayValue) - throws AnalyzerException - { + throws AnalyzerException { Type arrayType = objectArrayValue.getType(); if (arrayType != null) { if (arrayType.getSort() == Type.ARRAY) { @@ -196,28 +189,28 @@ public class SimpleVerifier extends BasicVerifier { } @Override - protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) { + protected boolean isSubTypeOf(final BasicValue value, + final BasicValue expected) { Type expectedType = expected.getType(); Type type = value.getType(); switch (expectedType.getSort()) { - case Type.INT: - case Type.FLOAT: - case Type.LONG: - case Type.DOUBLE: - return type.equals(expectedType); - case Type.ARRAY: - case Type.OBJECT: - if ("Lnull;".equals(type.getDescriptor())) { - return true; - } else if (type.getSort() == Type.OBJECT - || type.getSort() == Type.ARRAY) - { - return isAssignableFrom(expectedType, type); - } else { - return false; - } - default: - throw new Error("Internal error"); + case Type.INT: + case Type.FLOAT: + case Type.LONG: + case Type.DOUBLE: + return type.equals(expectedType); + case Type.ARRAY: + case Type.OBJECT: + if ("Lnull;".equals(type.getDescriptor())) { + return true; + } else if (type.getSort() == Type.OBJECT + || type.getSort() == Type.ARRAY) { + return isAssignableFrom(expectedType, type); + } else { + return false; + } + default: + throw new Error("Internal error"); } } @@ -227,11 +220,9 @@ public class SimpleVerifier extends BasicVerifier { Type t = v.getType(); Type u = w.getType(); if (t != null - && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) - { + && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) { if (u != null - && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) - { + && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) { if ("Lnull;".equals(t.getDescriptor())) { return w; } @@ -288,7 +279,8 @@ public class SimpleVerifier extends BasicVerifier { return false; } else { if (isInterface) { - return u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY; + return u.getSort() == Type.OBJECT + || u.getSort() == Type.ARRAY; } return isAssignableFrom(t, getSuperClass(u)); } @@ -318,8 +310,7 @@ public class SimpleVerifier extends BasicVerifier { try { if (t.getSort() == Type.ARRAY) { return Class.forName(t.getDescriptor().replace('/', '.'), - false, - loader); + false, loader); } return Class.forName(t.getClassName(), false, loader); } catch (ClassNotFoundException e) { diff --git a/src/asm/scala/tools/asm/tree/analysis/SourceInterpreter.java b/src/asm/scala/tools/asm/tree/analysis/SourceInterpreter.java index 067200b51e..a68086c073 100644 --- a/src/asm/scala/tools/asm/tree/analysis/SourceInterpreter.java +++ b/src/asm/scala/tools/asm/tree/analysis/SourceInterpreter.java @@ -47,8 +47,7 @@ import scala.tools.asm.tree.MethodInsnNode; * @author Eric Bruneton */ public class SourceInterpreter extends Interpreter<SourceValue> implements - Opcodes -{ + Opcodes { public SourceInterpreter() { super(ASM4); @@ -70,125 +69,118 @@ public class SourceInterpreter extends Interpreter<SourceValue> implements public SourceValue newOperation(final AbstractInsnNode insn) { int size; switch (insn.getOpcode()) { - case LCONST_0: - case LCONST_1: - case DCONST_0: - case DCONST_1: - size = 2; - break; - case LDC: - Object cst = ((LdcInsnNode) insn).cst; - size = cst instanceof Long || cst instanceof Double ? 2 : 1; - break; - case GETSTATIC: - size = Type.getType(((FieldInsnNode) insn).desc).getSize(); - break; - default: - size = 1; + case LCONST_0: + case LCONST_1: + case DCONST_0: + case DCONST_1: + size = 2; + break; + case LDC: + Object cst = ((LdcInsnNode) insn).cst; + size = cst instanceof Long || cst instanceof Double ? 2 : 1; + break; + case GETSTATIC: + size = Type.getType(((FieldInsnNode) insn).desc).getSize(); + break; + default: + size = 1; } return new SourceValue(size, insn); } @Override - public SourceValue copyOperation(final AbstractInsnNode insn, final SourceValue value) { + public SourceValue copyOperation(final AbstractInsnNode insn, + final SourceValue value) { return new SourceValue(value.getSize(), insn); } @Override - public SourceValue unaryOperation(final AbstractInsnNode insn, final SourceValue value) - { + public SourceValue unaryOperation(final AbstractInsnNode insn, + final SourceValue value) { int size; switch (insn.getOpcode()) { - case LNEG: - case DNEG: - case I2L: - case I2D: - case L2D: - case F2L: - case F2D: - case D2L: - size = 2; - break; - case GETFIELD: - size = Type.getType(((FieldInsnNode) insn).desc).getSize(); - break; - default: - size = 1; + case LNEG: + case DNEG: + case I2L: + case I2D: + case L2D: + case F2L: + case F2D: + case D2L: + size = 2; + break; + case GETFIELD: + size = Type.getType(((FieldInsnNode) insn).desc).getSize(); + break; + default: + size = 1; } return new SourceValue(size, insn); } @Override - public SourceValue binaryOperation( - final AbstractInsnNode insn, - final SourceValue value1, - final SourceValue value2) - { + public SourceValue binaryOperation(final AbstractInsnNode insn, + final SourceValue value1, final SourceValue value2) { int size; switch (insn.getOpcode()) { - case LALOAD: - case DALOAD: - case LADD: - case DADD: - case LSUB: - case DSUB: - case LMUL: - case DMUL: - case LDIV: - case DDIV: - case LREM: - case DREM: - case LSHL: - case LSHR: - case LUSHR: - case LAND: - case LOR: - case LXOR: - size = 2; - break; - default: - size = 1; + case LALOAD: + case DALOAD: + case LADD: + case DADD: + case LSUB: + case DSUB: + case LMUL: + case DMUL: + case LDIV: + case DDIV: + case LREM: + case DREM: + case LSHL: + case LSHR: + case LUSHR: + case LAND: + case LOR: + case LXOR: + size = 2; + break; + default: + size = 1; } return new SourceValue(size, insn); } @Override - public SourceValue ternaryOperation( - final AbstractInsnNode insn, - final SourceValue value1, - final SourceValue value2, - final SourceValue value3) - { + public SourceValue ternaryOperation(final AbstractInsnNode insn, + final SourceValue value1, final SourceValue value2, + final SourceValue value3) { return new SourceValue(1, insn); } @Override - public SourceValue naryOperation(final AbstractInsnNode insn, final List<? extends SourceValue> values) { + public SourceValue naryOperation(final AbstractInsnNode insn, + final List<? extends SourceValue> values) { int size; int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { size = 1; } else { - String desc = (opcode == INVOKEDYNAMIC)? - ((InvokeDynamicInsnNode) insn).desc: - ((MethodInsnNode) insn).desc; + String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc + : ((MethodInsnNode) insn).desc; size = Type.getReturnType(desc).getSize(); } return new SourceValue(size, insn); } @Override - public void returnOperation( - final AbstractInsnNode insn, - final SourceValue value, - final SourceValue expected) - { + public void returnOperation(final AbstractInsnNode insn, + final SourceValue value, final SourceValue expected) { } @Override public SourceValue merge(final SourceValue d, final SourceValue w) { if (d.insns instanceof SmallSet && w.insns instanceof SmallSet) { - Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns).union((SmallSet<AbstractInsnNode>) w.insns); + Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns) + .union((SmallSet<AbstractInsnNode>) w.insns); if (s == d.insns && d.size == w.size) { return d; } else { diff --git a/src/asm/scala/tools/asm/tree/analysis/SourceValue.java b/src/asm/scala/tools/asm/tree/analysis/SourceValue.java index 57ff212fb2..40d6b68180 100644 --- a/src/asm/scala/tools/asm/tree/analysis/SourceValue.java +++ b/src/asm/scala/tools/asm/tree/analysis/SourceValue.java @@ -48,8 +48,8 @@ public class SourceValue implements Value { /** * The instructions that can produce this value. For example, for the Java - * code below, the instructions that can produce the value of <tt>i</tt> - * at line 5 are the txo ISTORE instructions at line 1 and 3: + * code below, the instructions that can produce the value of <tt>i</tt> at + * line 5 are the txo ISTORE instructions at line 1 and 3: * * <pre> * 1: i = 0; @@ -64,7 +64,7 @@ public class SourceValue implements Value { public final Set<AbstractInsnNode> insns; public SourceValue(final int size) { - this(size, SmallSet.<AbstractInsnNode>emptySet()); + this(size, SmallSet.<AbstractInsnNode> emptySet()); } public SourceValue(final int size, final AbstractInsnNode insn) { @@ -84,7 +84,7 @@ public class SourceValue implements Value { @Override public boolean equals(final Object value) { if (!(value instanceof SourceValue)) { - return false; + return false; } SourceValue v = (SourceValue) value; return size == v.size && insns.equals(v.insns); diff --git a/src/asm/scala/tools/asm/tree/analysis/Subroutine.java b/src/asm/scala/tools/asm/tree/analysis/Subroutine.java index 038880ddcd..d734bbd499 100644 --- a/src/asm/scala/tools/asm/tree/analysis/Subroutine.java +++ b/src/asm/scala/tools/asm/tree/analysis/Subroutine.java @@ -51,11 +51,8 @@ class Subroutine { private Subroutine() { } - Subroutine( - final LabelNode start, - final int maxLocals, - final JumpInsnNode caller) - { + Subroutine(final LabelNode start, final int maxLocals, + final JumpInsnNode caller) { this.start = start; this.access = new boolean[maxLocals]; this.callers = new ArrayList<JumpInsnNode>(); @@ -90,4 +87,4 @@ class Subroutine { } return changes; } -}
\ No newline at end of file +} diff --git a/src/asm/scala/tools/asm/util/ASMifiable.java b/src/asm/scala/tools/asm/util/ASMifiable.java index 6a31dd508f..95cc6e3a74 100644 --- a/src/asm/scala/tools/asm/util/ASMifiable.java +++ b/src/asm/scala/tools/asm/util/ASMifiable.java @@ -34,7 +34,7 @@ import java.util.Map; import scala.tools.asm.Label; /** - * An {@link org.objectweb.asm.Attribute Attribute} that can print the ASM code + * An {@link scala.tools.asm.Attribute Attribute} that can print the ASM code * to create an equivalent attribute. * * @author Eugene Kuleshov @@ -44,10 +44,13 @@ public interface ASMifiable { /** * Prints the ASM code to create an attribute equal to this attribute. * - * @param buf a buffer used for printing Java code. - * @param varName name of the variable in a printed code used to store - * attribute instance. - * @param labelNames map of label instances to their names. + * @param buf + * a buffer used for printing Java code. + * @param varName + * name of the variable in a printed code used to store attribute + * instance. + * @param labelNames + * map of label instances to their names. */ void asmify(StringBuffer buf, String varName, Map<Label, String> labelNames); } diff --git a/src/asm/scala/tools/asm/util/ASMifier.java b/src/asm/scala/tools/asm/util/ASMifier.java index 5967c877d1..7e6b223853 100644 --- a/src/asm/scala/tools/asm/util/ASMifier.java +++ b/src/asm/scala/tools/asm/util/ASMifier.java @@ -91,11 +91,14 @@ public class ASMifier extends Printer { /** * Constructs a new {@link ASMifier}. * - * @param api the ASM API version implemented by this class. Must be one of - * {@link Opcodes#ASM4}. - * @param name the name of the visitor variable in the produced code. - * @param id identifier of the annotation visitor variable in the produced - * code. + * @param api + * the ASM API version implemented by this class. Must be one of + * {@link Opcodes#ASM4}. + * @param name + * the name of the visitor variable in the produced code. + * @param id + * identifier of the annotation visitor variable in the produced + * code. */ protected ASMifier(final int api, final String name, final int id) { super(api); @@ -105,13 +108,15 @@ public class ASMifier extends Printer { /** * Prints the ASM source code to generate the given class to the standard - * output. <p> Usage: ASMifier [-debug] <binary - * class name or class file name> + * output. + * <p> + * Usage: ASMifier [-debug] <binary class name or class file name> * - * @param args the command line arguments. + * @param args + * the command line arguments. * - * @throws Exception if the class cannot be found, or if an IO exception - * occurs. + * @throws Exception + * if the class cannot be found, or if an IO exception occurs. */ public static void main(final String[] args) throws Exception { int i = 0; @@ -129,22 +134,21 @@ public class ASMifier extends Printer { } } if (!ok) { - System.err.println("Prints the ASM code to generate the given class."); + System.err + .println("Prints the ASM code to generate the given class."); System.err.println("Usage: ASMifier [-debug] " + "<fully qualified class name or class file name>"); return; } ClassReader cr; if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1 - || args[i].indexOf('/') > -1) - { + || args[i].indexOf('/') > -1) { cr = new ClassReader(new FileInputStream(args[i])); } else { cr = new ClassReader(args[i]); } - cr.accept(new TraceClassVisitor(null, - new ASMifier(), - new PrintWriter(System.out)), flags); + cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter( + System.out)), flags); } // ------------------------------------------------------------------------ @@ -152,14 +156,9 @@ public class ASMifier extends Printer { // ------------------------------------------------------------------------ @Override - public void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces) - { + public void visit(final int version, final int access, final String name, + final String signature, final String superName, + final String[] interfaces) { String simpleName; int n = name.lastIndexOf('/'); if (n == -1) { @@ -170,8 +169,8 @@ public class ASMifier extends Printer { simpleName = name.substring(n + 1); } text.add("import java.util.*;\n"); - text.add("import org.objectweb.asm.*;\n"); - text.add("import org.objectweb.asm.attrs.*;\n"); + text.add("import scala.tools.asm.*;\n"); + text.add("import scala.tools.asm.attrs.*;\n"); text.add("public class " + simpleName + "Dump implements Opcodes {\n\n"); text.add("public static byte[] dump () throws Exception {\n\n"); text.add("ClassWriter cw = new ClassWriter(0);\n"); @@ -182,30 +181,30 @@ public class ASMifier extends Printer { buf.setLength(0); buf.append("cw.visit("); switch (version) { - case Opcodes.V1_1: - buf.append("V1_1"); - break; - case Opcodes.V1_2: - buf.append("V1_2"); - break; - case Opcodes.V1_3: - buf.append("V1_3"); - break; - case Opcodes.V1_4: - buf.append("V1_4"); - break; - case Opcodes.V1_5: - buf.append("V1_5"); - break; - case Opcodes.V1_6: - buf.append("V1_6"); - break; - case Opcodes.V1_7: - buf.append("V1_7"); - break; - default: - buf.append(version); - break; + case Opcodes.V1_1: + buf.append("V1_1"); + break; + case Opcodes.V1_2: + buf.append("V1_2"); + break; + case Opcodes.V1_3: + buf.append("V1_3"); + break; + case Opcodes.V1_4: + buf.append("V1_4"); + break; + case Opcodes.V1_5: + buf.append("V1_5"); + break; + case Opcodes.V1_6: + buf.append("V1_6"); + break; + case Opcodes.V1_7: + buf.append("V1_7"); + break; + default: + buf.append(version); + break; } buf.append(", "); appendAccess(access | ACCESS_CLASS); @@ -242,11 +241,8 @@ public class ASMifier extends Printer { } @Override - public void visitOuterClass( - final String owner, - final String name, - final String desc) - { + public void visitOuterClass(final String owner, final String name, + final String desc) { buf.setLength(0); buf.append("cw.visitOuterClass("); appendConstant(owner); @@ -259,10 +255,8 @@ public class ASMifier extends Printer { } @Override - public ASMifier visitClassAnnotation( - final String desc, - final boolean visible) - { + public ASMifier visitClassAnnotation(final String desc, + final boolean visible) { return visitAnnotation(desc, visible); } @@ -272,12 +266,8 @@ public class ASMifier extends Printer { } @Override - public void visitInnerClass( - final String name, - final String outerName, - final String innerName, - final int access) - { + public void visitInnerClass(final String name, final String outerName, + final String innerName, final int access) { buf.setLength(0); buf.append("cw.visitInnerClass("); appendConstant(name); @@ -292,13 +282,8 @@ public class ASMifier extends Printer { } @Override - public ASMifier visitField( - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { + public ASMifier visitField(final int access, final String name, + final String desc, final String signature, final Object value) { buf.setLength(0); buf.append("{\n"); buf.append("fv = cw.visitField("); @@ -320,13 +305,8 @@ public class ASMifier extends Printer { } @Override - public ASMifier visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { + public ASMifier visitMethod(final int access, final String name, + final String desc, final String signature, final String[] exceptions) { buf.setLength(0); buf.append("{\n"); buf.append("mv = cw.visitMethod("); @@ -380,11 +360,8 @@ public class ASMifier extends Printer { } @Override - public void visitEnum( - final String name, - final String desc, - final String value) - { + public void visitEnum(final String name, final String desc, + final String value) { buf.setLength(0); buf.append("av").append(id).append(".visitEnum("); appendConstant(buf, name); @@ -397,10 +374,7 @@ public class ASMifier extends Printer { } @Override - public ASMifier visitAnnotation( - final String name, - final String desc) - { + public ASMifier visitAnnotation(final String name, final String desc) { buf.setLength(0); buf.append("{\n"); buf.append("AnnotationVisitor av").append(id + 1).append(" = av"); @@ -443,10 +417,8 @@ public class ASMifier extends Printer { // ------------------------------------------------------------------------ @Override - public ASMifier visitFieldAnnotation( - final String desc, - final boolean visible) - { + public ASMifier visitFieldAnnotation(final String desc, + final boolean visible) { return visitAnnotation(desc, visible); } @@ -469,9 +441,7 @@ public class ASMifier extends Printer { @Override public ASMifier visitAnnotationDefault() { buf.setLength(0); - buf.append("{\n") - .append("av0 = ") - .append(name) + buf.append("{\n").append("av0 = ").append(name) .append(".visitAnnotationDefault();\n"); text.add(buf.toString()); ASMifier a = createASMifier("av", 0); @@ -481,23 +451,17 @@ public class ASMifier extends Printer { } @Override - public ASMifier visitMethodAnnotation( - final String desc, - final boolean visible) - { + public ASMifier visitMethodAnnotation(final String desc, + final boolean visible) { return visitAnnotation(desc, visible); } @Override - public ASMifier visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) - { + public ASMifier visitParameterAnnotation(final int parameter, + final String desc, final boolean visible) { buf.setLength(0); - buf.append("{\n") - .append("av0 = ").append(name).append(".visitParameterAnnotation(") - .append(parameter) + buf.append("{\n").append("av0 = ").append(name) + .append(".visitParameterAnnotation(").append(parameter) .append(", "); appendConstant(desc); buf.append(", ").append(visible).append(");\n"); @@ -519,52 +483,47 @@ public class ASMifier extends Printer { } @Override - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) - { + public void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack) { buf.setLength(0); switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - declareFrameTypes(nLocal, local); - declareFrameTypes(nStack, stack); - if (type == Opcodes.F_NEW) { - buf.append(name).append(".visitFrame(Opcodes.F_NEW, "); - } else { - buf.append(name).append(".visitFrame(Opcodes.F_FULL, "); - } - buf.append(nLocal).append(", new Object[] {"); - appendFrameTypes(nLocal, local); - buf.append("}, ").append(nStack).append(", new Object[] {"); - appendFrameTypes(nStack, stack); - buf.append('}'); - break; - case Opcodes.F_APPEND: - declareFrameTypes(nLocal, local); - buf.append(name).append(".visitFrame(Opcodes.F_APPEND,") - .append(nLocal) - .append(", new Object[] {"); - appendFrameTypes(nLocal, local); - buf.append("}, 0, null"); - break; - case Opcodes.F_CHOP: - buf.append(name).append(".visitFrame(Opcodes.F_CHOP,") - .append(nLocal) - .append(", null, 0, null"); - break; - case Opcodes.F_SAME: - buf.append(name).append(".visitFrame(Opcodes.F_SAME, 0, null, 0, null"); - break; - case Opcodes.F_SAME1: - declareFrameTypes(1, stack); - buf.append(name).append(".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"); - appendFrameTypes(1, stack); - buf.append('}'); - break; + case Opcodes.F_NEW: + case Opcodes.F_FULL: + declareFrameTypes(nLocal, local); + declareFrameTypes(nStack, stack); + if (type == Opcodes.F_NEW) { + buf.append(name).append(".visitFrame(Opcodes.F_NEW, "); + } else { + buf.append(name).append(".visitFrame(Opcodes.F_FULL, "); + } + buf.append(nLocal).append(", new Object[] {"); + appendFrameTypes(nLocal, local); + buf.append("}, ").append(nStack).append(", new Object[] {"); + appendFrameTypes(nStack, stack); + buf.append('}'); + break; + case Opcodes.F_APPEND: + declareFrameTypes(nLocal, local); + buf.append(name).append(".visitFrame(Opcodes.F_APPEND,") + .append(nLocal).append(", new Object[] {"); + appendFrameTypes(nLocal, local); + buf.append("}, 0, null"); + break; + case Opcodes.F_CHOP: + buf.append(name).append(".visitFrame(Opcodes.F_CHOP,") + .append(nLocal).append(", null, 0, null"); + break; + case Opcodes.F_SAME: + buf.append(name).append( + ".visitFrame(Opcodes.F_SAME, 0, null, 0, null"); + break; + case Opcodes.F_SAME1: + declareFrameTypes(1, stack); + buf.append(name).append( + ".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"); + appendFrameTypes(1, stack); + buf.append('}'); + break; } buf.append(");\n"); text.add(buf.toString()); @@ -573,7 +532,8 @@ public class ASMifier extends Printer { @Override public void visitInsn(final int opcode) { buf.setLength(0); - buf.append(name).append(".visitInsn(").append(OPCODES[opcode]).append(");\n"); + buf.append(name).append(".visitInsn(").append(OPCODES[opcode]) + .append(");\n"); text.add(buf.toString()); } @@ -584,43 +544,35 @@ public class ASMifier extends Printer { .append(".visitIntInsn(") .append(OPCODES[opcode]) .append(", ") - .append(opcode == Opcodes.NEWARRAY - ? TYPES[operand] - : Integer.toString(operand)) - .append(");\n"); + .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer + .toString(operand)).append(");\n"); text.add(buf.toString()); } @Override public void visitVarInsn(final int opcode, final int var) { buf.setLength(0); - buf.append(name) - .append(".visitVarInsn(") - .append(OPCODES[opcode]) - .append(", ") - .append(var) - .append(");\n"); + buf.append(name).append(".visitVarInsn(").append(OPCODES[opcode]) + .append(", ").append(var).append(");\n"); text.add(buf.toString()); } @Override public void visitTypeInsn(final int opcode, final String type) { buf.setLength(0); - buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode]).append(", "); + buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode]) + .append(", "); appendConstant(type); buf.append(");\n"); text.add(buf.toString()); } @Override - public void visitFieldInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc) { buf.setLength(0); - buf.append(this.name).append(".visitFieldInsn(").append(OPCODES[opcode]).append(", "); + buf.append(this.name).append(".visitFieldInsn(") + .append(OPCODES[opcode]).append(", "); appendConstant(owner); buf.append(", "); appendConstant(name); @@ -631,14 +583,11 @@ public class ASMifier extends Printer { } @Override - public void visitMethodInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { buf.setLength(0); - buf.append(this.name).append(".visitMethodInsn(").append(OPCODES[opcode]).append(", "); + buf.append(this.name).append(".visitMethodInsn(") + .append(OPCODES[opcode]).append(", "); appendConstant(owner); buf.append(", "); appendConstant(name); @@ -649,12 +598,8 @@ public class ASMifier extends Printer { } @Override - public void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs) - { + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { buf.setLength(0); buf.append(this.name).append(".visitInvokeDynamicInsn("); appendConstant(name); @@ -677,7 +622,8 @@ public class ASMifier extends Printer { public void visitJumpInsn(final int opcode, final Label label) { buf.setLength(0); declareLabel(label); - buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode]).append(", "); + buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode]) + .append(", "); appendLabel(label); buf.append(");\n"); text.add(buf.toString()); @@ -705,34 +651,22 @@ public class ASMifier extends Printer { @Override public void visitIincInsn(final int var, final int increment) { buf.setLength(0); - buf.append(name) - .append(".visitIincInsn(") - .append(var) - .append(", ") - .append(increment) - .append(");\n"); + buf.append(name).append(".visitIincInsn(").append(var).append(", ") + .append(increment).append(");\n"); text.add(buf.toString()); } @Override - public void visitTableSwitchInsn( - final int min, - final int max, - final Label dflt, - final Label... labels) - { + public void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels) { buf.setLength(0); for (int i = 0; i < labels.length; ++i) { declareLabel(labels[i]); } declareLabel(dflt); - buf.append(name) - .append(".visitTableSwitchInsn(") - .append(min) - .append(", ") - .append(max) - .append(", "); + buf.append(name).append(".visitTableSwitchInsn(").append(min) + .append(", ").append(max).append(", "); appendLabel(dflt); buf.append(", new Label[] {"); for (int i = 0; i < labels.length; ++i) { @@ -744,11 +678,8 @@ public class ASMifier extends Printer { } @Override - public void visitLookupSwitchInsn( - final Label dflt, - final int[] keys, - final Label[] labels) - { + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, + final Label[] labels) { buf.setLength(0); for (int i = 0; i < labels.length; ++i) { declareLabel(labels[i]); @@ -780,12 +711,8 @@ public class ASMifier extends Printer { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type) { buf.setLength(0); declareLabel(start); declareLabel(end); @@ -803,14 +730,9 @@ public class ASMifier extends Printer { } @Override - public void visitLocalVariable( - final String name, - final String desc, - final String signature, - final Label start, - final Label end, - final int index) - { + public void visitLocalVariable(final String name, final String desc, + final String signature, final Label start, final Label end, + final int index) { buf.setLength(0); buf.append(this.name).append(".visitLocalVariable("); appendConstant(name); @@ -838,12 +760,8 @@ public class ASMifier extends Printer { @Override public void visitMaxs(final int maxStack, final int maxLocals) { buf.setLength(0); - buf.append(name) - .append(".visitMaxs(") - .append(maxStack) - .append(", ") - .append(maxLocals) - .append(");\n"); + buf.append(name).append(".visitMaxs(").append(maxStack).append(", ") + .append(maxLocals).append(");\n"); text.add(buf.toString()); } @@ -858,14 +776,9 @@ public class ASMifier extends Printer { // Common methods // ------------------------------------------------------------------------ - public ASMifier visitAnnotation( - final String desc, - final boolean visible) - { + public ASMifier visitAnnotation(final String desc, final boolean visible) { buf.setLength(0); - buf.append("{\n") - .append("av0 = ") - .append(name) + buf.append("{\n").append("av0 = ").append(name) .append(".visitAnnotation("); appendConstant(desc); buf.append(", ").append(visible).append(");\n"); @@ -895,15 +808,16 @@ public class ASMifier extends Printer { // Utility methods // ------------------------------------------------------------------------ - protected ASMifier createASMifier(final String name, final int id) { + protected ASMifier createASMifier(final String name, final int id) { return new ASMifier(Opcodes.ASM4, name, id); } /** - * Appends a string representation of the given access modifiers to {@link - * #buf buf}. + * Appends a string representation of the given access modifiers to + * {@link #buf buf}. * - * @param access some access modifiers. + * @param access + * some access modifiers. */ void appendAccess(final int access) { boolean first = true; @@ -945,8 +859,7 @@ public class ASMifier extends Printer { first = false; } if ((access & Opcodes.ACC_VOLATILE) != 0 - && (access & ACCESS_FIELD) != 0) - { + && (access & ACCESS_FIELD) != 0) { if (!first) { buf.append(" + "); } @@ -954,8 +867,7 @@ public class ASMifier extends Printer { first = false; } if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0 - && (access & ACCESS_FIELD) == 0) - { + && (access & ACCESS_FIELD) == 0) { if (!first) { buf.append(" + "); } @@ -963,8 +875,7 @@ public class ASMifier extends Printer { first = false; } if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0 - && (access & ACCESS_FIELD) == 0) - { + && (access & ACCESS_FIELD) == 0) { if (!first) { buf.append(" + "); } @@ -972,8 +883,7 @@ public class ASMifier extends Printer { first = false; } if ((access & Opcodes.ACC_TRANSIENT) != 0 - && (access & ACCESS_FIELD) != 0) - { + && (access & ACCESS_FIELD) != 0) { if (!first) { buf.append(" + "); } @@ -981,8 +891,7 @@ public class ASMifier extends Printer { first = false; } if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0 - && (access & ACCESS_FIELD) == 0) - { + && (access & ACCESS_FIELD) == 0) { if (!first) { buf.append(" + "); } @@ -991,8 +900,7 @@ public class ASMifier extends Printer { } if ((access & Opcodes.ACC_ENUM) != 0 && ((access & ACCESS_CLASS) != 0 - || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0)) - { + || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0)) { if (!first) { buf.append(" + "); } @@ -1000,8 +908,7 @@ public class ASMifier extends Printer { first = false; } if ((access & Opcodes.ACC_ANNOTATION) != 0 - && ((access & ACCESS_CLASS) != 0 || (access & ACCESS_INNER) != 0)) - { + && ((access & ACCESS_CLASS) != 0 || (access & ACCESS_INNER) != 0)) { if (!first) { buf.append(" + "); } @@ -1052,8 +959,9 @@ public class ASMifier extends Printer { * Appends a string representation of the given constant to the given * buffer. * - * @param cst an {@link Integer}, {@link Float}, {@link Long}, - * {@link Double} or {@link String} object. May be <tt>null</tt>. + * @param cst + * an {@link Integer}, {@link Float}, {@link Long}, + * {@link Double} or {@link String} object. May be <tt>null</tt>. */ protected void appendConstant(final Object cst) { appendConstant(buf, cst); @@ -1063,9 +971,11 @@ public class ASMifier extends Printer { * Appends a string representation of the given constant to the given * buffer. * - * @param buf a string buffer. - * @param cst an {@link Integer}, {@link Float}, {@link Long}, - * {@link Double} or {@link String} object. May be <tt>null</tt>. + * @param buf + * a string buffer. + * @param cst + * an {@link Integer}, {@link Float}, {@link Long}, + * {@link Double} or {@link String} object. May be <tt>null</tt>. */ static void appendConstant(final StringBuffer buf, final Object cst) { if (cst == null) { @@ -1079,14 +989,16 @@ public class ASMifier extends Printer { } else if (cst instanceof Handle) { buf.append("new Handle("); Handle h = (Handle) cst; - buf.append("Opcodes.").append(HANDLE_TAG[h.getTag()]).append(", \""); + buf.append("Opcodes.").append(HANDLE_TAG[h.getTag()]) + .append(", \""); buf.append(h.getOwner()).append("\", \""); buf.append(h.getName()).append("\", \""); buf.append(h.getDesc()).append("\")"); } else if (cst instanceof Byte) { buf.append("new Byte((byte)").append(cst).append(')'); } else if (cst instanceof Boolean) { - buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE" : "Boolean.FALSE"); + buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE" + : "Boolean.FALSE"); } else if (cst instanceof Short) { buf.append("new Short((short)").append(cst).append(')'); } else if (cst instanceof Character) { @@ -1125,8 +1037,7 @@ public class ASMifier extends Printer { char[] v = (char[]) cst; buf.append("new char[] {"); for (int i = 0; i < v.length; i++) { - buf.append(i == 0 ? "" : ",") - .append("(char)") + buf.append(i == 0 ? "" : ",").append("(char)") .append((int) v[i]); } buf.append('}'); @@ -1178,27 +1089,27 @@ public class ASMifier extends Printer { appendConstant(o[i]); } else if (o[i] instanceof Integer) { switch (((Integer) o[i]).intValue()) { - case 0: - buf.append("Opcodes.TOP"); - break; - case 1: - buf.append("Opcodes.INTEGER"); - break; - case 2: - buf.append("Opcodes.FLOAT"); - break; - case 3: - buf.append("Opcodes.DOUBLE"); - break; - case 4: - buf.append("Opcodes.LONG"); - break; - case 5: - buf.append("Opcodes.NULL"); - break; - case 6: - buf.append("Opcodes.UNINITIALIZED_THIS"); - break; + case 0: + buf.append("Opcodes.TOP"); + break; + case 1: + buf.append("Opcodes.INTEGER"); + break; + case 2: + buf.append("Opcodes.FLOAT"); + break; + case 3: + buf.append("Opcodes.DOUBLE"); + break; + case 4: + buf.append("Opcodes.LONG"); + break; + case 5: + buf.append("Opcodes.NULL"); + break; + case 6: + buf.append("Opcodes.UNINITIALIZED_THIS"); + break; } } else { appendLabel((Label) o[i]); @@ -1211,7 +1122,8 @@ public class ASMifier extends Printer { * declaration is of the form "Label lXXX = new Label();". Does nothing if * the given label has already been declared. * - * @param l a label. + * @param l + * a label. */ protected void declareLabel(final Label l) { if (labelNames == null) { @@ -1227,10 +1139,11 @@ public class ASMifier extends Printer { /** * Appends the name of the given label to {@link #buf buf}. The given label - * <i>must</i> already have a name. One way to ensure this is to always - * call {@link #declareLabel declared} before calling this method. + * <i>must</i> already have a name. One way to ensure this is to always call + * {@link #declareLabel declared} before calling this method. * - * @param l a label. + * @param l + * a label. */ protected void appendLabel(final Label l) { buf.append(labelNames.get(l)); diff --git a/src/asm/scala/tools/asm/util/CheckAnnotationAdapter.java b/src/asm/scala/tools/asm/util/CheckAnnotationAdapter.java index 8030c14f2e..f00a8f04a2 100644 --- a/src/asm/scala/tools/asm/util/CheckAnnotationAdapter.java +++ b/src/asm/scala/tools/asm/util/CheckAnnotationAdapter.java @@ -65,8 +65,7 @@ public class CheckAnnotationAdapter extends AnnotationVisitor { || value instanceof byte[] || value instanceof boolean[] || value instanceof char[] || value instanceof short[] || value instanceof int[] || value instanceof long[] - || value instanceof float[] || value instanceof double[])) - { + || value instanceof float[] || value instanceof double[])) { throw new IllegalArgumentException("Invalid annotation value"); } if (value instanceof Type) { @@ -81,11 +80,8 @@ public class CheckAnnotationAdapter extends AnnotationVisitor { } @Override - public void visitEnum( - final String name, - final String desc, - final String value) - { + public void visitEnum(final String name, final String desc, + final String value) { checkEnd(); checkName(name); CheckMethodAdapter.checkDesc(desc, false); @@ -98,15 +94,12 @@ public class CheckAnnotationAdapter extends AnnotationVisitor { } @Override - public AnnotationVisitor visitAnnotation( - final String name, - final String desc) - { + public AnnotationVisitor visitAnnotation(final String name, + final String desc) { checkEnd(); checkName(name); CheckMethodAdapter.checkDesc(desc, false); - return new CheckAnnotationAdapter(av == null - ? null + return new CheckAnnotationAdapter(av == null ? null : av.visitAnnotation(name, desc)); } @@ -114,8 +107,7 @@ public class CheckAnnotationAdapter extends AnnotationVisitor { public AnnotationVisitor visitArray(final String name) { checkEnd(); checkName(name); - return new CheckAnnotationAdapter(av == null - ? null + return new CheckAnnotationAdapter(av == null ? null : av.visitArray(name), false); } @@ -130,13 +122,15 @@ public class CheckAnnotationAdapter extends AnnotationVisitor { private void checkEnd() { if (end) { - throw new IllegalStateException("Cannot call a visit method after visitEnd has been called"); + throw new IllegalStateException( + "Cannot call a visit method after visitEnd has been called"); } } private void checkName(final String name) { if (named && name == null) { - throw new IllegalArgumentException("Annotation value name must not be null"); + throw new IllegalArgumentException( + "Annotation value name must not be null"); } } } diff --git a/src/asm/scala/tools/asm/util/CheckClassAdapter.java b/src/asm/scala/tools/asm/util/CheckClassAdapter.java index a455322531..0bfa143a95 100644 --- a/src/asm/scala/tools/asm/util/CheckClassAdapter.java +++ b/src/asm/scala/tools/asm/util/CheckClassAdapter.java @@ -59,10 +59,10 @@ import scala.tools.asm.tree.analysis.SimpleVerifier; * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i> * of method calls. For example, the invalid sequence * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC, - * "i", "D", null)</tt> - * will <i>not</i> be detected by this class adapter. + * "i", "D", null)</tt> will <i>not</i> be detected by this class adapter. * - * <p><code>CheckClassAdapter</code> can be also used to verify bytecode + * <p> + * <code>CheckClassAdapter</code> can be also used to verify bytecode * transformations in order to make sure transformed bytecode is sane. For * example: * @@ -80,19 +80,20 @@ import scala.tools.asm.tree.analysis.SimpleVerifier; * </pre> * * Above code runs transformed bytecode trough the - * <code>CheckClassAdapter</code>. It won't be exactly the same verification - * as JVM does, but it run data flow analysis for the code of each method and + * <code>CheckClassAdapter</code>. It won't be exactly the same verification as + * JVM does, but it run data flow analysis for the code of each method and * checks that expectations are met for each method instruction. * - * <p>If method bytecode has errors, assertion text will show the erroneous + * <p> + * If method bytecode has errors, assertion text will show the erroneous * instruction number and dump of the failed method with information about * locals and stack slot for each instruction. For example (format is - * insnNumber locals : stack): * * <pre> - * org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found . - * at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289) - * at org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135) + * scala.tools.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found . + * at scala.tools.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289) + * at scala.tools.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135) * ... * remove()V * 00000 LinkedBlockingQueue$Itr . . . . . . . . : @@ -114,8 +115,9 @@ import scala.tools.asm.tree.analysis.SimpleVerifier; * initialized. You can also see that at the beginning of the method (code * inserted by the transformation) variable 2 is initialized. * - * <p>Note that when used like that, <code>CheckClassAdapter.verify()</code> - * can trigger additional class loading, because it is using + * <p> + * Note that when used like that, <code>CheckClassAdapter.verify()</code> can + * trigger additional class loading, because it is using * <code>SimpleVerifier</code>. * * @author Eric Bruneton @@ -159,13 +161,15 @@ public class CheckClassAdapter extends ClassVisitor { private boolean checkDataFlow; /** - * Checks a given class. <p> Usage: CheckClassAdapter <binary - * class name or class file name> + * Checks a given class. + * <p> + * Usage: CheckClassAdapter <binary class name or class file name> * - * @param args the command line arguments. + * @param args + * the command line arguments. * - * @throws Exception if the class cannot be found, or if an IO exception - * occurs. + * @throws Exception + * if the class cannot be found, or if an IO exception occurs. */ public static void main(final String[] args) throws Exception { if (args.length != 1) { @@ -187,27 +191,26 @@ public class CheckClassAdapter extends ClassVisitor { /** * Checks a given class. * - * @param cr a <code>ClassReader</code> that contains bytecode for the - * analysis. - * @param loader a <code>ClassLoader</code> which will be used to load - * referenced classes. This is useful if you are verifiying multiple - * interdependent classes. - * @param dump true if bytecode should be printed out not only when errors - * are found. - * @param pw write where results going to be printed + * @param cr + * a <code>ClassReader</code> that contains bytecode for the + * analysis. + * @param loader + * a <code>ClassLoader</code> which will be used to load + * referenced classes. This is useful if you are verifiying + * multiple interdependent classes. + * @param dump + * true if bytecode should be printed out not only when errors + * are found. + * @param pw + * write where results going to be printed */ - public static void verify( - final ClassReader cr, - final ClassLoader loader, - final boolean dump, - final PrintWriter pw) - { + public static void verify(final ClassReader cr, final ClassLoader loader, + final boolean dump, final PrintWriter pw) { ClassNode cn = new ClassNode(); cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG); - Type syperType = cn.superName == null - ? null - : Type.getObjectType(cn.superName); + Type syperType = cn.superName == null ? null : Type + .getObjectType(cn.superName); List<MethodNode> methods = cn.methods; List<Type> interfaces = new ArrayList<Type>(); @@ -217,9 +220,8 @@ public class CheckClassAdapter extends ClassVisitor { for (int i = 0; i < methods.size(); ++i) { MethodNode method = methods.get(i); - SimpleVerifier verifier = new SimpleVerifier(Type.getObjectType(cn.name), - syperType, - interfaces, + SimpleVerifier verifier = new SimpleVerifier( + Type.getObjectType(cn.name), syperType, interfaces, (cn.access & Opcodes.ACC_INTERFACE) != 0); Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier); if (loader != null) { @@ -241,25 +243,22 @@ public class CheckClassAdapter extends ClassVisitor { /** * Checks a given class * - * @param cr a <code>ClassReader</code> that contains bytecode for the - * analysis. - * @param dump true if bytecode should be printed out not only when errors - * are found. - * @param pw write where results going to be printed + * @param cr + * a <code>ClassReader</code> that contains bytecode for the + * analysis. + * @param dump + * true if bytecode should be printed out not only when errors + * are found. + * @param pw + * write where results going to be printed */ - public static void verify( - final ClassReader cr, - final boolean dump, - final PrintWriter pw) - { + public static void verify(final ClassReader cr, final boolean dump, + final PrintWriter pw) { verify(cr, null, dump, pw); } - static void printAnalyzerResult( - MethodNode method, - Analyzer<BasicValue> a, - final PrintWriter pw) - { + static void printAnalyzerResult(MethodNode method, Analyzer<BasicValue> a, + final PrintWriter pw) { Frame<BasicValue>[] frames = a.getFrames(); Textifier t = new Textifier(); TraceMethodVisitor mv = new TraceMethodVisitor(t); @@ -310,7 +309,8 @@ public class CheckClassAdapter extends ClassVisitor { * this constructor</i>. Instead, they must use the * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version. * - * @param cv the class visitor to which this adapter must delegate calls. + * @param cv + * the class visitor to which this adapter must delegate calls. */ public CheckClassAdapter(final ClassVisitor cv) { this(cv, true); @@ -321,33 +321,34 @@ public class CheckClassAdapter extends ClassVisitor { * this constructor</i>. Instead, they must use the * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version. * - * @param cv the class visitor to which this adapter must delegate calls. - * @param checkDataFlow <tt>true</tt> to perform basic data flow checks, or - * <tt>false</tt> to not perform any data flow check (see - * {@link CheckMethodAdapter}). This option requires valid maxLocals - * and maxStack values. + * @param cv + * the class visitor to which this adapter must delegate calls. + * @param checkDataFlow + * <tt>true</tt> to perform basic data flow checks, or + * <tt>false</tt> to not perform any data flow check (see + * {@link CheckMethodAdapter}). This option requires valid + * maxLocals and maxStack values. */ - public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) - { + public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) { this(Opcodes.ASM4, cv, checkDataFlow); } /** * Constructs a new {@link CheckClassAdapter}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param cv the class visitor to which this adapter must delegate calls. - * @param checkDataFlow <tt>true</tt> to perform basic data flow checks, or - * <tt>false</tt> to not perform any data flow check (see - * {@link CheckMethodAdapter}). This option requires valid maxLocals - * and maxStack values. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param cv + * the class visitor to which this adapter must delegate calls. + * @param checkDataFlow + * <tt>true</tt> to perform basic data flow checks, or + * <tt>false</tt> to not perform any data flow check (see + * {@link CheckMethodAdapter}). This option requires valid + * maxLocals and maxStack values. */ - protected CheckClassAdapter( - final int api, - final ClassVisitor cv, - final boolean checkDataFlow) - { + protected CheckClassAdapter(final int api, final ClassVisitor cv, + final boolean checkDataFlow) { super(api, cv); this.labels = new HashMap<Label, Integer>(); this.checkDataFlow = checkDataFlow; @@ -358,14 +359,9 @@ public class CheckClassAdapter extends ClassVisitor { // ------------------------------------------------------------------------ @Override - public void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces) - { + public void visit(final int version, final int access, final String name, + final String signature, final String superName, + final String[] interfaces) { if (start) { throw new IllegalStateException("visit must be called only once"); } @@ -375,24 +371,25 @@ public class CheckClassAdapter extends ClassVisitor { + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM - + Opcodes.ACC_DEPRECATED - + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE if (name == null || !name.endsWith("package-info")) { CheckMethodAdapter.checkInternalName(name, "class name"); } if ("java/lang/Object".equals(name)) { if (superName != null) { - throw new IllegalArgumentException("The super class name of the Object class must be 'null'"); + throw new IllegalArgumentException( + "The super class name of the Object class must be 'null'"); } } else { CheckMethodAdapter.checkInternalName(superName, "super class name"); } if (signature != null) { - CheckMethodAdapter.checkClassSignature(signature); + checkClassSignature(signature); } if ((access & Opcodes.ACC_INTERFACE) != 0) { if (!"java/lang/Object".equals(superName)) { - throw new IllegalArgumentException("The super class name of interfaces must be 'java/lang/Object'"); + throw new IllegalArgumentException( + "The super class name of interfaces must be 'java/lang/Object'"); } } if (interfaces != null) { @@ -409,21 +406,20 @@ public class CheckClassAdapter extends ClassVisitor { public void visitSource(final String file, final String debug) { checkState(); if (source) { - throw new IllegalStateException("visitSource can be called only once."); + throw new IllegalStateException( + "visitSource can be called only once."); } source = true; super.visitSource(file, debug); } @Override - public void visitOuterClass( - final String owner, - final String name, - final String desc) - { + public void visitOuterClass(final String owner, final String name, + final String desc) { checkState(); if (outer) { - throw new IllegalStateException("visitOuterClass can be called only once."); + throw new IllegalStateException( + "visitOuterClass can be called only once."); } outer = true; if (owner == null) { @@ -436,12 +432,8 @@ public class CheckClassAdapter extends ClassVisitor { } @Override - public void visitInnerClass( - final String name, - final String outerName, - final String innerName, - final int access) - { + public void visitInnerClass(final String name, final String outerName, + final String innerName, final int access) { checkState(); CheckMethodAdapter.checkInternalName(name, "class name"); if (outerName != null) { @@ -459,52 +451,44 @@ public class CheckClassAdapter extends ClassVisitor { } @Override - public FieldVisitor visitField( - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { + public FieldVisitor visitField(final int access, final String name, + final String desc, final String signature, final Object value) { checkState(); checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC - + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED - + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE CheckMethodAdapter.checkUnqualifiedName(version, name, "field name"); CheckMethodAdapter.checkDesc(desc, false); if (signature != null) { - CheckMethodAdapter.checkFieldSignature(signature); + checkFieldSignature(signature); } if (value != null) { CheckMethodAdapter.checkConstant(value); } - FieldVisitor av = super.visitField(access, name, desc, signature, value); + FieldVisitor av = super + .visitField(access, name, desc, signature, value); return new CheckFieldAdapter(av); } @Override - public MethodVisitor visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { + public MethodVisitor visitMethod(final int access, final String name, + final String desc, final String signature, final String[] exceptions) { checkState(); checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT - + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED - + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - CheckMethodAdapter.checkMethodIdentifier(version, name, "method name"); + + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + if (!"<init>".equals(name) && !"<clinit>".equals(name)) { + CheckMethodAdapter.checkMethodIdentifier(version, name, + "method name"); + } CheckMethodAdapter.checkMethodDesc(desc); if (signature != null) { - CheckMethodAdapter.checkMethodSignature(signature); + checkMethodSignature(signature); } if (exceptions != null) { for (int i = 0; i < exceptions.length; ++i) { @@ -514,27 +498,19 @@ public class CheckClassAdapter extends ClassVisitor { } CheckMethodAdapter cma; if (checkDataFlow) { - cma = new CheckMethodAdapter(access, - name, - desc, - super.visitMethod(access, name, desc, signature, exceptions), - labels); + cma = new CheckMethodAdapter(access, name, desc, super.visitMethod( + access, name, desc, signature, exceptions), labels); } else { - cma = new CheckMethodAdapter(super.visitMethod(access, - name, - desc, - signature, - exceptions), labels); + cma = new CheckMethodAdapter(super.visitMethod(access, name, desc, + signature, exceptions), labels); } cma.version = version; return cma; } @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { checkState(); CheckMethodAdapter.checkDesc(desc, false); return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible)); @@ -544,7 +520,8 @@ public class CheckClassAdapter extends ClassVisitor { public void visitAttribute(final Attribute attr) { checkState(); if (attr == null) { - throw new IllegalArgumentException("Invalid attribute (must not be null)"); + throw new IllegalArgumentException( + "Invalid attribute (must not be null)"); } super.visitAttribute(attr); } @@ -566,10 +543,12 @@ public class CheckClassAdapter extends ClassVisitor { */ private void checkState() { if (!start) { - throw new IllegalStateException("Cannot visit member before visit has been called."); + throw new IllegalStateException( + "Cannot visit member before visit has been called."); } if (end) { - throw new IllegalStateException("Cannot visit member after visitEnd has been called."); + throw new IllegalStateException( + "Cannot visit member after visitEnd has been called."); } } @@ -578,8 +557,10 @@ public class CheckClassAdapter extends ClassVisitor { * method also checks that mutually incompatible flags are not set * simultaneously. * - * @param access the access flags to be checked - * @param possibleAccess the valid access flags. + * @param access + * the access flags to be checked + * @param possibleAccess + * the valid access flags. */ static void checkAccess(final int access, final int possibleAccess) { if ((access & ~possibleAccess) != 0) { @@ -590,14 +571,336 @@ public class CheckClassAdapter extends ClassVisitor { int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1; int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1; if (pub + pri + pro > 1) { - throw new IllegalArgumentException("public private and protected are mutually exclusive: " - + access); + throw new IllegalArgumentException( + "public private and protected are mutually exclusive: " + + access); } int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1; int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1; if (fin + abs > 1) { - throw new IllegalArgumentException("final and abstract are mutually exclusive: " - + access); + throw new IllegalArgumentException( + "final and abstract are mutually exclusive: " + access); + } + } + + /** + * Checks a class signature. + * + * @param signature + * a string containing the signature that must be checked. + */ + public static void checkClassSignature(final String signature) { + // ClassSignature: + // FormalTypeParameters? ClassTypeSignature ClassTypeSignature* + + int pos = 0; + if (getChar(signature, 0) == '<') { + pos = checkFormalTypeParameters(signature, pos); + } + pos = checkClassTypeSignature(signature, pos); + while (getChar(signature, pos) == 'L') { + pos = checkClassTypeSignature(signature, pos); + } + if (pos != signature.length()) { + throw new IllegalArgumentException(signature + ": error at index " + + pos); + } + } + + /** + * Checks a method signature. + * + * @param signature + * a string containing the signature that must be checked. + */ + public static void checkMethodSignature(final String signature) { + // MethodTypeSignature: + // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) ( + // ^ClassTypeSignature | ^TypeVariableSignature )* + + int pos = 0; + if (getChar(signature, 0) == '<') { + pos = checkFormalTypeParameters(signature, pos); + } + pos = checkChar('(', signature, pos); + while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) { + pos = checkTypeSignature(signature, pos); + } + pos = checkChar(')', signature, pos); + if (getChar(signature, pos) == 'V') { + ++pos; + } else { + pos = checkTypeSignature(signature, pos); + } + while (getChar(signature, pos) == '^') { + ++pos; + if (getChar(signature, pos) == 'L') { + pos = checkClassTypeSignature(signature, pos); + } else { + pos = checkTypeVariableSignature(signature, pos); + } + } + if (pos != signature.length()) { + throw new IllegalArgumentException(signature + ": error at index " + + pos); + } + } + + /** + * Checks a field signature. + * + * @param signature + * a string containing the signature that must be checked. + */ + public static void checkFieldSignature(final String signature) { + int pos = checkFieldTypeSignature(signature, 0); + if (pos != signature.length()) { + throw new IllegalArgumentException(signature + ": error at index " + + pos); + } + } + + /** + * Checks the formal type parameters of a class or method signature. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkFormalTypeParameters(final String signature, int pos) { + // FormalTypeParameters: + // < FormalTypeParameter+ > + + pos = checkChar('<', signature, pos); + pos = checkFormalTypeParameter(signature, pos); + while (getChar(signature, pos) != '>') { + pos = checkFormalTypeParameter(signature, pos); + } + return pos + 1; + } + + /** + * Checks a formal type parameter of a class or method signature. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkFormalTypeParameter(final String signature, int pos) { + // FormalTypeParameter: + // Identifier : FieldTypeSignature? (: FieldTypeSignature)* + + pos = checkIdentifier(signature, pos); + pos = checkChar(':', signature, pos); + if ("L[T".indexOf(getChar(signature, pos)) != -1) { + pos = checkFieldTypeSignature(signature, pos); + } + while (getChar(signature, pos) == ':') { + pos = checkFieldTypeSignature(signature, pos + 1); + } + return pos; + } + + /** + * Checks a field type signature. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkFieldTypeSignature(final String signature, int pos) { + // FieldTypeSignature: + // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature + // + // ArrayTypeSignature: + // [ TypeSignature + + switch (getChar(signature, pos)) { + case 'L': + return checkClassTypeSignature(signature, pos); + case '[': + return checkTypeSignature(signature, pos + 1); + default: + return checkTypeVariableSignature(signature, pos); } } + + /** + * Checks a class type signature. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkClassTypeSignature(final String signature, int pos) { + // ClassTypeSignature: + // L Identifier ( / Identifier )* TypeArguments? ( . Identifier + // TypeArguments? )* ; + + pos = checkChar('L', signature, pos); + pos = checkIdentifier(signature, pos); + while (getChar(signature, pos) == '/') { + pos = checkIdentifier(signature, pos + 1); + } + if (getChar(signature, pos) == '<') { + pos = checkTypeArguments(signature, pos); + } + while (getChar(signature, pos) == '.') { + pos = checkIdentifier(signature, pos + 1); + if (getChar(signature, pos) == '<') { + pos = checkTypeArguments(signature, pos); + } + } + return checkChar(';', signature, pos); + } + + /** + * Checks the type arguments in a class type signature. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkTypeArguments(final String signature, int pos) { + // TypeArguments: + // < TypeArgument+ > + + pos = checkChar('<', signature, pos); + pos = checkTypeArgument(signature, pos); + while (getChar(signature, pos) != '>') { + pos = checkTypeArgument(signature, pos); + } + return pos + 1; + } + + /** + * Checks a type argument in a class type signature. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkTypeArgument(final String signature, int pos) { + // TypeArgument: + // * | ( ( + | - )? FieldTypeSignature ) + + char c = getChar(signature, pos); + if (c == '*') { + return pos + 1; + } else if (c == '+' || c == '-') { + pos++; + } + return checkFieldTypeSignature(signature, pos); + } + + /** + * Checks a type variable signature. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkTypeVariableSignature(final String signature, + int pos) { + // TypeVariableSignature: + // T Identifier ; + + pos = checkChar('T', signature, pos); + pos = checkIdentifier(signature, pos); + return checkChar(';', signature, pos); + } + + /** + * Checks a type signature. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkTypeSignature(final String signature, int pos) { + // TypeSignature: + // Z | C | B | S | I | F | J | D | FieldTypeSignature + + switch (getChar(signature, pos)) { + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + case 'F': + case 'J': + case 'D': + return pos + 1; + default: + return checkFieldTypeSignature(signature, pos); + } + } + + /** + * Checks an identifier. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkIdentifier(final String signature, int pos) { + if (!Character.isJavaIdentifierStart(getChar(signature, pos))) { + throw new IllegalArgumentException(signature + + ": identifier expected at index " + pos); + } + ++pos; + while (Character.isJavaIdentifierPart(getChar(signature, pos))) { + ++pos; + } + return pos; + } + + /** + * Checks a single character. + * + * @param signature + * a string containing the signature that must be checked. + * @param pos + * index of first character to be checked. + * @return the index of the first character after the checked part. + */ + private static int checkChar(final char c, final String signature, int pos) { + if (getChar(signature, pos) == c) { + return pos + 1; + } + throw new IllegalArgumentException(signature + ": '" + c + + "' expected at index " + pos); + } + + /** + * Returns the signature car at the given index. + * + * @param signature + * a signature. + * @param pos + * an index in signature. + * @return the character at the given index, or 0 if there is no such + * character. + */ + private static char getChar(final String signature, int pos) { + return pos < signature.length() ? signature.charAt(pos) : (char) 0; + } } diff --git a/src/asm/scala/tools/asm/util/CheckFieldAdapter.java b/src/asm/scala/tools/asm/util/CheckFieldAdapter.java index bdcbe14b16..4657605936 100644 --- a/src/asm/scala/tools/asm/util/CheckFieldAdapter.java +++ b/src/asm/scala/tools/asm/util/CheckFieldAdapter.java @@ -46,7 +46,8 @@ public class CheckFieldAdapter extends FieldVisitor { * this constructor</i>. Instead, they must use the * {@link #CheckFieldAdapter(int, FieldVisitor)} version. * - * @param fv the field visitor to which this adapter must delegate calls. + * @param fv + * the field visitor to which this adapter must delegate calls. */ public CheckFieldAdapter(final FieldVisitor fv) { this(Opcodes.ASM4, fv); @@ -55,19 +56,19 @@ public class CheckFieldAdapter extends FieldVisitor { /** * Constructs a new {@link CheckFieldAdapter}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param fv the field visitor to which this adapter must delegate calls. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param fv + * the field visitor to which this adapter must delegate calls. */ protected CheckFieldAdapter(final int api, final FieldVisitor fv) { super(api, fv); } @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { checkEnd(); CheckMethodAdapter.checkDesc(desc, false); return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible)); @@ -77,7 +78,8 @@ public class CheckFieldAdapter extends FieldVisitor { public void visitAttribute(final Attribute attr) { checkEnd(); if (attr == null) { - throw new IllegalArgumentException("Invalid attribute (must not be null)"); + throw new IllegalArgumentException( + "Invalid attribute (must not be null)"); } super.visitAttribute(attr); } @@ -91,7 +93,8 @@ public class CheckFieldAdapter extends FieldVisitor { private void checkEnd() { if (end) { - throw new IllegalStateException("Cannot call a visit method after visitEnd has been called"); + throw new IllegalStateException( + "Cannot call a visit method after visitEnd has been called"); } } } diff --git a/src/asm/scala/tools/asm/util/CheckMethodAdapter.java b/src/asm/scala/tools/asm/util/CheckMethodAdapter.java index 7549765421..9da01c9d6e 100644 --- a/src/asm/scala/tools/asm/util/CheckMethodAdapter.java +++ b/src/asm/scala/tools/asm/util/CheckMethodAdapter.java @@ -58,7 +58,7 @@ import scala.tools.asm.tree.analysis.BasicVerifier; * arguments - such as the fact that the given opcode is correct for a given * visit method. This adapter can also perform some basic data flow checks (more * precisely those that can be performed without the full class hierarchy - see - * {@link org.objectweb.asm.tree.analysis.BasicVerifier}). For instance in a + * {@link scala.tools.asm.tree.analysis.BasicVerifier}). For instance in a * method whose signature is <tt>void m ()</tt>, the invalid instruction * IRETURN, or the invalid sequence IADD L2I will be detected if the data flow * checks are enabled. These checks are enabled by using the @@ -75,6 +75,11 @@ public class CheckMethodAdapter extends MethodVisitor { public int version; /** + * The access flags of the method. + */ + private int access; + + /** * <tt>true</tt> if the visitCode method has been called. */ private boolean startCode; @@ -107,6 +112,21 @@ public class CheckMethodAdapter extends MethodVisitor { private Set<Label> usedLabels; /** + * Number of visited frames in expanded form. + */ + private int expandedFrames; + + /** + * Number of visited frames in compressed form. + */ + private int compressedFrames; + + /** + * Number of instructions before the last visited frame. + */ + private int lastFrame = -1; + + /** * The exception handler ranges. Each pair of list element contains the * start and end labels of an exception handler block. */ @@ -352,7 +372,8 @@ public class CheckMethodAdapter extends MethodVisitor { * <i>Subclasses must not use this constructor</i>. Instead, they must use * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version. * - * @param mv the method visitor to which this adapter must delegate calls. + * @param mv + * the method visitor to which this adapter must delegate calls. */ public CheckMethodAdapter(final MethodVisitor mv) { this(mv, new HashMap<Label, Integer>()); @@ -365,13 +386,13 @@ public class CheckMethodAdapter extends MethodVisitor { * <i>Subclasses must not use this constructor</i>. Instead, they must use * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version. * - * @param mv the method visitor to which this adapter must delegate calls. - * @param labels a map of already visited labels (in other methods). + * @param mv + * the method visitor to which this adapter must delegate calls. + * @param labels + * a map of already visited labels (in other methods). */ - public CheckMethodAdapter( - final MethodVisitor mv, - final Map<Label, Integer> labels) - { + public CheckMethodAdapter(final MethodVisitor mv, + final Map<Label, Integer> labels) { this(Opcodes.ASM4, mv, labels); } @@ -380,14 +401,13 @@ public class CheckMethodAdapter extends MethodVisitor { * will not perform any data flow check (see * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}). * - * @param mv the method visitor to which this adapter must delegate calls. - * @param labels a map of already visited labels (in other methods). + * @param mv + * the method visitor to which this adapter must delegate calls. + * @param labels + * a map of already visited labels (in other methods). */ - protected CheckMethodAdapter( - final int api, - final MethodVisitor mv, - final Map<Label, Integer> labels) - { + protected CheckMethodAdapter(final int api, final MethodVisitor mv, + final Map<Label, Integer> labels) { super(api, mv); this.labels = labels; this.usedLabels = new HashSet<Label>(); @@ -400,30 +420,32 @@ public class CheckMethodAdapter extends MethodVisitor { * signature is <tt>void m ()</tt>, the invalid instruction IRETURN, or the * invalid sequence IADD L2I will be detected. * - * @param access the method's access flags. - * @param name the method's name. - * @param desc the method's descriptor (see {@link Type Type}). - * @param cmv the method visitor to which this adapter must delegate calls. - * @param labels a map of already visited labels (in other methods). + * @param access + * the method's access flags. + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param cmv + * the method visitor to which this adapter must delegate calls. + * @param labels + * a map of already visited labels (in other methods). */ - public CheckMethodAdapter( - final int access, - final String name, - final String desc, - final MethodVisitor cmv, - final Map<Label, Integer> labels) - { + public CheckMethodAdapter(final int access, final String name, + final String desc, final MethodVisitor cmv, + final Map<Label, Integer> labels) { this(new MethodNode(access, name, desc, null, null) { @Override public void visitEnd() { - Analyzer<BasicValue> a = new Analyzer<BasicValue>(new BasicVerifier()); + Analyzer<BasicValue> a = new Analyzer<BasicValue>( + new BasicVerifier()); try { a.analyze("dummy", this); } catch (Exception e) { if (e instanceof IndexOutOfBoundsException - && maxLocals == 0 && maxStack == 0) - { - throw new RuntimeException("Data flow checking option requires valid, non zero maxLocals and maxStack values."); + && maxLocals == 0 && maxStack == 0) { + throw new RuntimeException( + "Data flow checking option requires valid, non zero maxLocals and maxStack values."); } e.printStackTrace(); StringWriter sw = new StringWriter(); @@ -435,15 +457,13 @@ public class CheckMethodAdapter extends MethodVisitor { } accept(cmv); } - }, - labels); + }, labels); + this.access = access; } @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { checkEndMethod(); checkDesc(desc, false); return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible)); @@ -456,68 +476,68 @@ public class CheckMethodAdapter extends MethodVisitor { } @Override - public AnnotationVisitor visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) - { + public AnnotationVisitor visitParameterAnnotation(final int parameter, + final String desc, final boolean visible) { checkEndMethod(); checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitParameterAnnotation(parameter, - desc, - visible)); + return new CheckAnnotationAdapter(super.visitParameterAnnotation( + parameter, desc, visible)); } @Override public void visitAttribute(final Attribute attr) { checkEndMethod(); if (attr == null) { - throw new IllegalArgumentException("Invalid attribute (must not be null)"); + throw new IllegalArgumentException( + "Invalid attribute (must not be null)"); } super.visitAttribute(attr); } @Override public void visitCode() { + if ((access & Opcodes.ACC_ABSTRACT) != 0) { + throw new RuntimeException("Abstract methods cannot have code"); + } startCode = true; super.visitCode(); } @Override - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) - { + public void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack) { + if (insnCount == lastFrame) { + throw new IllegalStateException( + "At most one frame can be visited at a given code location."); + } + lastFrame = insnCount; int mLocal; int mStack; switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - mLocal = Integer.MAX_VALUE; - mStack = Integer.MAX_VALUE; - break; + case Opcodes.F_NEW: + case Opcodes.F_FULL: + mLocal = Integer.MAX_VALUE; + mStack = Integer.MAX_VALUE; + break; - case Opcodes.F_SAME: - mLocal = 0; - mStack = 0; - break; + case Opcodes.F_SAME: + mLocal = 0; + mStack = 0; + break; - case Opcodes.F_SAME1: - mLocal = 0; - mStack = 1; - break; + case Opcodes.F_SAME1: + mLocal = 0; + mStack = 1; + break; - case Opcodes.F_APPEND: - case Opcodes.F_CHOP: - mLocal = 3; - mStack = 0; - break; + case Opcodes.F_APPEND: + case Opcodes.F_CHOP: + mLocal = 3; + mStack = 0; + break; - default: - throw new IllegalArgumentException("Invalid frame type " + type); + default: + throw new IllegalArgumentException("Invalid frame type " + type); } if (nLocal > mLocal) { @@ -531,19 +551,29 @@ public class CheckMethodAdapter extends MethodVisitor { if (type != Opcodes.F_CHOP) { if (nLocal > 0 && (local == null || local.length < nLocal)) { - throw new IllegalArgumentException("Array local[] is shorter than nLocal"); + throw new IllegalArgumentException( + "Array local[] is shorter than nLocal"); } for (int i = 0; i < nLocal; ++i) { checkFrameValue(local[i]); } } if (nStack > 0 && (stack == null || stack.length < nStack)) { - throw new IllegalArgumentException("Array stack[] is shorter than nStack"); + throw new IllegalArgumentException( + "Array stack[] is shorter than nStack"); } for (int i = 0; i < nStack; ++i) { checkFrameValue(stack[i]); } - + if (type == Opcodes.F_NEW) { + ++expandedFrames; + } else { + ++compressedFrames; + } + if (expandedFrames > 0 && compressedFrames > 0) { + throw new RuntimeException( + "Expanded and compressed frames must not be mixed."); + } super.visitFrame(type, nLocal, local, nStack, stack); } @@ -562,18 +592,19 @@ public class CheckMethodAdapter extends MethodVisitor { checkEndCode(); checkOpcode(opcode, 1); switch (opcode) { - case Opcodes.BIPUSH: - checkSignedByte(operand, "Invalid operand"); - break; - case Opcodes.SIPUSH: - checkSignedShort(operand, "Invalid operand"); - break; - // case Constants.NEWARRAY: - default: - if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) { - throw new IllegalArgumentException("Invalid operand (must be an array type code T_...): " - + operand); - } + case Opcodes.BIPUSH: + checkSignedByte(operand, "Invalid operand"); + break; + case Opcodes.SIPUSH: + checkSignedShort(operand, "Invalid operand"); + break; + // case Constants.NEWARRAY: + default: + if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) { + throw new IllegalArgumentException( + "Invalid operand (must be an array type code T_...): " + + operand); + } } super.visitIntInsn(opcode, operand); ++insnCount; @@ -596,20 +627,16 @@ public class CheckMethodAdapter extends MethodVisitor { checkOpcode(opcode, 3); checkInternalName(type, "type"); if (opcode == Opcodes.NEW && type.charAt(0) == '[') { - throw new IllegalArgumentException("NEW cannot be used to create arrays: " - + type); + throw new IllegalArgumentException( + "NEW cannot be used to create arrays: " + type); } super.visitTypeInsn(opcode, type); ++insnCount; } @Override - public void visitFieldInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 4); @@ -621,16 +648,14 @@ public class CheckMethodAdapter extends MethodVisitor { } @Override - public void visitMethodInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 5); - checkMethodIdentifier(version, name, "name"); + if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) { + checkMethodIdentifier(version, name, "name"); + } checkInternalName(owner, "owner"); checkMethodDesc(desc); super.visitMethodInsn(opcode, owner, name, desc); @@ -638,19 +663,14 @@ public class CheckMethodAdapter extends MethodVisitor { } @Override - public void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs) - { + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { checkStartCode(); checkEndCode(); checkMethodIdentifier(version, name, "name"); checkMethodDesc(desc); if (bsm.getTag() != Opcodes.H_INVOKESTATIC - && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) - { + && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) { throw new IllegalArgumentException("invalid handle tag " + bsm.getTag()); } @@ -705,12 +725,8 @@ public class CheckMethodAdapter extends MethodVisitor { } @Override - public void visitTableSwitchInsn( - final int min, - final int max, - final Label dflt, - final Label... labels) - { + public void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels) { checkStartCode(); checkEndCode(); if (max < min) { @@ -720,7 +736,8 @@ public class CheckMethodAdapter extends MethodVisitor { checkLabel(dflt, false, "default label"); checkNonDebugLabel(dflt); if (labels == null || labels.length != max - min + 1) { - throw new IllegalArgumentException("There must be max - min + 1 labels"); + throw new IllegalArgumentException( + "There must be max - min + 1 labels"); } for (int i = 0; i < labels.length; ++i) { checkLabel(labels[i], false, "label at index " + i); @@ -734,17 +751,15 @@ public class CheckMethodAdapter extends MethodVisitor { } @Override - public void visitLookupSwitchInsn( - final Label dflt, - final int[] keys, - final Label[] labels) - { + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, + final Label[] labels) { checkEndCode(); checkStartCode(); checkLabel(dflt, false, "default label"); checkNonDebugLabel(dflt); if (keys == null || labels == null || keys.length != labels.length) { - throw new IllegalArgumentException("There must be the same number of keys and labels"); + throw new IllegalArgumentException( + "There must be the same number of keys and labels"); } for (int i = 0; i < labels.length; ++i) { checkLabel(labels[i], false, "label at index " + i); @@ -764,28 +779,26 @@ public class CheckMethodAdapter extends MethodVisitor { checkEndCode(); checkDesc(desc, false); if (desc.charAt(0) != '[') { - throw new IllegalArgumentException("Invalid descriptor (must be an array type descriptor): " - + desc); + throw new IllegalArgumentException( + "Invalid descriptor (must be an array type descriptor): " + + desc); } if (dims < 1) { - throw new IllegalArgumentException("Invalid dimensions (must be greater than 0): " - + dims); + throw new IllegalArgumentException( + "Invalid dimensions (must be greater than 0): " + dims); } if (dims > desc.lastIndexOf('[') + 1) { - throw new IllegalArgumentException("Invalid dimensions (must not be greater than dims(desc)): " - + dims); + throw new IllegalArgumentException( + "Invalid dimensions (must not be greater than dims(desc)): " + + dims); } super.visitMultiANewArrayInsn(desc, dims); ++insnCount; } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type) { checkStartCode(); checkEndCode(); checkLabel(start, false, "start label"); @@ -795,9 +808,9 @@ public class CheckMethodAdapter extends MethodVisitor { checkNonDebugLabel(end); checkNonDebugLabel(handler); if (labels.get(start) != null || labels.get(end) != null - || labels.get(handler) != null) - { - throw new IllegalStateException("Try catch blocks must be visited before their labels"); + || labels.get(handler) != null) { + throw new IllegalStateException( + "Try catch blocks must be visited before their labels"); } if (type != null) { checkInternalName(type, "type"); @@ -808,14 +821,9 @@ public class CheckMethodAdapter extends MethodVisitor { } @Override - public void visitLocalVariable( - final String name, - final String desc, - final String signature, - final Label start, - final Label end, - final int index) - { + public void visitLocalVariable(final String name, final String desc, + final String signature, final Label start, final Label end, + final int index) { checkStartCode(); checkEndCode(); checkUnqualifiedName(version, name, "name"); @@ -826,7 +834,8 @@ public class CheckMethodAdapter extends MethodVisitor { int s = labels.get(start).intValue(); int e = labels.get(end).intValue(); if (e < s) { - throw new IllegalArgumentException("Invalid start and end labels (end must be greater than start)"); + throw new IllegalArgumentException( + "Invalid start and end labels (end must be greater than start)"); } super.visitLocalVariable(name, desc, signature, start, end, index); } @@ -850,14 +859,16 @@ public class CheckMethodAdapter extends MethodVisitor { throw new IllegalStateException("Undefined label used"); } } - for (int i = 0; i < handlers.size(); ) { + for (int i = 0; i < handlers.size();) { Integer start = labels.get(handlers.get(i++)); Integer end = labels.get(handlers.get(i++)); if (start == null || end == null) { - throw new IllegalStateException("Undefined try catch block labels"); + throw new IllegalStateException( + "Undefined try catch block labels"); } if (end.intValue() <= start.intValue()) { - throw new IllegalStateException("Emty try catch block handler range"); + throw new IllegalStateException( + "Emty try catch block handler range"); } } checkUnsignedShort(maxStack, "Invalid max stack"); @@ -879,7 +890,8 @@ public class CheckMethodAdapter extends MethodVisitor { */ void checkStartCode() { if (!startCode) { - throw new IllegalStateException("Cannot visit instructions before visitCode has been called."); + throw new IllegalStateException( + "Cannot visit instructions before visitCode has been called."); } } @@ -888,7 +900,8 @@ public class CheckMethodAdapter extends MethodVisitor { */ void checkEndCode() { if (endCode) { - throw new IllegalStateException("Cannot visit instructions after visitMaxs has been called."); + throw new IllegalStateException( + "Cannot visit instructions after visitMaxs has been called."); } } @@ -897,21 +910,22 @@ public class CheckMethodAdapter extends MethodVisitor { */ void checkEndMethod() { if (endMethod) { - throw new IllegalStateException("Cannot visit elements after visitEnd has been called."); + throw new IllegalStateException( + "Cannot visit elements after visitEnd has been called."); } } /** * Checks a stack frame value. * - * @param value the value to be checked. + * @param value + * the value to be checked. */ void checkFrameValue(final Object value) { if (value == Opcodes.TOP || value == Opcodes.INTEGER || value == Opcodes.FLOAT || value == Opcodes.LONG || value == Opcodes.DOUBLE || value == Opcodes.NULL - || value == Opcodes.UNINITIALIZED_THIS) - { + || value == Opcodes.UNINITIALIZED_THIS) { return; } if (value instanceof String) { @@ -929,8 +943,10 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the type of the given opcode is equal to the given type. * - * @param opcode the opcode to be checked. - * @param type the expected opcode type. + * @param opcode + * the opcode to be checked. + * @param type + * the expected opcode type. */ static void checkOpcode(final int opcode, final int type) { if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) { @@ -941,8 +957,10 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the given value is a signed byte. * - * @param value the value to be checked. - * @param msg an message to be used in case of error. + * @param value + * the value to be checked. + * @param msg + * an message to be used in case of error. */ static void checkSignedByte(final int value, final String msg) { if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { @@ -954,8 +972,10 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the given value is a signed short. * - * @param value the value to be checked. - * @param msg an message to be used in case of error. + * @param value + * the value to be checked. + * @param msg + * an message to be used in case of error. */ static void checkSignedShort(final int value, final String msg) { if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { @@ -967,8 +987,10 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the given value is an unsigned short. * - * @param value the value to be checked. - * @param msg an message to be used in case of error. + * @param value + * the value to be checked. + * @param msg + * an message to be used in case of error. */ static void checkUnsignedShort(final int value, final String msg) { if (value < 0 || value > 65535) { @@ -981,13 +1003,13 @@ public class CheckMethodAdapter extends MethodVisitor { * Checks that the given value is an {@link Integer}, a{@link Float}, a * {@link Long}, a {@link Double} or a {@link String}. * - * @param cst the value to be checked. + * @param cst + * the value to be checked. */ static void checkConstant(final Object cst) { if (!(cst instanceof Integer) && !(cst instanceof Float) && !(cst instanceof Long) && !(cst instanceof Double) - && !(cst instanceof String)) - { + && !(cst instanceof String)) { throw new IllegalArgumentException("Invalid constant: " + cst); } } @@ -999,19 +1021,21 @@ public class CheckMethodAdapter extends MethodVisitor { throw new IllegalArgumentException("Illegal LDC constant value"); } if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) { - throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5"); + throw new IllegalArgumentException( + "ldc of a constant class requires at least version 1.5"); } if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) { - throw new IllegalArgumentException("ldc of a method type requires at least version 1.7"); + throw new IllegalArgumentException( + "ldc of a method type requires at least version 1.7"); } } else if (cst instanceof Handle) { if ((version & 0xFFFF) < Opcodes.V1_7) { - throw new IllegalArgumentException("ldc of a handle requires at least version 1.7"); + throw new IllegalArgumentException( + "ldc of a handle requires at least version 1.7"); } int tag = ((Handle) cst).getTag(); if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) { - throw new IllegalArgumentException("invalid handle tag " - + tag); + throw new IllegalArgumentException("invalid handle tag " + tag); } } else { checkConstant(cst); @@ -1021,15 +1045,15 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the given string is a valid unqualified name. * - * @param version the class version. - * @param name the string to be checked. - * @param msg a message to be used in case of error. + * @param version + * the class version. + * @param name + * the string to be checked. + * @param msg + * a message to be used in case of error. */ - static void checkUnqualifiedName( - int version, - final String name, - final String msg) - { + static void checkUnqualifiedName(int version, final String name, + final String msg) { if ((version & 0xFFFF) < Opcodes.V1_5) { checkIdentifier(name, msg); } else { @@ -1045,8 +1069,10 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the given string is a valid Java identifier. * - * @param name the string to be checked. - * @param msg a message to be used in case of error. + * @param name + * the string to be checked. + * @param msg + * a message to be used in case of error. */ static void checkIdentifier(final String name, final String msg) { checkIdentifier(name, 0, -1, msg); @@ -1055,21 +1081,20 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the given substring is a valid Java identifier. * - * @param name the string to be checked. - * @param start index of the first character of the identifier (inclusive). - * @param end index of the last character of the identifier (exclusive). -1 - * is equivalent to <tt>name.length()</tt> if name is not - * <tt>null</tt>. - * @param msg a message to be used in case of error. + * @param name + * the string to be checked. + * @param start + * index of the first character of the identifier (inclusive). + * @param end + * index of the last character of the identifier (exclusive). -1 + * is equivalent to <tt>name.length()</tt> if name is not + * <tt>null</tt>. + * @param msg + * a message to be used in case of error. */ - static void checkIdentifier( - final String name, - final int start, - final int end, - final String msg) - { - if (name == null || (end == -1 ? name.length() <= start : end <= start)) - { + static void checkIdentifier(final String name, final int start, + final int end, final String msg) { + if (name == null || (end == -1 ? name.length() <= start : end <= start)) { throw new IllegalArgumentException("Invalid " + msg + " (must not be null or empty)"); } @@ -1087,25 +1112,21 @@ public class CheckMethodAdapter extends MethodVisitor { } /** - * Checks that the given string is a valid Java identifier or is equal to - * '<init>' or '<clinit>'. + * Checks that the given string is a valid Java identifier. * - * @param version the class version. - * @param name the string to be checked. - * @param msg a message to be used in case of error. + * @param version + * the class version. + * @param name + * the string to be checked. + * @param msg + * a message to be used in case of error. */ - static void checkMethodIdentifier( - int version, - final String name, - final String msg) - { + static void checkMethodIdentifier(int version, final String name, + final String msg) { if (name == null || name.length() == 0) { throw new IllegalArgumentException("Invalid " + msg + " (must not be null or empty)"); } - if ("<init>".equals(name) || "<clinit>".equals(name)) { - return; - } if ((version & 0xFFFF) >= Opcodes.V1_5) { for (int i = 0; i < name.length(); ++i) { if (".;[/<>".indexOf(name.charAt(i)) != -1) { @@ -1116,17 +1137,19 @@ public class CheckMethodAdapter extends MethodVisitor { return; } if (!Character.isJavaIdentifierStart(name.charAt(0))) { - throw new IllegalArgumentException("Invalid " - + msg - + " (must be a '<init>', '<clinit>' or a valid Java identifier): " - + name); + throw new IllegalArgumentException( + "Invalid " + + msg + + " (must be a '<init>', '<clinit>' or a valid Java identifier): " + + name); } for (int i = 1; i < name.length(); ++i) { if (!Character.isJavaIdentifierPart(name.charAt(i))) { - throw new IllegalArgumentException("Invalid " - + msg - + " (must be '<init>' or '<clinit>' or a valid Java identifier): " - + name); + throw new IllegalArgumentException( + "Invalid " + + msg + + " (must be '<init>' or '<clinit>' or a valid Java identifier): " + + name); } } } @@ -1134,8 +1157,10 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the given string is a valid internal class name. * - * @param name the string to be checked. - * @param msg a message to be used in case of error. + * @param name + * the string to be checked. + * @param msg + * a message to be used in case of error. */ static void checkInternalName(final String name, final String msg) { if (name == null || name.length() == 0) { @@ -1152,19 +1177,19 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the given substring is a valid internal class name. * - * @param name the string to be checked. - * @param start index of the first character of the identifier (inclusive). - * @param end index of the last character of the identifier (exclusive). -1 - * is equivalent to <tt>name.length()</tt> if name is not - * <tt>null</tt>. - * @param msg a message to be used in case of error. + * @param name + * the string to be checked. + * @param start + * index of the first character of the identifier (inclusive). + * @param end + * index of the last character of the identifier (exclusive). -1 + * is equivalent to <tt>name.length()</tt> if name is not + * <tt>null</tt>. + * @param msg + * a message to be used in case of error. */ - static void checkInternalName( - final String name, - final int start, - final int end, - final String msg) - { + static void checkInternalName(final String name, final int start, + final int end, final String msg) { int max = end == -1 ? name.length() : end; try { int begin = start; @@ -1178,18 +1203,21 @@ public class CheckMethodAdapter extends MethodVisitor { begin = slash + 1; } while (slash != max); } catch (IllegalArgumentException _) { - throw new IllegalArgumentException("Invalid " - + msg - + " (must be a fully qualified class name in internal form): " - + name); + throw new IllegalArgumentException( + "Invalid " + + msg + + " (must be a fully qualified class name in internal form): " + + name); } } /** * Checks that the given string is a valid type descriptor. * - * @param desc the string to be checked. - * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid. + * @param desc + * the string to be checked. + * @param canBeVoid + * <tt>true</tt> if <tt>V</tt> can be considered valid. */ static void checkDesc(final String desc, final boolean canBeVoid) { int end = checkDesc(desc, 0, canBeVoid); @@ -1201,75 +1229,77 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that a the given substring is a valid type descriptor. * - * @param desc the string to be checked. - * @param start index of the first character of the identifier (inclusive). - * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid. + * @param desc + * the string to be checked. + * @param start + * index of the first character of the identifier (inclusive). + * @param canBeVoid + * <tt>true</tt> if <tt>V</tt> can be considered valid. * @return the index of the last character of the type decriptor, plus one. */ - static int checkDesc( - final String desc, - final int start, - final boolean canBeVoid) - { + static int checkDesc(final String desc, final int start, + final boolean canBeVoid) { if (desc == null || start >= desc.length()) { - throw new IllegalArgumentException("Invalid type descriptor (must not be null or empty)"); + throw new IllegalArgumentException( + "Invalid type descriptor (must not be null or empty)"); } int index; switch (desc.charAt(start)) { - case 'V': - if (canBeVoid) { - return start + 1; - } else { - throw new IllegalArgumentException("Invalid descriptor: " - + desc); - } - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - case 'F': - case 'J': - case 'D': + case 'V': + if (canBeVoid) { return start + 1; - case '[': - index = start + 1; - while (index < desc.length() && desc.charAt(index) == '[') { - ++index; - } - if (index < desc.length()) { - return checkDesc(desc, index, false); - } else { - throw new IllegalArgumentException("Invalid descriptor: " - + desc); - } - case 'L': - index = desc.indexOf(';', start); - if (index == -1 || index - start < 2) { - throw new IllegalArgumentException("Invalid descriptor: " - + desc); - } - try { - checkInternalName(desc, start + 1, index, null); - } catch (IllegalArgumentException _) { - throw new IllegalArgumentException("Invalid descriptor: " - + desc); - } - return index + 1; - default: + } else { + throw new IllegalArgumentException("Invalid descriptor: " + + desc); + } + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + case 'F': + case 'J': + case 'D': + return start + 1; + case '[': + index = start + 1; + while (index < desc.length() && desc.charAt(index) == '[') { + ++index; + } + if (index < desc.length()) { + return checkDesc(desc, index, false); + } else { throw new IllegalArgumentException("Invalid descriptor: " + desc); + } + case 'L': + index = desc.indexOf(';', start); + if (index == -1 || index - start < 2) { + throw new IllegalArgumentException("Invalid descriptor: " + + desc); + } + try { + checkInternalName(desc, start + 1, index, null); + } catch (IllegalArgumentException _) { + throw new IllegalArgumentException("Invalid descriptor: " + + desc); + } + return index + 1; + default: + throw new IllegalArgumentException("Invalid descriptor: " + desc); } } /** * Checks that the given string is a valid method descriptor. * - * @param desc the string to be checked. + * @param desc + * the string to be checked. */ static void checkMethodDesc(final String desc) { if (desc == null || desc.length() == 0) { - throw new IllegalArgumentException("Invalid method descriptor (must not be null or empty)"); + throw new IllegalArgumentException( + "Invalid method descriptor (must not be null or empty)"); } if (desc.charAt(0) != '(' || desc.length() < 3) { throw new IllegalArgumentException("Invalid descriptor: " + desc); @@ -1291,322 +1321,18 @@ public class CheckMethodAdapter extends MethodVisitor { } /** - * Checks a class signature. - * - * @param signature a string containing the signature that must be checked. - */ - static void checkClassSignature(final String signature) { - // ClassSignature: - // FormalTypeParameters? ClassTypeSignature ClassTypeSignature* - - int pos = 0; - if (getChar(signature, 0) == '<') { - pos = checkFormalTypeParameters(signature, pos); - } - pos = checkClassTypeSignature(signature, pos); - while (getChar(signature, pos) == 'L') { - pos = checkClassTypeSignature(signature, pos); - } - if (pos != signature.length()) { - throw new IllegalArgumentException(signature + ": error at index " - + pos); - } - } - - /** - * Checks a method signature. - * - * @param signature a string containing the signature that must be checked. - */ - static void checkMethodSignature(final String signature) { - // MethodTypeSignature: - // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) ( - // ^ClassTypeSignature | ^TypeVariableSignature )* - - int pos = 0; - if (getChar(signature, 0) == '<') { - pos = checkFormalTypeParameters(signature, pos); - } - pos = checkChar('(', signature, pos); - while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) { - pos = checkTypeSignature(signature, pos); - } - pos = checkChar(')', signature, pos); - if (getChar(signature, pos) == 'V') { - ++pos; - } else { - pos = checkTypeSignature(signature, pos); - } - while (getChar(signature, pos) == '^') { - ++pos; - if (getChar(signature, pos) == 'L') { - pos = checkClassTypeSignature(signature, pos); - } else { - pos = checkTypeVariableSignature(signature, pos); - } - } - if (pos != signature.length()) { - throw new IllegalArgumentException(signature + ": error at index " - + pos); - } - } - - /** - * Checks a field signature. - * - * @param signature a string containing the signature that must be checked. - */ - static void checkFieldSignature(final String signature) { - int pos = checkFieldTypeSignature(signature, 0); - if (pos != signature.length()) { - throw new IllegalArgumentException(signature + ": error at index " - + pos); - } - } - - /** - * Checks the formal type parameters of a class or method signature. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkFormalTypeParameters(final String signature, int pos) - { - // FormalTypeParameters: - // < FormalTypeParameter+ > - - pos = checkChar('<', signature, pos); - pos = checkFormalTypeParameter(signature, pos); - while (getChar(signature, pos) != '>') { - pos = checkFormalTypeParameter(signature, pos); - } - return pos + 1; - } - - /** - * Checks a formal type parameter of a class or method signature. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkFormalTypeParameter(final String signature, int pos) - { - // FormalTypeParameter: - // Identifier : FieldTypeSignature? (: FieldTypeSignature)* - - pos = checkIdentifier(signature, pos); - pos = checkChar(':', signature, pos); - if ("L[T".indexOf(getChar(signature, pos)) != -1) { - pos = checkFieldTypeSignature(signature, pos); - } - while (getChar(signature, pos) == ':') { - pos = checkFieldTypeSignature(signature, pos + 1); - } - return pos; - } - - /** - * Checks a field type signature. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkFieldTypeSignature(final String signature, int pos) - { - // FieldTypeSignature: - // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature - // - // ArrayTypeSignature: - // [ TypeSignature - - switch (getChar(signature, pos)) { - case 'L': - return checkClassTypeSignature(signature, pos); - case '[': - return checkTypeSignature(signature, pos + 1); - default: - return checkTypeVariableSignature(signature, pos); - } - } - - /** - * Checks a class type signature. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkClassTypeSignature(final String signature, int pos) - { - // ClassTypeSignature: - // L Identifier ( / Identifier )* TypeArguments? ( . Identifier - // TypeArguments? )* ; - - pos = checkChar('L', signature, pos); - pos = checkIdentifier(signature, pos); - while (getChar(signature, pos) == '/') { - pos = checkIdentifier(signature, pos + 1); - } - if (getChar(signature, pos) == '<') { - pos = checkTypeArguments(signature, pos); - } - while (getChar(signature, pos) == '.') { - pos = checkIdentifier(signature, pos + 1); - if (getChar(signature, pos) == '<') { - pos = checkTypeArguments(signature, pos); - } - } - return checkChar(';', signature, pos); - } - - /** - * Checks the type arguments in a class type signature. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkTypeArguments(final String signature, int pos) { - // TypeArguments: - // < TypeArgument+ > - - pos = checkChar('<', signature, pos); - pos = checkTypeArgument(signature, pos); - while (getChar(signature, pos) != '>') { - pos = checkTypeArgument(signature, pos); - } - return pos + 1; - } - - /** - * Checks a type argument in a class type signature. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkTypeArgument(final String signature, int pos) { - // TypeArgument: - // * | ( ( + | - )? FieldTypeSignature ) - - char c = getChar(signature, pos); - if (c == '*') { - return pos + 1; - } else if (c == '+' || c == '-') { - pos++; - } - return checkFieldTypeSignature(signature, pos); - } - - /** - * Checks a type variable signature. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkTypeVariableSignature( - final String signature, - int pos) - { - // TypeVariableSignature: - // T Identifier ; - - pos = checkChar('T', signature, pos); - pos = checkIdentifier(signature, pos); - return checkChar(';', signature, pos); - } - - /** - * Checks a type signature. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkTypeSignature(final String signature, int pos) { - // TypeSignature: - // Z | C | B | S | I | F | J | D | FieldTypeSignature - - switch (getChar(signature, pos)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - case 'F': - case 'J': - case 'D': - return pos + 1; - default: - return checkFieldTypeSignature(signature, pos); - } - } - - /** - * Checks an identifier. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkIdentifier(final String signature, int pos) { - if (!Character.isJavaIdentifierStart(getChar(signature, pos))) { - throw new IllegalArgumentException(signature - + ": identifier expected at index " + pos); - } - ++pos; - while (Character.isJavaIdentifierPart(getChar(signature, pos))) { - ++pos; - } - return pos; - } - - /** - * Checks a single character. - * - * @param signature a string containing the signature that must be checked. - * @param pos index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkChar(final char c, final String signature, int pos) - { - if (getChar(signature, pos) == c) { - return pos + 1; - } - throw new IllegalArgumentException(signature + ": '" + c - + "' expected at index " + pos); - } - - /** - * Returns the signature car at the given index. - * - * @param signature a signature. - * @param pos an index in signature. - * @return the character at the given index, or 0 if there is no such - * character. - */ - private static char getChar(final String signature, int pos) { - return pos < signature.length() ? signature.charAt(pos) : (char) 0; - } - - /** * Checks that the given label is not null. This method can also check that * the label has been visited. * - * @param label the label to be checked. - * @param checkVisited <tt>true</tt> to check that the label has been - * visited. - * @param msg a message to be used in case of error. + * @param label + * the label to be checked. + * @param checkVisited + * <tt>true</tt> to check that the label has been visited. + * @param msg + * a message to be used in case of error. */ - void checkLabel( - final Label label, - final boolean checkVisited, - final String msg) - { + void checkLabel(final Label label, final boolean checkVisited, + final String msg) { if (label == null) { throw new IllegalArgumentException("Invalid " + msg + " (must not be null)"); @@ -1620,7 +1346,8 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Checks that the given label is not a label used only for debug purposes. * - * @param label the label to be checked. + * @param label + * the label to be checked. */ private static void checkNonDebugLabel(final Label label) { Field f = getLabelStatusField(); @@ -1631,7 +1358,8 @@ public class CheckMethodAdapter extends MethodVisitor { throw new Error("Internal error"); } if ((status & 0x01) != 0) { - throw new IllegalArgumentException("Labels used for debug info cannot be reused for control flow"); + throw new IllegalArgumentException( + "Labels used for debug info cannot be reused for control flow"); } } @@ -1653,7 +1381,8 @@ public class CheckMethodAdapter extends MethodVisitor { /** * Returns the field of the Label class whose name is given. * - * @param name a field name. + * @param name + * a field name. * @return the field of the Label class whose name is given, or null. */ private static Field getLabelField(final String name) { diff --git a/src/asm/scala/tools/asm/util/CheckSignatureAdapter.java b/src/asm/scala/tools/asm/util/CheckSignatureAdapter.java index 3a6c3e780f..e69302b8a6 100644 --- a/src/asm/scala/tools/asm/util/CheckSignatureAdapter.java +++ b/src/asm/scala/tools/asm/util/CheckSignatureAdapter.java @@ -41,19 +41,22 @@ public class CheckSignatureAdapter extends SignatureVisitor { /** * Type to be used to check class signatures. See - * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}. + * {@link #CheckSignatureAdapter(int, SignatureVisitor) + * CheckSignatureAdapter}. */ public static final int CLASS_SIGNATURE = 0; /** * Type to be used to check method signatures. See - * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}. + * {@link #CheckSignatureAdapter(int, SignatureVisitor) + * CheckSignatureAdapter}. */ public static final int METHOD_SIGNATURE = 1; /** * Type to be used to check type signatures.See - * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}. + * {@link #CheckSignatureAdapter(int, SignatureVisitor) + * CheckSignatureAdapter}. */ public static final int TYPE_SIGNATURE = 2; @@ -101,11 +104,13 @@ public class CheckSignatureAdapter extends SignatureVisitor { * not use this constructor</i>. Instead, they must use the * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version. * - * @param type the type of signature to be checked. See - * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and - * {@link #TYPE_SIGNATURE}. - * @param sv the visitor to which this adapter must delegate calls. May be - * <tt>null</tt>. + * @param type + * the type of signature to be checked. See + * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and + * {@link #TYPE_SIGNATURE}. + * @param sv + * the visitor to which this adapter must delegate calls. May be + * <tt>null</tt>. */ public CheckSignatureAdapter(final int type, final SignatureVisitor sv) { this(Opcodes.ASM4, type, sv); @@ -114,19 +119,19 @@ public class CheckSignatureAdapter extends SignatureVisitor { /** * Creates a new {@link CheckSignatureAdapter} object. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param type the type of signature to be checked. See - * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and - * {@link #TYPE_SIGNATURE}. - * @param sv the visitor to which this adapter must delegate calls. May be - * <tt>null</tt>. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param type + * the type of signature to be checked. See + * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and + * {@link #TYPE_SIGNATURE}. + * @param sv + * the visitor to which this adapter must delegate calls. May be + * <tt>null</tt>. */ - protected CheckSignatureAdapter( - final int api, - final int type, - final SignatureVisitor sv) - { + protected CheckSignatureAdapter(final int api, final int type, + final SignatureVisitor sv) { super(api); this.type = type; this.state = EMPTY; @@ -138,8 +143,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { @Override public void visitFormalTypeParameter(final String name) { if (type == TYPE_SIGNATURE - || (state != EMPTY && state != FORMAL && state != BOUND)) - { + || (state != EMPTY && state != FORMAL && state != BOUND)) { throw new IllegalStateException(); } CheckMethodAdapter.checkIdentifier(name, "formal type parameter"); @@ -172,8 +176,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { @Override public SignatureVisitor visitSuperclass() { - if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) - { + if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) { throw new IllegalArgumentException(); } state = SUPER; @@ -195,8 +198,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { @Override public SignatureVisitor visitParameterType() { if (type != METHOD_SIGNATURE - || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) - { + || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) { throw new IllegalArgumentException(); } state = PARAM; @@ -207,8 +209,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { @Override public SignatureVisitor visitReturnType() { if (type != METHOD_SIGNATURE - || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) - { + || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) { throw new IllegalArgumentException(); } state = RETURN; diff --git a/src/asm/scala/tools/asm/util/Printer.java b/src/asm/scala/tools/asm/util/Printer.java index c39fd548ce..86e0f9e122 100644 --- a/src/asm/scala/tools/asm/util/Printer.java +++ b/src/asm/scala/tools/asm/util/Printer.java @@ -52,14 +52,14 @@ public abstract class Printer { /** * The names of the for <code>operand</code> parameter values of the - * {@link org.objectweb.asm.MethodVisitor#visitIntInsn} method when + * {@link scala.tools.asm.MethodVisitor#visitIntInsn} method when * <code>opcode</code> is <code>NEWARRAY</code>. */ public static final String[] TYPES; /** * The names of the <code>tag</code> field values for - * {@link org.objectweb.asm.Handle}. + * {@link scala.tools.asm.Handle}. */ public static final String[] HANDLE_TAG; @@ -103,8 +103,8 @@ public abstract class Printer { } s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC," - + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL," - + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,"; + + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL," + + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,"; HANDLE_TAG = new String[10]; j = 0; i = 1; @@ -149,81 +149,58 @@ public abstract class Printer { } /** - * Class header. - * See {@link org.objectweb.asm.ClassVisitor#visit}. + * Class header. See {@link scala.tools.asm.ClassVisitor#visit}. */ - public abstract void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces); + public abstract void visit(final int version, final int access, + final String name, final String signature, final String superName, + final String[] interfaces); /** - * Class source. - * See {@link org.objectweb.asm.ClassVisitor#visitSource}. + * Class source. See {@link scala.tools.asm.ClassVisitor#visitSource}. */ public abstract void visitSource(final String file, final String debug); /** - * Class outer class. - * See {@link org.objectweb.asm.ClassVisitor#visitOuterClass}. + * Class outer class. See + * {@link scala.tools.asm.ClassVisitor#visitOuterClass}. */ - public abstract void visitOuterClass( - final String owner, - final String name, - final String desc); + public abstract void visitOuterClass(final String owner, final String name, + final String desc); /** - * Class annotation. - * See {@link org.objectweb.asm.ClassVisitor#visitAnnotation}. + * Class annotation. See + * {@link scala.tools.asm.ClassVisitor#visitAnnotation}. */ - public abstract Printer visitClassAnnotation( - final String desc, - final boolean visible); + public abstract Printer visitClassAnnotation(final String desc, + final boolean visible); /** - * Class attribute. - * See {@link org.objectweb.asm.ClassVisitor#visitAttribute}. + * Class attribute. See + * {@link scala.tools.asm.ClassVisitor#visitAttribute}. */ public abstract void visitClassAttribute(final Attribute attr); /** - * Class inner name. - * See {@link org.objectweb.asm.ClassVisitor#visitInnerClass}. + * Class inner name. See + * {@link scala.tools.asm.ClassVisitor#visitInnerClass}. */ - public abstract void visitInnerClass( - final String name, - final String outerName, - final String innerName, - final int access); + public abstract void visitInnerClass(final String name, + final String outerName, final String innerName, final int access); /** - * Class field. - * See {@link org.objectweb.asm.ClassVisitor#visitField}. + * Class field. See {@link scala.tools.asm.ClassVisitor#visitField}. */ - public abstract Printer visitField( - final int access, - final String name, - final String desc, - final String signature, - final Object value); + public abstract Printer visitField(final int access, final String name, + final String desc, final String signature, final Object value); /** - * Class method. - * See {@link org.objectweb.asm.ClassVisitor#visitMethod}. + * Class method. See {@link scala.tools.asm.ClassVisitor#visitMethod}. */ - public abstract Printer visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions); + public abstract Printer visitMethod(final int access, final String name, + final String desc, final String signature, final String[] exceptions); /** - * Class end. - * See {@link org.objectweb.asm.ClassVisitor#visitEnd}. + * Class end. See {@link scala.tools.asm.ClassVisitor#visitEnd}. */ public abstract void visitClassEnd(); @@ -232,37 +209,31 @@ public abstract class Printer { // ------------------------------------------------------------------------ /** - * Annotation value. - * See {@link org.objectweb.asm.AnnotationVisitor#visit}. + * Annotation value. See {@link scala.tools.asm.AnnotationVisitor#visit}. */ public abstract void visit(final String name, final Object value); /** - * Annotation enum value. - * See {@link org.objectweb.asm.AnnotationVisitor#visitEnum}. + * Annotation enum value. See + * {@link scala.tools.asm.AnnotationVisitor#visitEnum}. */ - public abstract void visitEnum( - final String name, - final String desc, - final String value); + public abstract void visitEnum(final String name, final String desc, + final String value); /** - * Nested annotation value. - * See {@link org.objectweb.asm.AnnotationVisitor#visitAnnotation}. + * Nested annotation value. See + * {@link scala.tools.asm.AnnotationVisitor#visitAnnotation}. */ - public abstract Printer visitAnnotation( - final String name, - final String desc); + public abstract Printer visitAnnotation(final String name, final String desc); /** - * Annotation array value. - * See {@link org.objectweb.asm.AnnotationVisitor#visitArray}. + * Annotation array value. See + * {@link scala.tools.asm.AnnotationVisitor#visitArray}. */ public abstract Printer visitArray(final String name); /** - * Annotation end. - * See {@link org.objectweb.asm.AnnotationVisitor#visitEnd}. + * Annotation end. See {@link scala.tools.asm.AnnotationVisitor#visitEnd}. */ public abstract void visitAnnotationEnd(); @@ -271,22 +242,20 @@ public abstract class Printer { // ------------------------------------------------------------------------ /** - * Field annotation. - * See {@link org.objectweb.asm.FieldVisitor#visitAnnotation}. + * Field annotation. See + * {@link scala.tools.asm.FieldVisitor#visitAnnotation}. */ - public abstract Printer visitFieldAnnotation( - final String desc, - final boolean visible); + public abstract Printer visitFieldAnnotation(final String desc, + final boolean visible); /** - * Field attribute. - * See {@link org.objectweb.asm.FieldVisitor#visitAttribute}. + * Field attribute. See + * {@link scala.tools.asm.FieldVisitor#visitAttribute}. */ public abstract void visitFieldAttribute(final Attribute attr); /** - * Field end. - * See {@link org.objectweb.asm.FieldVisitor#visitEnd}. + * Field end. See {@link scala.tools.asm.FieldVisitor#visitEnd}. */ public abstract void visitFieldEnd(); @@ -295,193 +264,161 @@ public abstract class Printer { // ------------------------------------------------------------------------ /** - * Method default annotation. - * See {@link org.objectweb.asm.MethodVisitor#visitAnnotationDefault}. + * Method default annotation. See + * {@link scala.tools.asm.MethodVisitor#visitAnnotationDefault}. */ public abstract Printer visitAnnotationDefault(); /** - * Method annotation. - * See {@link org.objectweb.asm.MethodVisitor#visitAnnotation}. + * Method annotation. See + * {@link scala.tools.asm.MethodVisitor#visitAnnotation}. */ - public abstract Printer visitMethodAnnotation( - final String desc, - final boolean visible); + public abstract Printer visitMethodAnnotation(final String desc, + final boolean visible); /** - * Method parameter annotation. - * See {@link org.objectweb.asm.MethodVisitor#visitParameterAnnotation}. + * Method parameter annotation. See + * {@link scala.tools.asm.MethodVisitor#visitParameterAnnotation}. */ - public abstract Printer visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible); + public abstract Printer visitParameterAnnotation(final int parameter, + final String desc, final boolean visible); /** - * Method attribute. - * See {@link org.objectweb.asm.MethodVisitor#visitAttribute}. + * Method attribute. See + * {@link scala.tools.asm.MethodVisitor#visitAttribute}. */ public abstract void visitMethodAttribute(final Attribute attr); /** - * Method start. - * See {@link org.objectweb.asm.MethodVisitor#visitCode}. + * Method start. See {@link scala.tools.asm.MethodVisitor#visitCode}. */ public abstract void visitCode(); /** - * Method stack frame. - * See {@link org.objectweb.asm.MethodVisitor#visitFrame}. + * Method stack frame. See + * {@link scala.tools.asm.MethodVisitor#visitFrame}. */ - public abstract void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack); + public abstract void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitInsn}. + * Method instruction. See {@link scala.tools.asm.MethodVisitor#visitInsn} + * . */ public abstract void visitInsn(final int opcode); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitIntInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitIntInsn}. */ public abstract void visitIntInsn(final int opcode, final int operand); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitVarInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitVarInsn}. */ public abstract void visitVarInsn(final int opcode, final int var); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitTypeInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitTypeInsn}. */ public abstract void visitTypeInsn(final int opcode, final String type); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitFieldInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitFieldInsn}. */ - public abstract void visitFieldInsn( - final int opcode, - final String owner, - final String name, - final String desc); + public abstract void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitMethodInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitMethodInsn}. */ - public abstract void visitMethodInsn( - final int opcode, - final String owner, - final String name, - final String desc); + public abstract void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitInvokeDynamicInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitInvokeDynamicInsn}. */ - public abstract void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs); + public abstract void visitInvokeDynamicInsn(String name, String desc, + Handle bsm, Object... bsmArgs); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitJumpInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitJumpInsn}. */ public abstract void visitJumpInsn(final int opcode, final Label label); /** - * Method label. - * See {@link org.objectweb.asm.MethodVisitor#visitLabel}. + * Method label. See {@link scala.tools.asm.MethodVisitor#visitLabel}. */ public abstract void visitLabel(final Label label); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitLdcInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitLdcInsn}. */ public abstract void visitLdcInsn(final Object cst); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitIincInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitIincInsn}. */ public abstract void visitIincInsn(final int var, final int increment); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitTableSwitchInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitTableSwitchInsn}. */ - public abstract void visitTableSwitchInsn( - final int min, - final int max, - final Label dflt, - final Label... labels); + public abstract void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitLookupSwitchInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitLookupSwitchInsn}. */ - public abstract void visitLookupSwitchInsn( - final Label dflt, - final int[] keys, - final Label[] labels); + public abstract void visitLookupSwitchInsn(final Label dflt, + final int[] keys, final Label[] labels); /** - * Method instruction. - * See {@link org.objectweb.asm.MethodVisitor#visitMultiANewArrayInsn}. + * Method instruction. See + * {@link scala.tools.asm.MethodVisitor#visitMultiANewArrayInsn}. */ - public abstract void visitMultiANewArrayInsn( - final String desc, - final int dims); + public abstract void visitMultiANewArrayInsn(final String desc, + final int dims); /** - * Method exception handler. - * See {@link org.objectweb.asm.MethodVisitor#visitTryCatchBlock}. + * Method exception handler. See + * {@link scala.tools.asm.MethodVisitor#visitTryCatchBlock}. */ - public abstract void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type); + public abstract void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type); /** - * Method debug info. - * See {@link org.objectweb.asm.MethodVisitor#visitLocalVariable}. + * Method debug info. See + * {@link scala.tools.asm.MethodVisitor#visitLocalVariable}. */ - public abstract void visitLocalVariable( - final String name, - final String desc, - final String signature, - final Label start, - final Label end, - final int index); + public abstract void visitLocalVariable(final String name, + final String desc, final String signature, final Label start, + final Label end, final int index); /** - * Method debug info. - * See {@link org.objectweb.asm.MethodVisitor#visitLineNumber}. + * Method debug info. See + * {@link scala.tools.asm.MethodVisitor#visitLineNumber}. */ public abstract void visitLineNumber(final int line, final Label start); /** - * Method max stack and max locals. - * See {@link org.objectweb.asm.MethodVisitor#visitMaxs}. + * Method max stack and max locals. See + * {@link scala.tools.asm.MethodVisitor#visitMaxs}. */ public abstract void visitMaxs(final int maxStack, final int maxLocals); /** - * Method end. - * See {@link org.objectweb.asm.MethodVisitor#visitEnd}. + * Method end. See {@link scala.tools.asm.MethodVisitor#visitEnd}. */ public abstract void visitMethodEnd(); @@ -497,7 +434,8 @@ public abstract class Printer { /** * Prints the text constructed by this visitor. * - * @param pw the print writer to be used. + * @param pw + * the print writer to be used. */ public void print(final PrintWriter pw) { printList(pw, text); @@ -506,8 +444,10 @@ public abstract class Printer { /** * Appends a quoted string to a given buffer. * - * @param buf the buffer where the string must be added. - * @param s the string to be added. + * @param buf + * the buffer where the string must be added. + * @param s + * the string to be added. */ public static void appendString(final StringBuffer buf, final String s) { buf.append('\"'); @@ -541,9 +481,11 @@ public abstract class Printer { /** * Prints the given string tree. * - * @param pw the writer to be used to print the tree. - * @param l a string tree, i.e., a string list that can contain other string - * lists, and so on recursively. + * @param pw + * the writer to be used to print the tree. + * @param l + * a string tree, i.e., a string list that can contain other + * string lists, and so on recursively. */ static void printList(final PrintWriter pw, final List<?> l) { for (int i = 0; i < l.size(); ++i) { diff --git a/src/asm/scala/tools/asm/util/SignatureChecker.java b/src/asm/scala/tools/asm/util/SignatureChecker.java deleted file mode 100644 index 71f0d80027..0000000000 --- a/src/asm/scala/tools/asm/util/SignatureChecker.java +++ /dev/null @@ -1,47 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - */ - -package scala.tools.asm.util; - -import scala.tools.asm.util.CheckMethodAdapter; -import scala.tools.asm.MethodVisitor; - -/** - * A subclass of ASM's CheckMethodAdapter for the sole purpose of accessing some protected methods there. - * - */ -public class SignatureChecker extends CheckMethodAdapter { - - public SignatureChecker(final MethodVisitor mv) { - super(mv); - } - - /** - * Checks a class signature. - * - * @param signature a string containing the signature that must be checked. - */ - public static void checkClassSignature(final String signature) { - CheckMethodAdapter.checkClassSignature(signature); - } - - /** - * Checks a method signature. - * - * @param signature a string containing the signature that must be checked. - */ - public static void checkMethodSignature(final String signature) { - CheckMethodAdapter.checkMethodSignature(signature); - } - - /** - * Checks a field signature. - * - * @param signature a string containing the signature that must be checked. - */ - public static void checkFieldSignature(final String signature) { - CheckMethodAdapter.checkFieldSignature(signature); - } - -} diff --git a/src/asm/scala/tools/asm/util/Textifiable.java b/src/asm/scala/tools/asm/util/Textifiable.java index b80d0139db..85e051e2f8 100644 --- a/src/asm/scala/tools/asm/util/Textifiable.java +++ b/src/asm/scala/tools/asm/util/Textifiable.java @@ -34,7 +34,7 @@ import java.util.Map; import scala.tools.asm.Label; /** - * An {@link org.objectweb.asm.Attribute Attribute} that can print a readable + * An {@link scala.tools.asm.Attribute Attribute} that can print a readable * representation of itself. * * Implementations should construct readable output from an attribute data @@ -47,8 +47,10 @@ public interface Textifiable { /** * Build a human readable representation of this attribute. * - * @param buf a buffer used for printing Java code. - * @param labelNames map of label instances to their names. + * @param buf + * a buffer used for printing Java code. + * @param labelNames + * map of label instances to their names. */ void textify(StringBuffer buf, Map<Label, String> labelNames); } diff --git a/src/asm/scala/tools/asm/util/Textifier.java b/src/asm/scala/tools/asm/util/Textifier.java index 8d40ebd026..a5c4f6779e 100644 --- a/src/asm/scala/tools/asm/util/Textifier.java +++ b/src/asm/scala/tools/asm/util/Textifier.java @@ -149,22 +149,24 @@ public class Textifier extends Printer { /** * Constructs a new {@link Textifier}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. */ protected Textifier(final int api) { super(api); } /** - * Prints a disassembled view of the given class to the standard output. <p> - * Usage: Textifier [-debug] <binary class name or class - * file name > + * Prints a disassembled view of the given class to the standard output. + * <p> + * Usage: Textifier [-debug] <binary class name or class file name > * - * @param args the command line arguments. + * @param args + * the command line arguments. * - * @throws Exception if the class cannot be found, or if an IO exception - * occurs. + * @throws Exception + * if the class cannot be found, or if an IO exception occurs. */ public static void main(final String[] args) throws Exception { int i = 0; @@ -182,21 +184,20 @@ public class Textifier extends Printer { } } if (!ok) { - System.err.println("Prints a disassembled view of the given class."); + System.err + .println("Prints a disassembled view of the given class."); System.err.println("Usage: Textifier [-debug] " + "<fully qualified class name or class file name>"); return; } ClassReader cr; if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1 - || args[i].indexOf('/') > -1) - { + || args[i].indexOf('/') > -1) { cr = new ClassReader(new FileInputStream(args[i])); } else { cr = new ClassReader(args[i]); } - cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), - flags); + cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags); } // ------------------------------------------------------------------------ @@ -204,38 +205,27 @@ public class Textifier extends Printer { // ------------------------------------------------------------------------ @Override - public void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces) - { + public void visit(final int version, final int access, final String name, + final String signature, final String superName, + final String[] interfaces) { int major = version & 0xFFFF; int minor = version >>> 16; buf.setLength(0); - buf.append("// class version ") - .append(major) - .append('.') - .append(minor) - .append(" (") - .append(version) - .append(")\n"); + buf.append("// class version ").append(major).append('.').append(minor) + .append(" (").append(version).append(")\n"); if ((access & Opcodes.ACC_DEPRECATED) != 0) { buf.append("// DEPRECATED\n"); } - buf.append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n'); + buf.append("// access flags 0x") + .append(Integer.toHexString(access).toUpperCase()).append('\n'); appendDescriptor(CLASS_SIGNATURE, signature); if (signature != null) { TraceSignatureVisitor sv = new TraceSignatureVisitor(access); SignatureReader r = new SignatureReader(signature); r.accept(sv); - buf.append("// declaration: ") - .append(name) - .append(sv.getDeclaration()) - .append('\n'); + buf.append("// declaration: ").append(name) + .append(sv.getDeclaration()).append('\n'); } appendAccess(access & ~Opcodes.ACC_SUPER); @@ -269,15 +259,11 @@ public class Textifier extends Printer { public void visitSource(final String file, final String debug) { buf.setLength(0); if (file != null) { - buf.append(tab) - .append("// compiled from: ") - .append(file) + buf.append(tab).append("// compiled from: ").append(file) .append('\n'); } if (debug != null) { - buf.append(tab) - .append("// debug info: ") - .append(debug) + buf.append(tab).append("// debug info: ").append(debug) .append('\n'); } if (buf.length() > 0) { @@ -286,11 +272,8 @@ public class Textifier extends Printer { } @Override - public void visitOuterClass( - final String owner, - final String name, - final String desc) - { + public void visitOuterClass(final String owner, final String name, + final String desc) { buf.setLength(0); buf.append(tab).append("OUTERCLASS "); appendDescriptor(INTERNAL_NAME, owner); @@ -304,10 +287,8 @@ public class Textifier extends Printer { } @Override - public Textifier visitClassAnnotation( - final String desc, - final boolean visible) - { + public Textifier visitClassAnnotation(final String desc, + final boolean visible) { text.add("\n"); return visitAnnotation(desc, visible); } @@ -319,15 +300,13 @@ public class Textifier extends Printer { } @Override - public void visitInnerClass( - final String name, - final String outerName, - final String innerName, - final int access) - { + public void visitInnerClass(final String name, final String outerName, + final String innerName, final int access) { buf.setLength(0); buf.append(tab).append("// access flags 0x"); - buf.append(Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase()).append('\n'); + buf.append( + Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase()) + .append('\n'); buf.append(tab); appendAccess(access); buf.append("INNERCLASS "); @@ -341,19 +320,15 @@ public class Textifier extends Printer { } @Override - public Textifier visitField( - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { + public Textifier visitField(final int access, final String name, + final String desc, final String signature, final Object value) { buf.setLength(0); buf.append('\n'); if ((access & Opcodes.ACC_DEPRECATED) != 0) { buf.append(tab).append("// DEPRECATED\n"); } - buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n'); + buf.append(tab).append("// access flags 0x") + .append(Integer.toHexString(access).toUpperCase()).append('\n'); if (signature != null) { buf.append(tab); appendDescriptor(FIELD_SIGNATURE, signature); @@ -361,10 +336,8 @@ public class Textifier extends Printer { TraceSignatureVisitor sv = new TraceSignatureVisitor(0); SignatureReader r = new SignatureReader(signature); r.acceptType(sv); - buf.append(tab) - .append("// declaration: ") - .append(sv.getDeclaration()) - .append('\n'); + buf.append(tab).append("// declaration: ") + .append(sv.getDeclaration()).append('\n'); } buf.append(tab); @@ -390,19 +363,15 @@ public class Textifier extends Printer { } @Override - public Textifier visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { + public Textifier visitMethod(final int access, final String name, + final String desc, final String signature, final String[] exceptions) { buf.setLength(0); buf.append('\n'); if ((access & Opcodes.ACC_DEPRECATED) != 0) { buf.append(tab).append("// DEPRECATED\n"); } - buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n'); + buf.append(tab).append("// access flags 0x") + .append(Integer.toHexString(access).toUpperCase()).append('\n'); if (signature != null) { buf.append(tab); @@ -415,12 +384,8 @@ public class Textifier extends Printer { String genericReturn = v.getReturnType(); String genericExceptions = v.getExceptions(); - buf.append(tab) - .append("// declaration: ") - .append(genericReturn) - .append(' ') - .append(name) - .append(genericDecl); + buf.append(tab).append("// declaration: ").append(genericReturn) + .append(' ').append(name).append(genericDecl); if (genericExceptions != null) { buf.append(" throws ").append(genericExceptions); } @@ -593,11 +558,8 @@ public class Textifier extends Printer { } @Override - public void visitEnum( - final String name, - final String desc, - final String value) - { + public void visitEnum(final String name, final String desc, + final String value) { buf.setLength(0); appendComa(valueNumber++); if (name != null) { @@ -609,10 +571,7 @@ public class Textifier extends Printer { } @Override - public Textifier visitAnnotation( - final String name, - final String desc) - { + public Textifier visitAnnotation(final String name, final String desc) { buf.setLength(0); appendComa(valueNumber++); if (name != null) { @@ -629,9 +588,7 @@ public class Textifier extends Printer { } @Override - public Textifier visitArray( - final String name) - { + public Textifier visitArray(final String name) { buf.setLength(0); appendComa(valueNumber++); if (name != null) { @@ -654,10 +611,8 @@ public class Textifier extends Printer { // ------------------------------------------------------------------------ @Override - public Textifier visitFieldAnnotation( - final String desc, - final boolean visible) - { + public Textifier visitFieldAnnotation(final String desc, + final boolean visible) { return visitAnnotation(desc, visible); } @@ -684,19 +639,14 @@ public class Textifier extends Printer { } @Override - public Textifier visitMethodAnnotation( - final String desc, - final boolean visible) - { + public Textifier visitMethodAnnotation(final String desc, + final boolean visible) { return visitAnnotation(desc, visible); } @Override - public Textifier visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) - { + public Textifier visitParameterAnnotation(final int parameter, + final String desc, final boolean visible) { buf.setLength(0); buf.append(tab2).append('@'); appendDescriptor(FIELD_DESCRIPTOR, desc); @@ -730,40 +680,35 @@ public class Textifier extends Printer { } @Override - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) - { + public void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack) { buf.setLength(0); buf.append(ltab); buf.append("FRAME "); switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - buf.append("FULL ["); - appendFrameTypes(nLocal, local); - buf.append("] ["); - appendFrameTypes(nStack, stack); - buf.append(']'); - break; - case Opcodes.F_APPEND: - buf.append("APPEND ["); - appendFrameTypes(nLocal, local); - buf.append(']'); - break; - case Opcodes.F_CHOP: - buf.append("CHOP ").append(nLocal); - break; - case Opcodes.F_SAME: - buf.append("SAME"); - break; - case Opcodes.F_SAME1: - buf.append("SAME1 "); - appendFrameTypes(1, stack); - break; + case Opcodes.F_NEW: + case Opcodes.F_FULL: + buf.append("FULL ["); + appendFrameTypes(nLocal, local); + buf.append("] ["); + appendFrameTypes(nStack, stack); + buf.append(']'); + break; + case Opcodes.F_APPEND: + buf.append("APPEND ["); + appendFrameTypes(nLocal, local); + buf.append(']'); + break; + case Opcodes.F_CHOP: + buf.append("CHOP ").append(nLocal); + break; + case Opcodes.F_SAME: + buf.append("SAME"); + break; + case Opcodes.F_SAME1: + buf.append("SAME1 "); + appendFrameTypes(1, stack); + break; } buf.append('\n'); text.add(buf.toString()); @@ -782,20 +727,15 @@ public class Textifier extends Printer { buf.append(tab2) .append(OPCODES[opcode]) .append(' ') - .append(opcode == Opcodes.NEWARRAY - ? TYPES[operand] - : Integer.toString(operand)) - .append('\n'); + .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer + .toString(operand)).append('\n'); text.add(buf.toString()); } @Override public void visitVarInsn(final int opcode, final int var) { buf.setLength(0); - buf.append(tab2) - .append(OPCODES[opcode]) - .append(' ') - .append(var) + buf.append(tab2).append(OPCODES[opcode]).append(' ').append(var) .append('\n'); text.add(buf.toString()); } @@ -810,12 +750,8 @@ public class Textifier extends Printer { } @Override - public void visitFieldInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc) { buf.setLength(0); buf.append(tab2).append(OPCODES[opcode]).append(' '); appendDescriptor(INTERNAL_NAME, owner); @@ -826,12 +762,8 @@ public class Textifier extends Printer { } @Override - public void visitMethodInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { buf.setLength(0); buf.append(tab2).append(OPCODES[opcode]).append(' '); appendDescriptor(INTERNAL_NAME, owner); @@ -842,12 +774,8 @@ public class Textifier extends Printer { } @Override - public void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs) - { + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { buf.setLength(0); buf.append(tab2).append("INVOKEDYNAMIC").append(' '); buf.append(name); @@ -855,11 +783,11 @@ public class Textifier extends Printer { buf.append(" ["); appendHandle(bsm); buf.append(tab3).append("// arguments:"); - if(bsmArgs.length == 0) { + if (bsmArgs.length == 0) { buf.append(" none"); } else { buf.append('\n').append(tab3); - for(int i = 0; i < bsmArgs.length; i++) { + for (int i = 0; i < bsmArgs.length; i++) { Object cst = bsmArgs[i]; if (cst instanceof String) { Printer.appendString(buf, (String) cst); @@ -915,22 +843,14 @@ public class Textifier extends Printer { @Override public void visitIincInsn(final int var, final int increment) { buf.setLength(0); - buf.append(tab2) - .append("IINC ") - .append(var) - .append(' ') - .append(increment) - .append('\n'); + buf.append(tab2).append("IINC ").append(var).append(' ') + .append(increment).append('\n'); text.add(buf.toString()); } @Override - public void visitTableSwitchInsn( - final int min, - final int max, - final Label dflt, - final Label... labels) - { + public void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels) { buf.setLength(0); buf.append(tab2).append("TABLESWITCH\n"); for (int i = 0; i < labels.length; ++i) { @@ -945,11 +865,8 @@ public class Textifier extends Printer { } @Override - public void visitLookupSwitchInsn( - final Label dflt, - final int[] keys, - final Label[] labels) - { + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, + final Label[] labels) { buf.setLength(0); buf.append(tab2).append("LOOKUPSWITCH\n"); for (int i = 0; i < labels.length; ++i) { @@ -973,12 +890,8 @@ public class Textifier extends Printer { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type) { buf.setLength(0); buf.append(tab2).append("TRYCATCHBLOCK "); appendLabel(start); @@ -993,14 +906,9 @@ public class Textifier extends Printer { } @Override - public void visitLocalVariable( - final String name, - final String desc, - final String signature, - final Label start, - final Label end, - final int index) - { + public void visitLocalVariable(final String name, final String desc, + final String signature, final Label start, final Label end, + final int index) { buf.setLength(0); buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' '); appendDescriptor(FIELD_DESCRIPTOR, desc); @@ -1017,10 +925,8 @@ public class Textifier extends Printer { TraceSignatureVisitor sv = new TraceSignatureVisitor(0); SignatureReader r = new SignatureReader(signature); r.acceptType(sv); - buf.append(tab2) - .append("// declaration: ") - .append(sv.getDeclaration()) - .append('\n'); + buf.append(tab2).append("// declaration: ") + .append(sv.getDeclaration()).append('\n'); } text.add(buf.toString()); } @@ -1056,14 +962,13 @@ public class Textifier extends Printer { /** * Prints a disassembled view of the given annotation. * - * @param desc the class descriptor of the annotation class. - * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * <tt>true</tt> if the annotation is visible at runtime. * @return a visitor to visit the annotation values. */ - public Textifier visitAnnotation( - final String desc, - final boolean visible) - { + public Textifier visitAnnotation(final String desc, final boolean visible) { buf.setLength(0); buf.append(tab).append('@'); appendDescriptor(FIELD_DESCRIPTOR, desc); @@ -1078,7 +983,8 @@ public class Textifier extends Printer { /** * Prints a disassembled view of the given attribute. * - * @param attr an attribute. + * @param attr + * an attribute. */ public void visitAttribute(final Attribute attr) { buf.setLength(0); @@ -1111,15 +1017,16 @@ public class Textifier extends Printer { * Appends an internal name, a type descriptor or a type signature to * {@link #buf buf}. * - * @param type indicates if desc is an internal name, a field descriptor, a - * method descriptor, a class signature, ... - * @param desc an internal name, type descriptor, or type signature. May be - * <tt>null</tt>. + * @param type + * indicates if desc is an internal name, a field descriptor, a + * method descriptor, a class signature, ... + * @param desc + * an internal name, type descriptor, or type signature. May be + * <tt>null</tt>. */ protected void appendDescriptor(final int type, final String desc) { if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE - || type == METHOD_SIGNATURE) - { + || type == METHOD_SIGNATURE) { if (desc != null) { buf.append("// signature ").append(desc).append('\n'); } @@ -1132,7 +1039,8 @@ public class Textifier extends Printer { * Appends the name of the given label to {@link #buf buf}. Creates a new * label name if the given label does not yet have one. * - * @param l a label. + * @param l + * a label. */ protected void appendLabel(final Label l) { if (labelNames == null) { @@ -1149,40 +1057,42 @@ public class Textifier extends Printer { /** * Appends the information about the given handle to {@link #buf buf}. * - * @param h a handle, non null. + * @param h + * a handle, non null. */ protected void appendHandle(final Handle h) { buf.append('\n').append(tab3); int tag = h.getTag(); - buf.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : "); + buf.append("// handle kind 0x").append(Integer.toHexString(tag)) + .append(" : "); switch (tag) { - case Opcodes.H_GETFIELD: - buf.append("GETFIELD"); - break; - case Opcodes.H_GETSTATIC: - buf.append("GETSTATIC"); - break; - case Opcodes.H_PUTFIELD: - buf.append("PUTFIELD"); - break; - case Opcodes.H_PUTSTATIC: - buf.append("PUTSTATIC"); - break; - case Opcodes.H_INVOKEINTERFACE: - buf.append("INVOKEINTERFACE"); - break; - case Opcodes.H_INVOKESPECIAL: - buf.append("INVOKESPECIAL"); - break; - case Opcodes.H_INVOKESTATIC: - buf.append("INVOKESTATIC"); - break; - case Opcodes.H_INVOKEVIRTUAL: - buf.append("INVOKEVIRTUAL"); - break; - case Opcodes.H_NEWINVOKESPECIAL: - buf.append("NEWINVOKESPECIAL"); - break; + case Opcodes.H_GETFIELD: + buf.append("GETFIELD"); + break; + case Opcodes.H_GETSTATIC: + buf.append("GETSTATIC"); + break; + case Opcodes.H_PUTFIELD: + buf.append("PUTFIELD"); + break; + case Opcodes.H_PUTSTATIC: + buf.append("PUTSTATIC"); + break; + case Opcodes.H_INVOKEINTERFACE: + buf.append("INVOKEINTERFACE"); + break; + case Opcodes.H_INVOKESPECIAL: + buf.append("INVOKESPECIAL"); + break; + case Opcodes.H_INVOKESTATIC: + buf.append("INVOKESTATIC"); + break; + case Opcodes.H_INVOKEVIRTUAL: + buf.append("INVOKEVIRTUAL"); + break; + case Opcodes.H_NEWINVOKESPECIAL: + buf.append("NEWINVOKESPECIAL"); + break; } buf.append('\n'); buf.append(tab3); @@ -1195,10 +1105,11 @@ public class Textifier extends Printer { } /** - * Appends a string representation of the given access modifiers to {@link - * #buf buf}. + * Appends a string representation of the given access modifiers to + * {@link #buf buf}. * - * @param access some access modifiers. + * @param access + * some access modifiers. */ private void appendAccess(final int access) { if ((access & Opcodes.ACC_PUBLIC) != 0) { @@ -1231,6 +1142,9 @@ public class Textifier extends Printer { if ((access & Opcodes.ACC_STRICT) != 0) { buf.append("strictfp "); } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + buf.append("synthetic "); + } if ((access & Opcodes.ACC_ENUM) != 0) { buf.append("enum "); } @@ -1256,27 +1170,27 @@ public class Textifier extends Printer { } } else if (o[i] instanceof Integer) { switch (((Integer) o[i]).intValue()) { - case 0: - appendDescriptor(FIELD_DESCRIPTOR, "T"); - break; - case 1: - appendDescriptor(FIELD_DESCRIPTOR, "I"); - break; - case 2: - appendDescriptor(FIELD_DESCRIPTOR, "F"); - break; - case 3: - appendDescriptor(FIELD_DESCRIPTOR, "D"); - break; - case 4: - appendDescriptor(FIELD_DESCRIPTOR, "J"); - break; - case 5: - appendDescriptor(FIELD_DESCRIPTOR, "N"); - break; - case 6: - appendDescriptor(FIELD_DESCRIPTOR, "U"); - break; + case 0: + appendDescriptor(FIELD_DESCRIPTOR, "T"); + break; + case 1: + appendDescriptor(FIELD_DESCRIPTOR, "I"); + break; + case 2: + appendDescriptor(FIELD_DESCRIPTOR, "F"); + break; + case 3: + appendDescriptor(FIELD_DESCRIPTOR, "D"); + break; + case 4: + appendDescriptor(FIELD_DESCRIPTOR, "J"); + break; + case 5: + appendDescriptor(FIELD_DESCRIPTOR, "N"); + break; + case 6: + appendDescriptor(FIELD_DESCRIPTOR, "U"); + break; } } else { appendLabel((Label) o[i]); diff --git a/src/asm/scala/tools/asm/util/TraceAnnotationVisitor.java b/src/asm/scala/tools/asm/util/TraceAnnotationVisitor.java index f112609031..33e7cf0b26 100644 --- a/src/asm/scala/tools/asm/util/TraceAnnotationVisitor.java +++ b/src/asm/scala/tools/asm/util/TraceAnnotationVisitor.java @@ -58,33 +58,26 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor { } @Override - public void visitEnum( - final String name, - final String desc, - final String value) - { + public void visitEnum(final String name, final String desc, + final String value) { p.visitEnum(name, desc, value); super.visitEnum(name, desc, value); } @Override - public AnnotationVisitor visitAnnotation( - final String name, - final String desc) - { + public AnnotationVisitor visitAnnotation(final String name, + final String desc) { Printer p = this.p.visitAnnotation(name, desc); - AnnotationVisitor av = this.av == null - ? null - : this.av.visitAnnotation(name, desc); + AnnotationVisitor av = this.av == null ? null : this.av + .visitAnnotation(name, desc); return new TraceAnnotationVisitor(av, p); } @Override public AnnotationVisitor visitArray(final String name) { Printer p = this.p.visitArray(name); - AnnotationVisitor av = this.av == null - ? null - : this.av.visitArray(name); + AnnotationVisitor av = this.av == null ? null : this.av + .visitArray(name); return new TraceAnnotationVisitor(av, p); } diff --git a/src/asm/scala/tools/asm/util/TraceClassVisitor.java b/src/asm/scala/tools/asm/util/TraceClassVisitor.java index bb830b71ce..ff7a017482 100644 --- a/src/asm/scala/tools/asm/util/TraceClassVisitor.java +++ b/src/asm/scala/tools/asm/util/TraceClassVisitor.java @@ -42,30 +42,41 @@ import scala.tools.asm.Opcodes; * A {@link ClassVisitor} that prints the classes it visits with a * {@link Printer}. This class visitor can be used in the middle of a class * visitor chain to trace the class that is visited at a given point in this - * chain. This may be useful for debugging purposes. <p> The trace printed when - * visiting the <tt>Hello</tt> class is the following: <p> <blockquote> - * - * <pre> // class version 49.0 (49) // access flags 0x21 public class Hello { - * + * chain. This may be useful for debugging purposes. + * <p> + * The trace printed when visiting the <tt>Hello</tt> class is the following: + * <p> + * <blockquote> + * + * <pre> + * // class version 49.0 (49) // access flags 0x21 public class Hello { + * * // compiled from: Hello.java - * + * * // access flags 0x1 public <init> ()V ALOAD 0 INVOKESPECIAL * java/lang/Object <init> ()V RETURN MAXSTACK = 1 MAXLOCALS = 1 - * + * * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC * java/lang/System out Ljava/io/PrintStream; LDC "hello" * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN - * MAXSTACK = 2 MAXLOCALS = 1 } </pre> - * - * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote> - * - * <pre> public class Hello { - * - * public static void main(String[] args) { - * System.out.println("hello"); } } </pre> - * + * MAXSTACK = 2 MAXLOCALS = 1 } + * </pre> + * + * </blockquote> where <tt>Hello</tt> is defined by: + * <p> + * <blockquote> + * + * <pre> + * public class Hello { + * + * public static void main(String[] args) { + * System.out.println("hello"); + * } + * } + * </pre> + * * </blockquote> - * + * * @author Eric Bruneton * @author Eugene Kuleshov */ @@ -83,8 +94,9 @@ public final class TraceClassVisitor extends ClassVisitor { /** * Constructs a new {@link TraceClassVisitor}. - * - * @param pw the print writer to be used to print the class. + * + * @param pw + * the print writer to be used to print the class. */ public TraceClassVisitor(final PrintWriter pw) { this(null, pw); @@ -92,10 +104,12 @@ public final class TraceClassVisitor extends ClassVisitor { /** * Constructs a new {@link TraceClassVisitor}. - * - * @param cv the {@link ClassVisitor} to which this visitor delegates calls. - * May be <tt>null</tt>. - * @param pw the print writer to be used to print the class. + * + * @param cv + * the {@link ClassVisitor} to which this visitor delegates + * calls. May be <tt>null</tt>. + * @param pw + * the print writer to be used to print the class. */ public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) { this(cv, new Textifier(), pw); @@ -103,33 +117,28 @@ public final class TraceClassVisitor extends ClassVisitor { /** * Constructs a new {@link TraceClassVisitor}. - * - * @param cv the {@link ClassVisitor} to which this visitor delegates calls. - * May be <tt>null</tt>. - * @param p the object that actually converts visit events into text. - * @param pw the print writer to be used to print the class. May be null if - * you simply want to use the result via - * {@link Printer#getText()}, instead of printing it. + * + * @param cv + * the {@link ClassVisitor} to which this visitor delegates + * calls. May be <tt>null</tt>. + * @param p + * the object that actually converts visit events into text. + * @param pw + * the print writer to be used to print the class. May be null if + * you simply want to use the result via + * {@link Printer#getText()}, instead of printing it. */ - public TraceClassVisitor( - final ClassVisitor cv, - final Printer p, - final PrintWriter pw) - { + public TraceClassVisitor(final ClassVisitor cv, final Printer p, + final PrintWriter pw) { super(Opcodes.ASM4, cv); this.pw = pw; this.p = p; } @Override - public void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces) - { + public void visit(final int version, final int access, final String name, + final String signature, final String superName, + final String[] interfaces) { p.visit(version, access, name, signature, superName, interfaces); super.visit(version, access, name, signature, superName, interfaces); } @@ -141,20 +150,15 @@ public final class TraceClassVisitor extends ClassVisitor { } @Override - public void visitOuterClass( - final String owner, - final String name, - final String desc) - { + public void visitOuterClass(final String owner, final String name, + final String desc) { p.visitOuterClass(owner, name, desc); super.visitOuterClass(owner, name, desc); } @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { Printer p = this.p.visitClassAnnotation(desc, visible); AnnotationVisitor av = cv == null ? null : cv.visitAnnotation(desc, visible); @@ -168,55 +172,28 @@ public final class TraceClassVisitor extends ClassVisitor { } @Override - public void visitInnerClass( - final String name, - final String outerName, - final String innerName, - final int access) - { + public void visitInnerClass(final String name, final String outerName, + final String innerName, final int access) { p.visitInnerClass(name, outerName, innerName, access); super.visitInnerClass(name, outerName, innerName, access); } @Override - public FieldVisitor visitField( - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { - Printer p = this.p.visitField(access, - name, - desc, - signature, - value); - FieldVisitor fv = cv == null ? null : cv.visitField(access, - name, - desc, - signature, - value); + public FieldVisitor visitField(final int access, final String name, + final String desc, final String signature, final Object value) { + Printer p = this.p.visitField(access, name, desc, signature, value); + FieldVisitor fv = cv == null ? null : cv.visitField(access, name, desc, + signature, value); return new TraceFieldVisitor(fv, p); } @Override - public MethodVisitor visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { - Printer p = this.p.visitMethod(access, - name, - desc, - signature, - exceptions); - MethodVisitor mv = cv == null ? null : cv.visitMethod(access, - name, - desc, - signature, + public MethodVisitor visitMethod(final int access, final String name, + final String desc, final String signature, final String[] exceptions) { + Printer p = this.p.visitMethod(access, name, desc, signature, exceptions); + MethodVisitor mv = cv == null ? null : cv.visitMethod(access, name, + desc, signature, exceptions); return new TraceMethodVisitor(mv, p); } diff --git a/src/asm/scala/tools/asm/util/TraceFieldVisitor.java b/src/asm/scala/tools/asm/util/TraceFieldVisitor.java index f537e83be1..9547a70008 100644 --- a/src/asm/scala/tools/asm/util/TraceFieldVisitor.java +++ b/src/asm/scala/tools/asm/util/TraceFieldVisitor.java @@ -37,7 +37,7 @@ import scala.tools.asm.Opcodes; /** * A {@link FieldVisitor} that prints the fields it visits with a * {@link Printer}. - * + * * @author Eric Bruneton */ public final class TraceFieldVisitor extends FieldVisitor { @@ -52,12 +52,10 @@ public final class TraceFieldVisitor extends FieldVisitor { super(Opcodes.ASM4, fv); this.p = p; } - + @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { Printer p = this.p.visitFieldAnnotation(desc, visible); AnnotationVisitor av = fv == null ? null : fv.visitAnnotation(desc, visible); diff --git a/src/asm/scala/tools/asm/util/TraceMethodVisitor.java b/src/asm/scala/tools/asm/util/TraceMethodVisitor.java index 9aabf2079e..9034567c8f 100644 --- a/src/asm/scala/tools/asm/util/TraceMethodVisitor.java +++ b/src/asm/scala/tools/asm/util/TraceMethodVisitor.java @@ -56,10 +56,8 @@ public final class TraceMethodVisitor extends MethodVisitor { } @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { Printer p = this.p.visitMethodAnnotation(desc, visible); AnnotationVisitor av = mv == null ? null : mv.visitAnnotation(desc, visible); @@ -80,17 +78,11 @@ public final class TraceMethodVisitor extends MethodVisitor { } @Override - public AnnotationVisitor visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) - { - Printer p = this.p.visitParameterAnnotation(parameter, - desc, - visible); - AnnotationVisitor av = mv == null - ? null - : mv.visitParameterAnnotation(parameter, desc, visible); + public AnnotationVisitor visitParameterAnnotation(final int parameter, + final String desc, final boolean visible) { + Printer p = this.p.visitParameterAnnotation(parameter, desc, visible); + AnnotationVisitor av = mv == null ? null : mv.visitParameterAnnotation( + parameter, desc, visible); return new TraceAnnotationVisitor(av, p); } @@ -101,13 +93,8 @@ public final class TraceMethodVisitor extends MethodVisitor { } @Override - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) - { + public void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack) { p.visitFrame(type, nLocal, local, nStack, stack); super.visitFrame(type, nLocal, local, nStack, stack); } @@ -137,34 +124,22 @@ public final class TraceMethodVisitor extends MethodVisitor { } @Override - public void visitFieldInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc) { p.visitFieldInsn(opcode, owner, name, desc); super.visitFieldInsn(opcode, owner, name, desc); } @Override - public void visitMethodInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { p.visitMethodInsn(opcode, owner, name, desc); super.visitMethodInsn(opcode, owner, name, desc); } @Override - public void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs) - { + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { p.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); } @@ -194,22 +169,15 @@ public final class TraceMethodVisitor extends MethodVisitor { } @Override - public void visitTableSwitchInsn( - final int min, - final int max, - final Label dflt, - final Label... labels) - { + public void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels) { p.visitTableSwitchInsn(min, max, dflt, labels); super.visitTableSwitchInsn(min, max, dflt, labels); } @Override - public void visitLookupSwitchInsn( - final Label dflt, - final int[] keys, - final Label[] labels) - { + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, + final Label[] labels) { p.visitLookupSwitchInsn(dflt, keys, labels); super.visitLookupSwitchInsn(dflt, keys, labels); } @@ -221,25 +189,16 @@ public final class TraceMethodVisitor extends MethodVisitor { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type) { p.visitTryCatchBlock(start, end, handler, type); super.visitTryCatchBlock(start, end, handler, type); } @Override - public void visitLocalVariable( - final String name, - final String desc, - final String signature, - final Label start, - final Label end, - final int index) - { + public void visitLocalVariable(final String name, final String desc, + final String signature, final Label start, final Label end, + final int index) { p.visitLocalVariable(name, desc, signature, start, end, index); super.visitLocalVariable(name, desc, signature, start, end, index); } diff --git a/src/asm/scala/tools/asm/util/TraceSignatureVisitor.java b/src/asm/scala/tools/asm/util/TraceSignatureVisitor.java index a37b759811..1e23c7ef1a 100644 --- a/src/asm/scala/tools/asm/util/TraceSignatureVisitor.java +++ b/src/asm/scala/tools/asm/util/TraceSignatureVisitor.java @@ -117,8 +117,7 @@ public final class TraceSignatureVisitor extends SignatureVisitor { @Override public SignatureVisitor visitInterface() { - separator = seenInterface ? ", " : isInterface - ? " extends " + separator = seenInterface ? ", " : isInterface ? " extends " : " implements "; seenInterface = true; startType(); @@ -165,34 +164,34 @@ public final class TraceSignatureVisitor extends SignatureVisitor { @Override public void visitBaseType(final char descriptor) { switch (descriptor) { - case 'V': - declaration.append("void"); - break; - case 'B': - declaration.append("byte"); - break; - case 'J': - declaration.append("long"); - break; - case 'Z': - declaration.append("boolean"); - break; - case 'I': - declaration.append("int"); - break; - case 'S': - declaration.append("short"); - break; - case 'C': - declaration.append("char"); - break; - case 'F': - declaration.append("float"); - break; - // case 'D': - default: - declaration.append("double"); - break; + case 'V': + declaration.append("void"); + break; + case 'B': + declaration.append("byte"); + break; + case 'J': + declaration.append("long"); + break; + case 'Z': + declaration.append("boolean"); + break; + case 'I': + declaration.append("int"); + break; + case 'S': + declaration.append("short"); + break; + case 'C': + declaration.append("char"); + break; + case 'F': + declaration.append("float"); + break; + // case 'D': + default: + declaration.append("double"); + break; } endType(); } |