diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java index 9690afe2cf0086fae5e6e3f50a94a649628a31d7..0841a6c97c629cc97ee6e4211c5e1f67c758de8f 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java @@ -70,7 +70,7 @@ public abstract class AnnotationVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4}. + * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. */ protected final int api; @@ -83,8 +83,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} or {@link Opcodes#ASM5}. */ public AnnotationVisitor(final int api) { this(api, null); @@ -93,15 +94,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} or {@link Opcodes#ASM5}. + * @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 && api != Opcodes.ASM5) { throw new IllegalArgumentException(); - }*/ + } this.api = api; this.av = av; } @@ -109,14 +112,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) { @@ -127,9 +133,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) { @@ -140,12 +149,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 - * null if this visitor is not interested in visiting - * this nested annotation. The nested annotation value must be - * fully visited before calling other methods on this annotation + * null if this visitor is not interested in visiting this + * nested annotation. The nested annotation value must be fully + * visited before calling other methods on this annotation * visitor. */ public AnnotationVisitor visitAnnotation(String name, String desc) { @@ -161,10 +172,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 - * null if this visitor is not interested in visiting - * these values. The 'name' parameters passed to the methods of this + * null if this visitor is not interested in visiting these + * values. The 'name' parameters passed to the methods of this * visitor are ignored. All the array values must be visited * before calling other methods on this annotation visitor. */ diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java b/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java index ca72839339213bc971f1591d454f1e7bfccd7d0d..5419615e86c6c0e4ee37c123b64435e536b5159f 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java @@ -119,21 +119,21 @@ final class AnnotationWriter extends AnnotationVisitor { /** * Constructs a new {@link AnnotationWriter}. * - * @param cw the class writer to which this annotation must be added. - * @param named true if values are named, false 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 parent the number of annotation values must - * be stored. + * @param cw + * the class writer to which this annotation must be added. + * @param named + * true if values are named, false 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 parent the number of annotation values must + * be stored. */ - AnnotationWriter( - final ClassWriter cw, - final boolean named, - final ByteVector bv, - final ByteVector parent, - final int offset) - { - super(Opcodes.ASM4); + AnnotationWriter(final ClassWriter cw, final boolean named, + final ByteVector bv, final ByteVector parent, final int offset) { + super(Opcodes.ASM5); this.cw = cw; this.named = named; this.bv = bv; @@ -219,11 +219,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)); @@ -232,10 +229,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)); @@ -288,7 +283,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; @@ -315,15 +311,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(); @@ -348,4 +344,57 @@ final class AnnotationWriter extends AnnotationVisitor { } } } + + /** + * Puts the given type reference and type path into the given bytevector. + * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported. + * + * @param typeRef + * a reference to the annotated type. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param out + * where the type reference and type path must be put. + */ + static void putTarget(int typeRef, TypePath typePath, ByteVector out) { + switch (typeRef >>> 24) { + case 0x00: // CLASS_TYPE_PARAMETER + case 0x01: // METHOD_TYPE_PARAMETER + case 0x16: // METHOD_FORMAL_PARAMETER + out.putShort(typeRef >>> 16); + break; + case 0x13: // FIELD + case 0x14: // METHOD_RETURN + case 0x15: // METHOD_RECEIVER + out.putByte(typeRef >>> 24); + break; + case 0x47: // CAST + case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT + case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT + out.putInt(typeRef); + break; + // case 0x10: // CLASS_EXTENDS + // case 0x11: // CLASS_TYPE_PARAMETER_BOUND + // case 0x12: // METHOD_TYPE_PARAMETER_BOUND + // case 0x17: // THROWS + // case 0x42: // EXCEPTION_PARAMETER + // case 0x43: // INSTANCEOF + // case 0x44: // NEW + // case 0x45: // CONSTRUCTOR_REFERENCE + // case 0x46: // METHOD_REFERENCE + default: + out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8); + break; + } + if (typePath == null) { + out.putByte(0); + } else { + int length = typePath.b[typePath.offset] * 2 + 1; + out.putByteArray(typePath.b, typePath.offset, length); + } + } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/Attribute.java b/src/share/classes/jdk/internal/org/objectweb/asm/Attribute.java index 03817bc7841444792788a7b1090a8c8e6a3686cc..20eb27216cbfe1edd79e3b892d2a7226e9cf26c6 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/Attribute.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Attribute.java @@ -84,7 +84,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; @@ -120,39 +121,39 @@ public class Attribute { } /** - * Reads a {@link #type type} attribute. This method must return a new - * {@link Attribute} object, of type {@link #type type}, corresponding to - * the len bytes starting at the given offset, in the given class - * reader. + * Reads a {@link #type type} attribute. This method must return a + * new {@link Attribute} object, of type {@link #type type}, + * corresponding to the len 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 null 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 null if the + * attribute to be read is not a code attribute. * @return a new {@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); @@ -162,30 +163,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 null if this attribute is not a code - * attributes. - * @param len the length of the bytecode of the method corresponding to this - * code attribute, or null 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 null if this attribute is not a code + * attributes. + * @param len + * the length of the bytecode of the method corresponding to this + * code attribute, or null 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; @@ -210,30 +211,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 null if these attributes are not code - * attributes. - * @param len the length of the bytecode of the method corresponding to - * these code attributes, or null 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 null if these attributes are not code + * attributes. + * @param len + * the length of the bytecode of the method corresponding to + * these code attributes, or null 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) { @@ -248,30 +249,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 null if these attributes are not code - * attributes. - * @param len the length of the bytecode of the method corresponding to - * these code attributes, or null 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 null if these attributes are not code + * attributes. + * @param len + * the length of the bytecode of the method corresponding to + * these code attributes, or null 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/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java b/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java index 6a00f9da48c2b3138a5c612e9d08935ba3fef51c..0d3472bcac12f1939ccfee96c2e78f546a94e993 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java @@ -88,7 +88,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]; @@ -98,7 +99,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) { @@ -115,8 +117,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) { @@ -135,7 +139,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) { @@ -154,8 +159,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) { @@ -175,7 +182,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) { @@ -196,7 +204,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) { @@ -223,7 +232,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) { @@ -288,14 +298,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 null to put len - * 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 null to put len + * 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); } @@ -309,8 +321,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/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java b/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java index 99d8a1092f4b3cca170cb66a1f008f1bca9a7ab7..8cbc2d2c199e777e5aa1f41e8792784741869040 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java @@ -141,9 +141,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; @@ -176,7 +175,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); @@ -185,14 +185,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_8) { throw new IllegalArgumentException(); } // parses the constant pool @@ -205,35 +208,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; } @@ -278,8 +281,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]); } /** @@ -309,7 +311,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]; @@ -321,82 +324,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; @@ -411,77 +395,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)); @@ -490,25 +456,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"); } @@ -549,14 +520,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); @@ -567,1117 +540,1218 @@ 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. 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. - * @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. + * 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. + * @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 - - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - attrName = readUTF8(v, c); + int anns = 0; + int ianns = 0; + int tanns = 0; + int itanns = 0; + int innerClasses = 0; + Attribute attributes = null; + + 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 (ANNOTATIONS + && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + tanns = 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 (ANNOTATIONS + && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + itanns = 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); - } - // calls the visit method - classVisitor.visit(readInt(4), - access, - name, - signature, - superClassName, - implementedItfs); - - // calls the visitSource method - if (!skipDebug && (sourceFile != null || sourceDebug != null)) { + u += 6 + readInt(u + 4); + } + + // 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)); - } - } + // visits the class annotations and type annotations + 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)); + } + } + if (ANNOTATIONS && tanns != 0) { + for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + classVisitor.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && itanns != 0) { + for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + classVisitor.visitTypeAnnotation(context.typeRef, + context.typePath, 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; + int tanns = 0; + int itanns = 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 + && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + tanns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + itanns = 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 and type 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)); + } + } + if (ANNOTATIONS && tanns != 0) { + for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + fv.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && itanns != 0) { + for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + fv.visitTypeAnnotation(context.typeRef, + context.typePath, 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; + context.access = readUnsignedShort(u); + context.name = readUTF8(u + 2, c); + context.desc = readUTF8(u + 4, c); + u += 6; + + // reads the method attributes + int code = 0; + int exception = 0; + String[] exceptions = null; + String signature = null; + int methodParameters = 0; + int anns = 0; + int ianns = 0; + int tanns = 0; + int itanns = 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)) { + context.access |= Opcodes.ACC_DEPRECATED; + } else if (ANNOTATIONS + && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = u + 8; + } else if (ANNOTATIONS + && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + tanns = u + 8; + } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { + dann = u + 8; + } else if ("Synthetic".equals(attrName)) { + context.access |= Opcodes.ACC_SYNTHETIC + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; + } else if (ANNOTATIONS + && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + itanns = u + 8; + } else if (ANNOTATIONS + && "RuntimeVisibleParameterAnnotations".equals(attrName)) { + mpanns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleParameterAnnotations".equals(attrName)) { + impanns = u + 8; + } else if ("MethodParameters".equals(attrName)) { + methodParameters = 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(context.access, + context.name, context.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); + } + } + + // visit the method parameters + if (methodParameters != 0) { + for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) { + mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2)); + } + } + + // 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 && tanns != 0) { + for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + mv.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && itanns != 0) { + for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + mv.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), false)); + } + } + if (ANNOTATIONS && mpanns != 0) { + readParameterAnnotations(mv, context, mpanns, true); + } + if (ANNOTATIONS && impanns != 0) { + readParameterAnnotations(mv, context, impanns, false); + } + + // 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) { + 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 = context.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; - } + // reads the code attributes + int[] tanns = null; // start index of each visible type annotation + int[] itanns = null; // start index of each invisible type annotation + int tann = 0; // current index in tanns array + int itann = 0; // current index in itanns array + int ntoff = -1; // next visible type annotation code offset + int nitoff = -1; // next invisible type annotation code offset + 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; } - } 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); - } - /* - * 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 ("".equals(name)) { - frameLocal[local++] = Opcodes.UNINITIALIZED_THIS; - } else { - frameLocal[local++] = readClass(header + 2, c); - } + } 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; } - 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; - } - } - 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 (ANNOTATIONS + && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + tanns = readTypeAnnotations(mv, context, u + 8, true); + ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 + : readUnsignedShort(tanns[0] + 1); + } else if (ANNOTATIONS + && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + itanns = readTypeAnnotations(mv, context, u + 8, false); + nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 + : readUnsignedShort(itanns[0] + 1); + } 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 || unzip)) { + /* + * 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); + } + } + if (FRAMES && stackMap != 0) { + /* + * 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(s) 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 (!zip || unzip) { + mv.visitFrame(Opcodes.F_NEW, frame.localCount, frame.local, + frame.stackCount, frame.stack); + } else if (frame.offset != -1) { + mv.visitFrame(frame.mode, frame.localDiff, frame.local, + frame.stackCount, frame.stack); + } + if (frameCount > 0) { + stackMap = readFrame(stackMap, zip, unzip, 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; - } - } + 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); + } + if (opcode == Opcodes.INVOKEINTERFACE) { + u += 5; + } else { + u += 3; + } + 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; + } + + // visit the instruction annotations, if any + while (tanns != null && tann < tanns.length && ntoff <= offset) { + if (ntoff == offset) { + int v = readAnnotationTarget(context, tanns[tann]); + readAnnotationValues(v + 2, c, true, + mv.visitInsnAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), true)); + } + ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1 + : readUnsignedShort(tanns[tann] + 1); + } + while (itanns != null && itann < itanns.length && nitoff <= offset) { + if (nitoff == offset) { + int v = readAnnotationTarget(context, itanns[itann]); + readAnnotationValues(v + 2, c, true, + mv.visitInsnAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), false)); + } + nitoff = ++itann >= itanns.length + || readByte(itanns[itann]) < 0x43 ? -1 + : readUnsignedShort(itanns[itann] + 1); + } + } + if (labels[codeLength] != null) { + mv.visitLabel(labels[codeLength]); + } + + // 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(w + 4, c), - readUTF8(w + 6, c), - vsignature, - labels[start], - labels[start + length], - index); - w += 10; } } - // visits the other attributes - while (cattrs != null) { - attr = cattrs.next; - cattrs.next = null; - mv.visitAttribute(cattrs); - cattrs = attr; + mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c), + vsignature, labels[start], labels[start + length], + index); + u += 10; + } + } + + // visits the local variables type annotations + if (tanns != null) { + for (int i = 0; i < tanns.length; ++i) { + if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) { + int v = readAnnotationTarget(context, tanns[i]); + v = readAnnotationValues(v + 2, c, true, + mv.visitLocalVariableAnnotation(context.typeRef, + context.typePath, context.start, + context.end, context.index, readUTF8(v, c), + true)); + } + } + } + if (itanns != null) { + for (int i = 0; i < itanns.length; ++i) { + if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) { + int v = readAnnotationTarget(context, itanns[i]); + v = readAnnotationValues(v + 2, c, true, + mv.visitLocalVariableAnnotation(context.typeRef, + context.typePath, context.start, + context.end, context.index, readUTF8(v, c), + false)); } - // visits the max stack and max locals values - mv.visitMaxs(maxStack, maxLocals); } + } + + // visits the code attributes + while (attributes != null) { + Attribute attr = attributes.next; + attributes.next = null; + mv.visitAttribute(attributes); + attributes = attr; + } - if (mv != null) { - mv.visitEnd(); + // visits the max stack and max locals values + mv.visitMaxs(maxStack, maxLocals); + } + + /** + * Parses a type annotation table to find the labels, and to visit the try + * catch block annotations. + * + * @param u + * the start offset of a type annotation table. + * @param mv + * the method visitor to be used to visit the try catch block + * annotations. + * @param context + * information about the class being parsed. + * @param visible + * if the type annotation table to parse contains runtime visible + * annotations. + * @return the start offset of each type annotation in the parsed table. + */ + private int[] readTypeAnnotations(final MethodVisitor mv, + final Context context, int u, boolean visible) { + char[] c = context.buffer; + int[] offsets = new int[readUnsignedShort(u)]; + u += 2; + for (int i = 0; i < offsets.length; ++i) { + offsets[i] = u; + int target = readInt(u); + switch (target >>> 24) { + case 0x00: // CLASS_TYPE_PARAMETER + case 0x01: // METHOD_TYPE_PARAMETER + case 0x16: // METHOD_FORMAL_PARAMETER + u += 2; + break; + case 0x13: // FIELD + case 0x14: // METHOD_RETURN + case 0x15: // METHOD_RECEIVER + u += 1; + break; + case 0x40: // LOCAL_VARIABLE + case 0x41: // RESOURCE_VARIABLE + for (int j = readUnsignedShort(u + 1); j > 0; --j) { + int start = readUnsignedShort(u + 3); + int length = readUnsignedShort(u + 5); + readLabel(start, context.labels); + readLabel(start + length, context.labels); + u += 6; + } + u += 3; + break; + case 0x47: // CAST + case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT + case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT + u += 4; + break; + // case 0x10: // CLASS_EXTENDS + // case 0x11: // CLASS_TYPE_PARAMETER_BOUND + // case 0x12: // METHOD_TYPE_PARAMETER_BOUND + // case 0x17: // THROWS + // case 0x42: // EXCEPTION_PARAMETER + // case 0x43: // INSTANCEOF + // case 0x44: // NEW + // case 0x45: // CONSTRUCTOR_REFERENCE + // case 0x46: // METHOD_REFERENCE + default: + u += 3; + break; + } + int pathLength = readByte(u); + if ((target >>> 24) == 0x42) { + TypePath path = pathLength == 0 ? null : new TypePath(b, u); + u += 1 + 2 * pathLength; + u = readAnnotationValues(u + 2, c, true, + mv.visitTryCatchAnnotation(target, path, + readUTF8(u, c), visible)); + } else { + u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null); } } + return offsets; + } - // visits the end of the class - classVisitor.visitEnd(); + /** + * Parses the header of a type annotation to extract its target_type and + * target_path (the result is stored in the given context), and returns the + * start offset of the rest of the type_annotation structure (i.e. the + * offset to the type_index field, which is followed by + * num_element_value_pairs and then the name,value pairs). + * + * @param context + * information about the class being parsed. This is where the + * extracted target_type and target_path must be stored. + * @param u + * the start offset of a type_annotation structure. + * @return the start offset of the rest of the type_annotation structure. + */ + private int readAnnotationTarget(final Context context, int u) { + int target = readInt(u); + switch (target >>> 24) { + case 0x00: // CLASS_TYPE_PARAMETER + case 0x01: // METHOD_TYPE_PARAMETER + case 0x16: // METHOD_FORMAL_PARAMETER + target &= 0xFFFF0000; + u += 2; + break; + case 0x13: // FIELD + case 0x14: // METHOD_RETURN + case 0x15: // METHOD_RECEIVER + target &= 0xFF000000; + u += 1; + break; + case 0x40: // LOCAL_VARIABLE + case 0x41: { // RESOURCE_VARIABLE + target &= 0xFF000000; + int n = readUnsignedShort(u + 1); + context.start = new Label[n]; + context.end = new Label[n]; + context.index = new int[n]; + u += 3; + for (int i = 0; i < n; ++i) { + int start = readUnsignedShort(u); + int length = readUnsignedShort(u + 2); + context.start[i] = readLabel(start, context.labels); + context.end[i] = readLabel(start + length, context.labels); + context.index[i] = readUnsignedShort(u + 4); + u += 6; + } + break; + } + case 0x47: // CAST + case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT + case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT + target &= 0xFF0000FF; + u += 4; + break; + // case 0x10: // CLASS_EXTENDS + // case 0x11: // CLASS_TYPE_PARAMETER_BOUND + // case 0x12: // METHOD_TYPE_PARAMETER_BOUND + // case 0x17: // THROWS + // case 0x42: // EXCEPTION_PARAMETER + // case 0x43: // INSTANCEOF + // case 0x44: // NEW + // case 0x45: // CONSTRUCTOR_REFERENCE + // case 0x46: // METHOD_REFERENCE + default: + target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000; + u += 3; + break; + } + int pathLength = readByte(u); + context.typeRef = target; + context.typePath = pathLength == 0 ? null : new TypePath(b, u); + return u + 1 + 2 * pathLength; } /** * 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 true if the annotations to be read are visible - * at runtime. - * @param mv the visitor that must visit the annotations. + * @param mv + * the visitor that must visit the annotations. + * @param context + * information about the class being parsed. + * @param v + * start offset in {@link #b b} of the annotations to be read. + * @param visible + * true if the annotations to be read are visible at + * runtime. */ - private void readParameterAnnotations( - int v, - final String desc, - final char[] buf, - final boolean visible, - final MethodVisitor mv) - { + private void readParameterAnnotations(final MethodVisitor mv, + final Context context, int v, final boolean visible) { int i; int n = b[v++] & 0xFF; // workaround for a bug in javac (javac compiler generates a parameter @@ -1686,7 +1760,7 @@ public class ClassReader { // equal to the number of parameters in the method descriptor - which // includes the synthetic parameters added by the compiler). This work- // around supposes that the synthetic parameters are the first ones. - int synthetics = Type.getArgumentTypes(desc).length - n; + int synthetics = Type.getArgumentTypes(context.desc).length - n; AnnotationVisitor av; for (i = 0; i < synthetics; ++i) { // virtual annotation to detect synthetic parameters in MethodWriter @@ -1695,12 +1769,13 @@ public class ClassReader { av.visitEnd(); } } + char[] c = context.buffer; for (; i < n + synthetics; ++i) { int j = readUnsignedShort(v); v += 2; for (; j > 0; --j) { - av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible); - v = readAnnotationValues(v + 2, buf, true, av); + av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible); + v = readAnnotationValues(v + 2, c, true, av); } } } @@ -1708,21 +1783,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) { @@ -1743,210 +1819,368 @@ 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 (not - * including the value name constant pool index). - * @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 + * (not including the value name constant pool index). + * @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 ("".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 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, + Context frame) { + char[] c = frame.buffer; + Label[] labels = frame.labels; + 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; } @@ -1956,10 +2190,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) { @@ -1969,40 +2205,68 @@ public class ClassReader { return labels[offset]; } + /** + * 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 null 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 null if the + * attribute to be read is not a code attribute. * @return the attribute that has been read, or null 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); @@ -2016,9 +2280,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; @@ -2029,7 +2293,8 @@ public class ClassReader { * one. This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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. */ @@ -2053,7 +2318,8 @@ public class ClassReader { * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * - * @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) { @@ -2061,11 +2327,12 @@ public class ClassReader { } /** - * Reads an unsigned short value in {@link #b b}. This method is - * intended for {@link Attribute} sub classes, and is normally not needed by - * class generators or adapters. + * Reads an unsigned short value in {@link #b b}. This method is intended + * for {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters. * - * @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) { @@ -2078,7 +2345,8 @@ public class ClassReader { * for {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * - * @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) { @@ -2091,7 +2359,8 @@ public class ClassReader { * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * - * @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) { @@ -2101,11 +2370,12 @@ public class ClassReader { } /** - * Reads a signed long value in {@link #b b}. 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}. This method is intended for + * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * - * @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) { @@ -2119,14 +2389,19 @@ public class ClassReader { * is intended for {@link Attribute} sub classes, and is normally not needed * by class generators or adapters. * - * @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; @@ -2138,10 +2413,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) { @@ -2154,28 +2432,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); @@ -2186,10 +2464,12 @@ public class ClassReader { * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters. * - * @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) { @@ -2204,9 +2484,11 @@ public class ClassReader { * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters. * - * @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. @@ -2214,32 +2496,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/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java index 73096fa9e7031b8510e80a00d8d27ccd76c916e5..f95597e2317b5b0815eb8cd92cb932ed3cb5e4ce 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java @@ -59,11 +59,12 @@ package jdk.internal.org.objectweb.asm; /** - * A visitor to visit a Java class. The methods of this class must be called - * in the following order: visit [ visitSource ] [ + * A visitor to visit a Java class. The methods of this class must be called in + * the following order: visit [ visitSource ] [ * visitOuterClass ] ( visitAnnotation | - * visitAttribute )* ( visitInnerClass | - * visitField | visitMethod )* visitEnd. + * visitTypeAnnotation | visitAttribute )* ( + * visitInnerClass | visitField | visitMethod )* + * visitEnd. * * @author Eric Bruneton */ @@ -71,7 +72,7 @@ public abstract class ClassVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4}. + * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. */ protected final int api; @@ -84,8 +85,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} or {@link Opcodes#ASM5}. */ public ClassVisitor(final int api) { this(api, null); @@ -94,15 +96,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} or {@link Opcodes#ASM5}. + * @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 && api != Opcodes.ASM5) { throw new IllegalArgumentException(); - }*/ + } this.api = api; this.cv = cv; } @@ -110,30 +114,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 null 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 null, but - * only for the {@link Object} class. - * @param interfaces the internal names of the class's interfaces (see - * {@link Type#getInternalName() getInternalName}). May be - * null. + * @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 null 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 + * null, but only for the {@link Object} class. + * @param interfaces + * the internal names of the class's interfaces (see + * {@link Type#getInternalName() getInternalName}). May be + * null. */ - 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); } @@ -142,11 +146,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 null. - * @param debug additional debug information to compute the correspondance - * between source and compiled elements of the class. May be - * null. + * @param source + * the name of the source file from which the class was compiled. + * May be null. + * @param debug + * additional debug information to compute the correspondance + * between source and compiled elements of the class. May be + * null. */ public void visitSource(String source, String debug) { if (cv != null) { @@ -158,16 +164,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 - * null 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 - * null 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 + * null 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 + * null 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); } } @@ -175,8 +184,10 @@ public abstract class ClassVisitor { /** * Visits an annotation of the class. * - * @param desc the class descriptor of the annotation class. - * @param visible true if the annotation is visible at runtime. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or null if * this visitor is not interested in visiting this annotation. */ @@ -187,10 +198,44 @@ public abstract class ClassVisitor { return null; } + /** + * Visits an annotation on a type in the class signature. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#CLASS_TYPE_PARAMETER + * CLASS_TYPE_PARAMETER}, + * {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND + * CLASS_TYPE_PARAMETER_BOUND} or + * {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See + * {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (cv != null) { + return cv.visitTypeAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + /** * Visits a non standard attribute of the class. * - * @param attr an attribute. + * @param attr + * an attribute. */ public void visitAttribute(Attribute attr) { if (cv != null) { @@ -202,23 +247,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 null for not member classes. - * @param innerName the (simple) name of the inner class inside its - * enclosing class. May be null 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 null for not member classes. + * @param innerName + * the (simple) name of the inner class inside its enclosing + * class. May be null 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); } @@ -227,33 +271,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 null if the - * field's type does not use generic types. - * @param value the field's initial value. This parameter, which may be - * null 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 int, - * float, long or String fields - * respectively). This parameter is only used for static fields. - * 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 null if the field's + * type does not use generic types. + * @param value + * the field's initial value. This parameter, which may be + * null 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 int, + * float, long or String fields + * respectively). This parameter is only used for static + * fields. 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 - * null if this class visitor is not interested in - * visiting these annotations and attributes. + * null 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); } @@ -262,31 +305,31 @@ public abstract class ClassVisitor { /** * Visits a method of the class. This method must return a new - * {@link MethodVisitor} instance (or null) each time it is - * called, i.e., it should not return a previously returned visitor. + * {@link MethodVisitor} instance (or null) 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 null 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 - * null. + * @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 null 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 + * null. * @return an object to visit the byte code of the method, or null * 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/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java b/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java index 33c98295db07d1ca7d72a39c322ff62fbb70dfe9..d5d8fa48903051189ada486b94ccdabf7cf0f422 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java @@ -95,11 +95,17 @@ 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. */ @@ -267,8 +273,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; @@ -295,9 +301,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; @@ -356,10 +361,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 i - * the Item whose index is i. 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 i. 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; @@ -440,6 +445,16 @@ public class ClassWriter extends ClassVisitor { */ private AnnotationWriter ianns; + /** + * The runtime visible type annotations of this class. + */ + private AnnotationWriter tanns; + + /** + * The runtime invisible type annotations of this class. + */ + private AnnotationWriter itanns; + /** * The non standard attributes of this class. */ @@ -468,16 +483,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; @@ -492,8 +507,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; @@ -613,11 +628,13 @@ 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); + super(Opcodes.ASM5); index = 1; pool = new ByteVector(); items = new Item[256]; @@ -635,26 +652,32 @@ public class ClassWriter extends ClassVisitor { * "mostly add" bytecode transformations. These optimizations are the * following: * - * + * * - * @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. 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. 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. 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. See {@link #COMPUTE_MAXS}, + * {@link #COMPUTE_FRAMES}. */ public ClassWriter(final ClassReader classReader, final int flags) { this(flags); @@ -667,14 +690,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); @@ -703,11 +721,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); @@ -715,10 +730,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; } @@ -736,6 +749,29 @@ public class ClassWriter extends ClassVisitor { return aw; } + @Override + public final AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, final String desc, final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = tanns; + tanns = aw; + } else { + aw.next = itanns; + itanns = aw; + } + return aw; + } + @Override public final void visitAttribute(final Attribute attr) { attr.next = attrs; @@ -743,12 +779,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(); } @@ -760,32 +792,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 @@ -802,7 +818,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 @@ -822,8 +838,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"); @@ -853,12 +870,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; @@ -875,6 +893,16 @@ public class ClassWriter extends ClassVisitor { size += 8 + ianns.getSize(); newUTF8("RuntimeInvisibleAnnotations"); } + if (ClassReader.ANNOTATIONS && tanns != null) { + ++attributeCount; + size += 8 + tanns.getSize(); + newUTF8("RuntimeVisibleTypeAnnotations"); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + ++attributeCount; + size += 8 + itanns.getSize(); + newUTF8("RuntimeInvisibleTypeAnnotations"); + } if (attrs != null) { attributeCount += attrs.getCount(); size += attrs.getSize(this, null, 0, -1, -1); @@ -885,9 +913,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) { @@ -906,9 +933,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) { @@ -929,10 +957,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")); @@ -947,6 +976,14 @@ public class ClassWriter extends ClassVisitor { out.putShort(newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } + if (ClassReader.ANNOTATIONS && tanns != null) { + out.putShort(newUTF8("RuntimeVisibleTypeAnnotations")); + tanns.put(out); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations")); + itanns.put(out); + } if (attrs != null) { attrs.put(this, null, 0, -1, -1, out); } @@ -966,10 +1003,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) { @@ -1002,12 +1040,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; @@ -1023,9 +1061,10 @@ public class ClassWriter extends ClassVisitor { * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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. */ @@ -1039,7 +1078,8 @@ public class ClassWriter extends ClassVisitor { * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters. * - * @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) { @@ -1059,7 +1099,8 @@ public class ClassWriter extends ClassVisitor { * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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) { @@ -1079,7 +1120,8 @@ public class ClassWriter extends ClassVisitor { * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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) { @@ -1092,7 +1134,8 @@ public class ClassWriter extends ClassVisitor { * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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) { @@ -1112,7 +1155,8 @@ public class ClassWriter extends ClassVisitor { * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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. */ @@ -1126,33 +1170,34 @@ public class ClassWriter extends ClassVisitor { * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters. * - * @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); @@ -1161,29 +1206,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. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. + * Adds a handle to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters. * - * @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; } @@ -1193,19 +1239,19 @@ public class ClassWriter extends ClassVisitor { * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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) { @@ -1215,9 +1261,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; @@ -1279,20 +1323,20 @@ public class ClassWriter extends ClassVisitor { * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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; } @@ -1300,13 +1344,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) { @@ -1323,13 +1369,15 @@ public class ClassWriter extends ClassVisitor { * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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; } @@ -1337,18 +1385,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 true if owner 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 + * true if owner 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); @@ -1366,18 +1414,18 @@ public class ClassWriter extends ClassVisitor { * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * - * @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 true if owner 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 + * true if owner 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; } @@ -1385,7 +1433,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) { @@ -1403,7 +1452,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) { @@ -1421,7 +1471,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) { @@ -1440,7 +1491,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) { @@ -1459,7 +1511,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) { @@ -1479,8 +1532,10 @@ public class ClassWriter extends ClassVisitor { * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters. * - * @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) { @@ -1491,8 +1546,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) { @@ -1510,7 +1567,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) { @@ -1527,9 +1585,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) { @@ -1547,7 +1607,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. */ @@ -1573,8 +1634,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) { @@ -1594,20 +1657,21 @@ public class ClassWriter extends ClassVisitor { /** * Returns the common super type of the two given types. The default - * implementation of this method loads the two given classes and uses + * implementation of this method loads the two given classes and uses * the java.lang.Class methods to find the common super class. It can be * overridden to compute this common super type in other ways, in particular * without actually loading any class, or to take into account the class * 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 { @@ -1636,7 +1700,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 null if there is no such item. */ @@ -1652,7 +1717,8 @@ public class ClassWriter extends ClassVisitor { * Puts the given item in the constant pool's hash table. The hash table * must 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) { @@ -1680,9 +1746,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); @@ -1691,9 +1760,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/share/classes/jdk/internal/org/objectweb/asm/Context.java b/src/share/classes/jdk/internal/org/objectweb/asm/Context.java new file mode 100644 index 0000000000000000000000000000000000000000..e515e575a35d156da3198ab6c0aee4dad9bf41ec --- /dev/null +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Context.java @@ -0,0 +1,174 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * 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 jdk.internal.org.objectweb.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 label objects, indexed by bytecode offset, of the method currently + * being parsed (only bytecode offsets for which a label is needed have a + * non null associated Label object). + */ + Label[] labels; + + /** + * The target of the type annotation currently being parsed. + */ + int typeRef; + + /** + * The path of the type annotation currently being parsed. + */ + TypePath typePath; + + /** + * The offset of the latest stack map frame that has been parsed. + */ + int offset; + + /** + * The labels corresponding to the start of the local variable ranges in the + * local variable type annotation currently being parsed. + */ + Label[] start; + + /** + * The labels corresponding to the end of the local variable ranges in the + * local variable type annotation currently being parsed. + */ + Label[] end; + + /** + * The local variable indices for each local variable range in the local + * variable type annotation currently being parsed. + */ + int[] index; + + /** + * 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/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java index 116be9fe7af66a84d0fa9bea7fe26f1cbb846395..7f16c4e70b3de823c7e5c8080a16fbd57ee85e52 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java @@ -59,9 +59,9 @@ package jdk.internal.org.objectweb.asm; /** - * A visitor to visit a Java field. The methods of this class must be called - * in the following order: ( visitAnnotation | - * visitAttribute )* visitEnd. + * A visitor to visit a Java field. The methods of this class must be called in + * the following order: ( visitAnnotation | + * visitTypeAnnotation | visitAttribute )* visitEnd. * * @author Eric Bruneton */ @@ -69,7 +69,7 @@ public abstract class FieldVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4}. + * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. */ protected final int api; @@ -82,8 +82,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} or {@link Opcodes#ASM5}. */ public FieldVisitor(final int api) { this(api, null); @@ -92,15 +93,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} or {@link Opcodes#ASM5}. + * @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 && api != Opcodes.ASM5) { throw new IllegalArgumentException(); - }*/ + } this.api = api; this.fv = fv; } @@ -108,8 +111,10 @@ public abstract class FieldVisitor { /** * Visits an annotation of the field. * - * @param desc the class descriptor of the annotation class. - * @param visible true if the annotation is visible at runtime. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or null if * this visitor is not interested in visiting this annotation. */ @@ -120,10 +125,40 @@ public abstract class FieldVisitor { return null; } + /** + * Visits an annotation on the type of the field. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#FIELD FIELD}. See + * {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (fv != null) { + return fv.visitTypeAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + /** * 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/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java b/src/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java index 53d3fa2866f2e4554089aad3e01ea2f186b26886..b30eeacb25244250969e604b3ebd204af5779757 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java @@ -109,6 +109,17 @@ final class FieldWriter extends FieldVisitor { */ private AnnotationWriter ianns; + /** + * The runtime visible type annotations of this field. May be null. + */ + private AnnotationWriter tanns; + + /** + * The runtime invisible type annotations of this field. May be + * null. + */ + private AnnotationWriter itanns; + /** * The non standard attributes of this field. May be null. */ @@ -121,22 +132,22 @@ 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 null. - * @param value the field's constant value. May be null. + * @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 null. + * @param value + * the field's constant value. May be null. */ - FieldWriter( - final ClassWriter cw, - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { - super(Opcodes.ASM4); + FieldWriter(final ClassWriter cw, final int access, final String name, + final String desc, final String signature, final Object value) { + super(Opcodes.ASM5); if (cw.firstField == null) { cw.firstField = this; } else { @@ -160,10 +171,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; } @@ -181,6 +190,29 @@ final class FieldWriter extends FieldVisitor { return aw; } + @Override + public AnnotationVisitor visitTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = tanns; + tanns = aw; + } else { + aw.next = itanns; + itanns = aw; + } + return aw; + } + @Override public void visitAttribute(final Attribute attr) { attr.next = attrs; @@ -206,11 +238,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"); @@ -228,6 +261,14 @@ final class FieldWriter extends FieldVisitor { cw.newUTF8("RuntimeInvisibleAnnotations"); size += 8 + ianns.getSize(); } + if (ClassReader.ANNOTATIONS && tanns != null) { + cw.newUTF8("RuntimeVisibleTypeAnnotations"); + size += 8 + tanns.getSize(); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + cw.newUTF8("RuntimeInvisibleTypeAnnotations"); + size += 8 + itanns.getSize(); + } if (attrs != null) { size += attrs.getSize(cw, null, 0, -1, -1); } @@ -237,21 +278,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; @@ -265,6 +308,12 @@ final class FieldWriter extends FieldVisitor { if (ClassReader.ANNOTATIONS && ianns != null) { ++attributeCount; } + if (ClassReader.ANNOTATIONS && tanns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && itanns != null) { + ++attributeCount; + } if (attrs != null) { attributeCount += attrs.getCount(); } @@ -273,10 +322,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); @@ -293,6 +343,14 @@ final class FieldWriter extends FieldVisitor { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } + if (ClassReader.ANNOTATIONS && tanns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); + tanns.put(out); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); + itanns.put(out); + } if (attrs != null) { attrs.put(cw, null, 0, -1, -1, out); } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java b/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java index 48e331d35f53b4f1a9135e9fa12b909655baf919..20a94b275eb34b635a7bbaec1735233dc1cfffdf 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java @@ -109,13 +109,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). */ /** @@ -146,9 +146,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; @@ -552,7 +552,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) { @@ -574,8 +575,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 @@ -595,7 +598,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 @@ -620,10 +624,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); @@ -638,72 +644,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; } } @@ -724,7 +732,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) { @@ -741,9 +750,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); @@ -760,7 +770,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 @@ -781,8 +792,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. */ @@ -816,17 +829,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; @@ -852,435 +865,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; } } @@ -1289,10 +1302,13 @@ final class Frame { * frames of this basic block. Returns true 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 true if the input frame of the given label has been * changed by this operation. */ @@ -1323,7 +1339,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; } } @@ -1375,7 +1392,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; } } @@ -1392,19 +1410,19 @@ final class Frame { * type. Returns true 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 true 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/share/classes/jdk/internal/org/objectweb/asm/Handle.java b/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java index a70e3859b8006e27f025c452d2914222dcccbf1c..f262f9a09a00b6e54ef86c4331fecb2617559c38 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java @@ -95,18 +95,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; @@ -130,11 +135,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; @@ -167,8 +170,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 @@ -178,8 +181,13 @@ public final class Handle { /** * Returns the textual representation of this handle. The textual - * representation is:
owner '.' name desc ' ' '(' tag ')'
. As - * this format is unambiguous, it can be parsed if necessary. + * representation is: + * + *
+     * owner '.' name desc ' ' '(' tag ')'
+     * 
+ * + * . As this format is unambiguous, it can be parsed if necessary. */ @Override public String toString() { diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/Handler.java b/src/share/classes/jdk/internal/org/objectweb/asm/Handler.java index 72211a3a93f70f853c5559490cce5daa4d0d1f1b..72a30b2bcf4b29ef6b2de38b3c6701b16319cf1e 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/Handler.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Handler.java @@ -101,9 +101,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/share/classes/jdk/internal/org/objectweb/asm/Item.java b/src/share/classes/jdk/internal/org/objectweb/asm/Item.java index 97b56f766c6d5d5fc328b5a13bf42c489a088f14..90ff74377ff570c56fd41ba1765fda5fe8a63d36 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/Item.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Item.java @@ -82,8 +82,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 @@ -144,7 +144,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; @@ -153,8 +154,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; @@ -170,7 +173,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; @@ -181,7 +185,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; @@ -192,7 +197,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; @@ -203,7 +209,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; @@ -214,49 +221,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; @@ -270,10 +281,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; @@ -285,41 +298,42 @@ final class Item { * Indicates if the given item is equal to this one. This method assumes * that the two items have the same {@link #type}. * - * @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 true if the given item if equal to this one, * false 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/share/classes/jdk/internal/org/objectweb/asm/Label.java b/src/share/classes/jdk/internal/org/objectweb/asm/Label.java index 220a6e38bd3bb986858cf7c7eb994ebb7f781a73..f4bc30df4bd5cf747b3dafc6e350e5741879f986 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/Label.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Label.java @@ -61,9 +61,9 @@ package jdk.internal.org.objectweb.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 instruction 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 instruction 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 */ @@ -139,8 +139,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 - * jdk.internal.org.objectweb.asm.tree.MethodNode#getLabelNode} method. + * package you must override the + * {@link jdk.internal.org.objectweb.asm.tree.MethodNode#getLabelNode} method. */ public Object info; @@ -183,7 +183,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. */ @@ -206,11 +206,11 @@ public class Label { * state of the local variables and the operand stack at the end of each * basic block, called the "output frame", relatively to the frame * state at the beginning of the basic block, which is called the "input - * frame", and which is unknown 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 unknown 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 @@ -295,11 +295,13 @@ public class Label { * generators or adapters.
* * @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; } @@ -310,21 +312,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 true if the reference must be stored in 4 - * bytes, or false 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 + * true if the reference must be stored in 4 bytes, or + * false 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); @@ -348,25 +350,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; } @@ -380,9 +378,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 true 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 @@ -390,14 +391,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; @@ -460,7 +459,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) { @@ -474,7 +474,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. */ @@ -493,8 +494,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) { @@ -510,14 +513,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/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java index 241f4fb89f9209f941337d624b40e345a8b364ec..f21519e962c9d76d3ee987a12d7afda474625654 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java @@ -59,19 +59,25 @@ package jdk.internal.org.objectweb.asm; /** - * A visitor to visit a Java method. The methods of this class must be - * called in the following order: [ visitAnnotationDefault ] ( - * visitAnnotation | visitParameterAnnotation | - * visitAttribute )* [ visitCode ( visitFrame | - * visitXInsn
| visitLabel | visitTryCatchBlock | - * visitLocalVariable | visitLineNumber )* visitMaxs ] - * visitEnd. In addition, the visitXInsn
- * and visitLabel methods must be called in the sequential order of - * the bytecode instructions of the visited code, visitTryCatchBlock - * must be called before the labels passed as arguments have been - * visited, and the visitLocalVariable and visitLineNumber - * methods must be called after the labels passed as arguments have been - * visited. + * A visitor to visit a Java method. The methods of this class must be called in + * the following order: ( visitParameter )* [ + * visitAnnotationDefault ] ( visitAnnotation | + * visitTypeAnnotation | visitAttribute )* [ + * visitCode ( visitFrame | visitXInsn | + * visitLabel | visitInsnAnnotation | + * visitTryCatchBlock | visitTryCatchBlockAnnotation | + * visitLocalVariable | visitLocalVariableAnnotation | + * visitLineNumber )* visitMaxs ] visitEnd. In + * addition, the visitXInsn and visitLabel + * methods must be called in the sequential order of the bytecode instructions + * of the visited code, visitInsnAnnotation must be called after + * the annotated instruction, visitTryCatchBlock must be called + * before the labels passed as arguments have been visited, + * visitTryCatchBlockAnnotation must be called after the + * corresponding try catch block has been visited, and the + * visitLocalVariable, visitLocalVariableAnnotation and + * visitLineNumber methods must be called after the labels + * passed as arguments have been visited. * * @author Eric Bruneton */ @@ -79,7 +85,7 @@ public abstract class MethodVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4}. + * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. */ protected final int api; @@ -92,8 +98,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} or {@link Opcodes#ASM5}. */ public MethodVisitor(final int api) { this(api, null); @@ -102,29 +109,50 @@ 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} or {@link Opcodes#ASM5}. + * @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 && api != Opcodes.ASM5) { throw new IllegalArgumentException(); - }*/ + } this.api = api; this.mv = mv; } // ------------------------------------------------------------------------- - // Annotations and non standard attributes + // Parameters, annotations and non standard attributes // ------------------------------------------------------------------------- + /** + * Visits a parameter of this method. + * + * @param name + * parameter name or null if none is provided. + * @param access + * the parameter's access flags, only ACC_FINAL, + * ACC_SYNTHETIC or/and ACC_MANDATED are + * allowed (see {@link Opcodes}). + */ + public void visitParameter(String name, int access) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + mv.visitParameter(name, access); + } + } + /** * 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 null if this visitor - * is not interested in visiting this default value. The 'name' + * annotation interface method, or null 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. @@ -139,8 +167,10 @@ public abstract class MethodVisitor { /** * Visits an annotation of this method. * - * @param desc the class descriptor of the annotation class. - * @param visible true if the annotation is visible at runtime. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or null if * this visitor is not interested in visiting this annotation. */ @@ -151,20 +181,56 @@ public abstract class MethodVisitor { return null; } + /** + * Visits an annotation on a type in the method signature. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#METHOD_TYPE_PARAMETER + * METHOD_TYPE_PARAMETER}, + * {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND + * METHOD_TYPE_PARAMETER_BOUND}, + * {@link TypeReference#METHOD_RETURN METHOD_RETURN}, + * {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER}, + * {@link TypeReference#METHOD_FORMAL_PARAMETER + * METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS + * THROWS}. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + return mv.visitTypeAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + /** * Visits an annotation of a parameter this method. * - * @param parameter the parameter index. - * @param desc the class descriptor of the annotation class. - * @param visible true if the annotation is visible at runtime. + * @param parameter + * the parameter index. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or null 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); } @@ -174,7 +240,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) { @@ -198,57 +265,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 just - * before i is executed.

(*) this is mandatory only - * for classes whose version is greater than or equal to - * {@link Opcodes#V1_6 V1_6}.

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):
* - * @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) - { + * @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) { if (mv != null) { mv.visitFrame(type, nLocal, local, nStack, stack); } @@ -261,20 +345,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) { @@ -285,17 +371,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.
When - * opcode is BIPUSH, operand value should be between Byte.MIN_VALUE - * and Byte.MAX_VALUE.
When opcode is SIPUSH, operand value - * should be between Short.MIN_VALUE and Short.MAX_VALUE.
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.
+ * When opcode is BIPUSH, operand value should be between + * Byte.MIN_VALUE and Byte.MAX_VALUE.
+ * When opcode is SIPUSH, operand value should be between + * Short.MIN_VALUE and Short.MAX_VALUE.
+ * 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) { @@ -307,11 +396,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) { @@ -323,11 +414,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) { @@ -339,14 +432,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}). - */ - public void visitFieldInsn(int opcode, String owner, String name, String desc) { + * @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) { if (mv != null) { mv.visitFieldInsn(opcode, owner, name, desc); } @@ -356,15 +454,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}). - */ - public void visitMethodInsn(int opcode, String owner, String name, String desc) { + * @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) { if (mv != null) { mv.visitMethodInsn(opcode, owner, name, desc); } @@ -373,16 +476,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. - */ - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { + * @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) { if (mv != null) { mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); } @@ -392,13 +500,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) { @@ -410,7 +520,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) { @@ -427,41 +538,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: + * *
      * 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
-     * }
+ * // throw an exception + * } + * * - * @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 .class 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 .class 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) { @@ -472,8 +586,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) { @@ -484,13 +600,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. labels[i] is - * the beginning of the handler block for the min + i 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. labels[i] is the + * beginning of the handler block for the min + i 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); } @@ -499,10 +620,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. labels[i] is - * the beginning of the handler block for the keys[i] key. + * @param dflt + * beginning of the default handler block. + * @param keys + * the values of the keys. + * @param labels + * beginnings of the handler blocks. labels[i] is the + * beginning of the handler block for the keys[i] key. */ public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { if (mv != null) { @@ -513,8 +637,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) { @@ -522,6 +648,48 @@ public abstract class MethodVisitor { } } + /** + * Visits an annotation on an instruction. This method must be called just + * after the annotated instruction. It can be called several times + * for the same instruction. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#INSTANCEOF INSTANCEOF}, + * {@link TypeReference#NEW NEW}, + * {@link TypeReference#CONSTRUCTOR_REFERENCE + * CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE + * METHOD_REFERENCE}, {@link TypeReference#CAST CAST}, + * {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT + * METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT + * METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitInsnAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + return mv.visitInsnAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + // ------------------------------------------------------------------------- // Exceptions table entries, debug information, max stack and max locals // ------------------------------------------------------------------------- @@ -529,61 +697,142 @@ 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 null 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) { + * @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 null 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) { if (mv != null) { mv.visitTryCatchBlock(start, end, handler, type); } } + /** + * Visits an annotation on an exception handler type. This method must be + * called after the {@link #visitTryCatchBlock} for the annotated + * exception handler. It can be called several times for the same exception + * handler. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#EXCEPTION_PARAMETER + * EXCEPTION_PARAMETER}. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitTryCatchAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + /** * 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 - * null 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) - { + * @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 + * null 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) { if (mv != null) { mv.visitLocalVariable(name, desc, signature, start, end, index); } } + /** + * Visits an annotation on a local variable type. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#LOCAL_VARIABLE + * LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE + * RESOURCE_VARIABLE}. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param start + * the fist instructions corresponding to the continuous ranges + * that make the scope of this local variable (inclusive). + * @param end + * the last instructions corresponding to the continuous ranges + * that make the scope of this local variable (exclusive). This + * array must have the same size as the 'start' array. + * @param index + * the local variable's index in each range. This array must have + * the same size as the 'start' array. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, + TypePath typePath, Label[] start, Label[] end, int[] index, + String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + return mv.visitLocalVariableAnnotation(typeRef, typePath, start, + end, index, desc, visible); + } + return null; + } + /** * 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 start 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 start has not already been visited by this + * visitor (by the {@link #visitLabel visitLabel} method). */ public void visitLineNumber(int line, Label start) { if (mv != null) { @@ -595,8 +844,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/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java b/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java index e43ecb1d072501e4abc93b26659c24b8269e4892..f59abfa7a3af9002c7b633eeacea9f968839bf43 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java @@ -220,6 +220,18 @@ class MethodWriter extends MethodVisitor { */ private AnnotationWriter ianns; + /** + * The runtime visible type annotations of this method. May be null + * . + */ + private AnnotationWriter tanns; + + /** + * The runtime invisible type annotations of this method. May be + * null. + */ + private AnnotationWriter itanns; + /** * The runtime visible parameter annotations of this method. May be * null. @@ -258,7 +270,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; @@ -316,6 +328,16 @@ class MethodWriter extends MethodVisitor { */ private Handler lastHandler; + /** + * Number of entries in the MethodParameters attribute. + */ + private int methodParametersCount; + + /** + * The MethodParameters attribute. + */ + private ByteVector methodParameters; + /** * Number of entries in the LocalVariableTable attribute. */ @@ -346,6 +368,21 @@ class MethodWriter extends MethodVisitor { */ private ByteVector lineNumber; + /** + * The start offset of the last visited instruction. + */ + private int lastCodeOffset; + + /** + * The runtime visible type annotations of the code. May be null. + */ + private AnnotationWriter ctanns; + + /** + * The runtime invisible type annotations of the code. May be null. + */ + private AnnotationWriter ictanns; + /** * The non standard attributes of the method's code. */ @@ -386,7 +423,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; @@ -425,29 +463,31 @@ 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 null. - * @param exceptions the internal names of the method's exceptions. May be - * null. - * @param computeMaxs true if the maximum stack size and number - * of local variables must be automatically computed. - * @param computeFrames true 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); + * @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 null. + * @param exceptions + * the internal names of the method's exceptions. May be + * null. + * @param computeMaxs + * true if the maximum stack size and number of local + * variables must be automatically computed. + * @param computeFrames + * true 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.ASM5); if (cw.firstMethod == null) { cw.firstMethod = this; } else { @@ -492,6 +532,16 @@ class MethodWriter extends MethodVisitor { // Implementation of the MethodVisitor abstract class // ------------------------------------------------------------------------ + @Override + public void visitParameter(String name, int access) { + if (methodParameters == null) { + methodParameters = new ByteVector(); + } + ++methodParametersCount; + methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name)) + .putShort(access); + } + @Override public AnnotationVisitor visitAnnotationDefault() { if (!ClassReader.ANNOTATIONS) { @@ -502,10 +552,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; } @@ -524,11 +572,31 @@ class MethodWriter extends MethodVisitor { } @Override - public AnnotationVisitor visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) - { + public AnnotationVisitor visitTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = tanns; + tanns = aw; + } else { + aw.next = itanns; + itanns = aw; + } + return aw; + } + + @Override + public AnnotationVisitor visitParameterAnnotation(final int parameter, + final String desc, final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } @@ -574,13 +642,8 @@ 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; } @@ -630,48 +693,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; @@ -684,6 +743,7 @@ class MethodWriter extends MethodVisitor { @Override public void visitInsn(final int opcode) { + lastCodeOffset = code.length; // adds the instruction to the bytecode of the method code.putByte(opcode); // update currentBlock @@ -701,8 +761,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(); } } @@ -710,6 +769,7 @@ class MethodWriter extends MethodVisitor { @Override public void visitIntInsn(final int opcode, final int operand) { + lastCodeOffset = code.length; // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { @@ -734,6 +794,7 @@ class MethodWriter extends MethodVisitor { @Override public void visitVarInsn(final int opcode, final int var) { + lastCodeOffset = code.length; // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { @@ -760,8 +821,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; @@ -793,6 +853,7 @@ class MethodWriter extends MethodVisitor { @Override public void visitTypeInsn(final int opcode, final String type) { + lastCodeOffset = code.length; Item i = cw.newClassItem(type); // Label currentBlock = this.currentBlock; if (currentBlock != null) { @@ -813,12 +874,9 @@ 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) { + lastCodeOffset = code.length; Item i = cw.newFieldItem(owner, name, desc); // Label currentBlock = this.currentBlock; if (currentBlock != null) { @@ -829,19 +887,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) { @@ -855,12 +913,9 @@ 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) { + lastCodeOffset = code.length; boolean itf = opcode == Opcodes.INVOKEINTERFACE; Item i = cw.newMethodItem(owner, name, desc, itf); int argSize = i.intVal; @@ -911,12 +966,9 @@ 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) { + lastCodeOffset = code.length; Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs); int argSize = i.intVal; // Label currentBlock = this.currentBlock; @@ -956,6 +1008,7 @@ class MethodWriter extends MethodVisitor { @Override public void visitJumpInsn(final int opcode, final Label label) { + lastCodeOffset = code.length; Label nextInsn = null; // Label currentBlock = this.currentBlock; if (currentBlock != null) { @@ -996,8 +1049,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 @@ -1015,8 +1067,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 @@ -1103,6 +1154,7 @@ class MethodWriter extends MethodVisitor { @Override public void visitLdcInsn(final Object cst) { + lastCodeOffset = code.length; Item i = cw.newConstItem(cst); // Label currentBlock = this.currentBlock; if (currentBlock != null) { @@ -1111,8 +1163,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; @@ -1137,6 +1188,7 @@ class MethodWriter extends MethodVisitor { @Override public void visitIincInsn(final int var, final int increment) { + lastCodeOffset = code.length; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(Opcodes.IINC, var, null, null); @@ -1151,8 +1203,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); @@ -1160,12 +1211,9 @@ 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) { + lastCodeOffset = code.length; // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.TABLESWITCH); @@ -1180,11 +1228,9 @@ 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) { + lastCodeOffset = code.length; // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.LOOKUPSWITCH); @@ -1227,6 +1273,7 @@ class MethodWriter extends MethodVisitor { @Override public void visitMultiANewArrayInsn(final String desc, final int dims) { + lastCodeOffset = code.length; Item i = cw.newClassItem(desc); // Label currentBlock = this.currentBlock; if (currentBlock != null) { @@ -1243,12 +1290,32 @@ class MethodWriter extends MethodVisitor { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public AnnotationVisitor visitInsnAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8); + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = ctanns; + ctanns = aw; + } else { + aw.next = ictanns; + ictanns = aw; + } + return aw; + } + + @Override + public void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type) { ++handlerCount; Handler h = new Handler(); h.start = start; @@ -1265,14 +1332,32 @@ 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 AnnotationVisitor visitTryCatchAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = ctanns; + ctanns = aw; + } else { + aw.next = ictanns; + ictanns = aw; + } + return aw; + } + + @Override + 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(); @@ -1280,8 +1365,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) { @@ -1290,8 +1374,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 @@ -1303,6 +1386,41 @@ class MethodWriter extends MethodVisitor { } } + @Override + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, + TypePath typePath, Label[] start, Label[] end, int[] index, + String desc, boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + bv.putByte(typeRef >>> 24).putShort(start.length); + for (int i = 0; i < start.length; ++i) { + bv.putShort(start[i].position) + .putShort(end[i].position - start[i].position) + .putShort(index[i]); + } + if (typePath == null) { + bv.putByte(0); + } else { + int length = typePath.b[typePath.offset] * 2 + 1; + bv.putByteArray(typePath.b, typePath.offset, length); + } + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = ctanns; + ctanns = aw; + } else { + aw.next = ictanns; + ictanns = aw; + } + return aw; + } + @Override public void visitLineNumber(final int line, final Label start) { if (lineNumber == null) { @@ -1323,8 +1441,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 @@ -1415,7 +1532,8 @@ class MethodWriter extends MethodVisitor { 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); } } @@ -1564,8 +1682,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... @@ -1602,7 +1722,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; @@ -1656,13 +1777,14 @@ class MethodWriter extends MethodVisitor { /** * 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. + */ + private void 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]; @@ -1715,24 +1837,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) { @@ -1747,36 +1868,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); } } @@ -1786,8 +1905,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) { @@ -1796,15 +1917,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(); @@ -1818,29 +1939,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())); @@ -1903,11 +2024,16 @@ class MethodWriter extends MethodVisitor { cw.newUTF8(zip ? "StackMapTable" : "StackMap"); size += 8 + stackMap.length; } + if (ClassReader.ANNOTATIONS && ctanns != null) { + cw.newUTF8("RuntimeVisibleTypeAnnotations"); + size += 8 + ctanns.getSize(); + } + if (ClassReader.ANNOTATIONS && ictanns != null) { + cw.newUTF8("RuntimeInvisibleTypeAnnotations"); + size += 8 + ictanns.getSize(); + } if (cattrs != null) { - size += cattrs.getSize(cw, - code.data, - code.length, - maxStack, + size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals); } } @@ -1915,11 +2041,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"); @@ -1930,6 +2057,10 @@ class MethodWriter extends MethodVisitor { cw.newUTF8(signature); size += 8; } + if (methodParameters != null) { + cw.newUTF8("MethodParameters"); + size += 7 + methodParameters.length; + } if (ClassReader.ANNOTATIONS && annd != null) { cw.newUTF8("AnnotationDefault"); size += 6 + annd.length; @@ -1942,6 +2073,14 @@ class MethodWriter extends MethodVisitor { cw.newUTF8("RuntimeInvisibleAnnotations"); size += 8 + ianns.getSize(); } + if (ClassReader.ANNOTATIONS && tanns != null) { + cw.newUTF8("RuntimeVisibleTypeAnnotations"); + size += 8 + tanns.getSize(); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + cw.newUTF8("RuntimeInvisibleTypeAnnotations"); + size += 8 + itanns.getSize(); + } if (ClassReader.ANNOTATIONS && panns != null) { cw.newUTF8("RuntimeVisibleParameterAnnotations"); size += 7 + 2 * (panns.length - synthetics); @@ -1965,13 +2104,14 @@ 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 - | 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); if (classReaderOffset != 0) { out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); @@ -1984,10 +2124,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; @@ -1995,6 +2136,9 @@ class MethodWriter extends MethodVisitor { if (ClassReader.SIGNATURES && signature != null) { ++attributeCount; } + if (methodParameters != null) { + ++attributeCount; + } if (ClassReader.ANNOTATIONS && annd != null) { ++attributeCount; } @@ -2004,6 +2148,12 @@ class MethodWriter extends MethodVisitor { if (ClassReader.ANNOTATIONS && ianns != null) { ++attributeCount; } + if (ClassReader.ANNOTATIONS && tanns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && itanns != null) { + ++attributeCount; + } if (ClassReader.ANNOTATIONS && panns != null) { ++attributeCount; } @@ -2028,11 +2178,14 @@ class MethodWriter extends MethodVisitor { if (stackMap != null) { size += 8 + stackMap.length; } + if (ClassReader.ANNOTATIONS && ctanns != null) { + size += 8 + ctanns.getSize(); + } + if (ClassReader.ANNOTATIONS && ictanns != null) { + size += 8 + ictanns.getSize(); + } 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); @@ -2042,10 +2195,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; } } @@ -2062,6 +2213,12 @@ class MethodWriter extends MethodVisitor { if (stackMap != null) { ++attributeCount; } + if (ClassReader.ANNOTATIONS && ctanns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && ictanns != null) { + ++attributeCount; + } if (cattrs != null) { attributeCount += cattrs.getCount(); } @@ -2087,31 +2244,45 @@ class MethodWriter extends MethodVisitor { out.putInt(stackMap.length + 2).putShort(frameCount); out.putByteArray(stackMap.data, 0, stackMap.length); } + if (ClassReader.ANNOTATIONS && ctanns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); + ctanns.put(out); + } + if (ClassReader.ANNOTATIONS && ictanns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); + ictanns.put(out); + } if (cattrs != null) { cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); } } 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 (methodParameters != null) { + out.putShort(cw.newUTF8("MethodParameters")); + out.putInt(methodParameters.length + 1).putByte( + methodParametersCount); + out.putByteArray(methodParameters.data, 0, methodParameters.length); + } if (ClassReader.ANNOTATIONS && annd != null) { out.putShort(cw.newUTF8("AnnotationDefault")); out.putInt(annd.length); @@ -2125,6 +2296,14 @@ class MethodWriter extends MethodVisitor { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } + if (ClassReader.ANNOTATIONS && tanns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); + tanns.put(out); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); + itanns.put(out); + } if (ClassReader.ANNOTATIONS && panns != null) { out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); AnnotationWriter.put(panns, synthetics, out); @@ -2152,10 +2331,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.

This method must be called after all the method - * that is being built has been visited. 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. + *

+ * This method must be called after all the method that is being built + * has been visited. 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 @@ -2205,158 +2386,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 instruction with - // IFNOTxxx GOTO_W , where IFNOTxxx - // is the "opposite" opcode of IFxxx (i.e., - // IFNE for IFEQ) and where 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); @@ -2364,100 +2401,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 - // with IFNOTxxx GOTO_W , where IFNOTxxx is - // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) - // and where 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 instruction with + // IFNOTxxx GOTO_W , where IFNOTxxx + // is the "opposite" opcode of IFxxx (i.e., + // IFNE for IFEQ) and where 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: @@ -2465,19 +2480,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 + // with IFNOTxxx GOTO_W , where IFNOTxxx is + // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) + // and where 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; } } @@ -2500,8 +2674,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); @@ -2557,10 +2730,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; } } @@ -2583,8 +2757,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) { @@ -2594,8 +2770,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) { @@ -2605,8 +2783,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) { @@ -2617,9 +2797,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); @@ -2627,32 +2810,34 @@ class MethodWriter extends MethodVisitor { } /** - * Computes the future value of a bytecode offset.

Note: it is possible - * to have several entries for the same instruction in the indexes - * and sizes: 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. + *

+ * Note: it is possible to have several entries for the same instruction in + * the indexes and sizes: 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 last - * byte, plus one (or, in other words, by the index of the first - * byte of the next instruction). - * @param sizes the number of bytes to be added to the above - * instructions. More precisely, for each i < len, - * sizes[i] bytes will be added at the end of the - * instruction designated by indexes[i] or, if - * sizes[i] is negative, the last |sizes[i]| - * bytes of the instruction will be removed (the instruction size - * must not 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 last + * byte, plus one (or, in other words, by the index of the + * first byte of the next instruction). + * @param sizes + * the number of bytes to be added to the above + * instructions. More precisely, for each i < len, + * sizes[i] bytes will be added at the end of the + * instruction designated by indexes[i] or, if + * sizes[i] is negative, the last | + * sizes[i]| bytes of the instruction will be removed + * (the instruction size must not 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) { @@ -2669,24 +2854,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 last - * byte, plus one (or, in other words, by the index of the first - * byte of the next instruction). - * @param sizes the number of bytes to be added to the above - * instructions. More precisely, for each i < len, - * sizes[i] bytes will be added at the end of the - * instruction designated by indexes[i] or, if - * sizes[i] is negative, the last |sizes[i]| - * bytes of the instruction will be removed (the instruction size - * must not 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 last + * byte, plus one (or, in other words, by the index of the + * first byte of the next instruction). + * @param sizes + * the number of bytes to be added to the above + * instructions. More precisely, for each i < len, + * sizes[i] bytes will be added at the end of the + * instruction designated by indexes[i] or, if + * sizes[i] is negative, the last | + * sizes[i]| bytes of the instruction will be removed + * (the instruction size must not 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/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java b/src/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java index df3dcbcd7497b0349aeed393acb70c30e7feb257..286853352d259bae03d426b9e01b69a16159e8e6 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java @@ -75,6 +75,7 @@ public interface Opcodes { // ASM API versions int ASM4 = 4 << 16 | 0 << 8 | 0; + int ASM5 = 5 << 16 | 0 << 8 | 0; // versions @@ -85,6 +86,7 @@ public interface Opcodes { int V1_5 = 0 << 16 | 49; int V1_6 = 0 << 16 | 50; int V1_7 = 0 << 16 | 51; + int V1_8 = 0 << 16 | 52; // access flags @@ -92,7 +94,7 @@ public interface Opcodes { int ACC_PRIVATE = 0x0002; // class, field, method int ACC_PROTECTED = 0x0004; // class, field, method int ACC_STATIC = 0x0008; // field, method - int ACC_FINAL = 0x0010; // class, field, method + int ACC_FINAL = 0x0010; // class, field, method, parameter int ACC_SUPER = 0x0020; // class int ACC_SYNCHRONIZED = 0x0020; // method int ACC_VOLATILE = 0x0040; // field @@ -103,9 +105,10 @@ public interface Opcodes { int ACC_INTERFACE = 0x0200; // class int ACC_ABSTRACT = 0x0400; // class, method int ACC_STRICT = 0x0800; // method - int ACC_SYNTHETIC = 0x1000; // class, field, method + int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter int ACC_ANNOTATION = 0x2000; // class int ACC_ENUM = 0x4000; // class(?) field inner + int ACC_MANDATED = 0x8000; // parameter // ASM specific pseudo access flags diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/Type.java b/src/share/classes/jdk/internal/org/objectweb/asm/Type.java index b7c7a7cf7f7d2d9ee441fa055f9fc6a39d293263..e385f9f649123b26e6d9c0ca16649d6a52445871 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/Type.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Type.java @@ -219,13 +219,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; @@ -235,7 +238,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) { @@ -245,7 +249,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) { @@ -257,7 +262,8 @@ public class Type { * Returns the Java type corresponding to the given method descriptor. * Equivalent to Type.getType(methodDescriptor). * - * @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) { @@ -268,18 +274,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) { @@ -311,7 +322,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) { @@ -321,7 +333,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) { @@ -332,7 +345,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. */ @@ -367,7 +381,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. */ @@ -384,7 +399,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. */ @@ -397,7 +413,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. */ @@ -408,12 +425,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 = - * (argSize << 2) | retSize (argSize is therefore equal - * to i >> 2, and retSize to i & 0x03). + * (argSize << 2) | retSize (argSize is therefore equal to + * i >> 2, and retSize to i & 0x03). */ public static int getArgumentsAndReturnSizes(final String desc) { int n = 1; @@ -448,52 +466,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); } } @@ -504,11 +524,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; @@ -546,34 +566,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; } } @@ -615,9 +635,10 @@ public class Type { * * @return the size of the arguments (plus one for the implicit this * argument), argSize, and the size of the return value, retSize, - * packed into a single int i = (argSize << 2) | retSize - * (argSize is therefore equal to i >> 2, and retSize to - * i & 0x03). + * packed into a single + * int i = (argSize << 2) | retSize + * (argSize is therefore equal to i >> 2, + * and retSize to i & 0x03). */ public int getArgumentsAndReturnSizes() { return getArgumentsAndReturnSizes(getDescriptor()); @@ -642,15 +663,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) { @@ -665,11 +686,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'); @@ -690,7 +713,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) { @@ -700,7 +724,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) { @@ -712,7 +737,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) { @@ -728,7 +754,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) { @@ -746,8 +773,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; @@ -812,9 +841,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 float and * opcode is IRETURN, this method returns FRETURN. @@ -838,7 +868,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 true if the given object is equal to this type. */ @Override diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/TypePath.java b/src/share/classes/jdk/internal/org/objectweb/asm/TypePath.java new file mode 100644 index 0000000000000000000000000000000000000000..b43a11d5a30c9b23b8df882613db46384533a267 --- /dev/null +++ b/src/share/classes/jdk/internal/org/objectweb/asm/TypePath.java @@ -0,0 +1,222 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2013 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 jdk.internal.org.objectweb.asm; + +/** + * The path to a type argument, wildcard bound, array element type, or static + * inner type within an enclosing type. + * + * @author Eric Bruneton + */ +public class TypePath { + + /** + * A type path step that steps into the element type of an array type. See + * {@link #getStep getStep}. + */ + public final static int ARRAY_ELEMENT = 0; + + /** + * A type path step that steps into the nested type of a class type. See + * {@link #getStep getStep}. + */ + public final static int INNER_TYPE = 1; + + /** + * A type path step that steps into the bound of a wildcard type. See + * {@link #getStep getStep}. + */ + public final static int WILDCARD_BOUND = 2; + + /** + * A type path step that steps into a type argument of a generic type. See + * {@link #getStep getStep}. + */ + public final static int TYPE_ARGUMENT = 3; + + /** + * The byte array where the path is stored, in Java class file format. + */ + byte[] b; + + /** + * The offset of the first byte of the type path in 'b'. + */ + int offset; + + /** + * Creates a new type path. + * + * @param b + * the byte array containing the type path in Java class file + * format. + * @param offset + * the offset of the first byte of the type path in 'b'. + */ + TypePath(byte[] b, int offset) { + this.b = b; + this.offset = offset; + } + + /** + * Returns the length of this path. + * + * @return the length of this path. + */ + public int getLength() { + return b[offset]; + } + + /** + * Returns the value of the given step of this path. + * + * @param index + * an index between 0 and {@link #getLength()}, exclusive. + * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE + * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or + * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. + */ + public int getStep(int index) { + return b[offset + 2 * index + 1]; + } + + /** + * Returns the index of the type argument that the given step is stepping + * into. This method should only be used for steps whose value is + * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. + * + * @param index + * an index between 0 and {@link #getLength()}, exclusive. + * @return the index of the type argument that the given step is stepping + * into. + */ + public int getStepArgument(int index) { + return b[offset + 2 * index + 2]; + } + + /** + * Converts a type path in string form, in the format used by + * {@link #toString()}, into a TypePath object. + * + * @param typePath + * a type path in string form, in the format used by + * {@link #toString()}. May be null or empty. + * @return the corresponding TypePath object, or null if the path is empty. + */ + public static TypePath fromString(final String typePath) { + if (typePath == null || typePath.length() == 0) { + return null; + } + int n = typePath.length(); + ByteVector out = new ByteVector(n); + out.putByte(0); + for (int i = 0; i < n;) { + char c = typePath.charAt(i++); + if (c == '[') { + out.put11(ARRAY_ELEMENT, 0); + } else if (c == '.') { + out.put11(INNER_TYPE, 0); + } else if (c == '*') { + out.put11(WILDCARD_BOUND, 0); + } else if (c >= '0' && c <= '9') { + int typeArg = c - '0'; + while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') { + typeArg = typeArg * 10 + c - '0'; + i += 1; + } + out.put11(TYPE_ARGUMENT, typeArg); + } + } + out.data[0] = (byte) (out.length / 2); + return new TypePath(out.data, 0); + } + + /** + * Returns a string representation of this type path. {@link #ARRAY_ELEMENT + * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE + * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps + * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type + * argument index in decimal form. + */ + @Override + public String toString() { + int length = getLength(); + StringBuilder result = new StringBuilder(length * 2); + for (int i = 0; i < length; ++i) { + switch (getStep(i)) { + case ARRAY_ELEMENT: + result.append('['); + break; + case INNER_TYPE: + result.append('.'); + break; + case WILDCARD_BOUND: + result.append('*'); + break; + case TYPE_ARGUMENT: + result.append(getStepArgument(i)); + break; + default: + result.append('_'); + } + } + return result.toString(); + } +} diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java b/src/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java new file mode 100644 index 0000000000000000000000000000000000000000..4caf8f10db0491a7bbc748b9be27972a70d26db8 --- /dev/null +++ b/src/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java @@ -0,0 +1,481 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2013 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 jdk.internal.org.objectweb.asm; + +/** + * A reference to a type appearing in a class, field or method declaration, or + * on an instruction. Such a reference designates the part of the class where + * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws' + * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable + * declaration, etc). + * + * @author Eric Bruneton + */ +public class TypeReference { + + /** + * The sort of type references that target a type parameter of a generic + * class. See {@link #getSort getSort}. + */ + public final static int CLASS_TYPE_PARAMETER = 0x00; + + /** + * The sort of type references that target a type parameter of a generic + * method. See {@link #getSort getSort}. + */ + public final static int METHOD_TYPE_PARAMETER = 0x01; + + /** + * The sort of type references that target the super class of a class or one + * of the interfaces it implements. See {@link #getSort getSort}. + */ + public final static int CLASS_EXTENDS = 0x10; + + /** + * The sort of type references that target a bound of a type parameter of a + * generic class. See {@link #getSort getSort}. + */ + public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; + + /** + * The sort of type references that target a bound of a type parameter of a + * generic method. See {@link #getSort getSort}. + */ + public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; + + /** + * The sort of type references that target the type of a field. See + * {@link #getSort getSort}. + */ + public final static int FIELD = 0x13; + + /** + * The sort of type references that target the return type of a method. See + * {@link #getSort getSort}. + */ + public final static int METHOD_RETURN = 0x14; + + /** + * The sort of type references that target the receiver type of a method. + * See {@link #getSort getSort}. + */ + public final static int METHOD_RECEIVER = 0x15; + + /** + * The sort of type references that target the type of a formal parameter of + * a method. See {@link #getSort getSort}. + */ + public final static int METHOD_FORMAL_PARAMETER = 0x16; + + /** + * The sort of type references that target the type of an exception declared + * in the throws clause of a method. See {@link #getSort getSort}. + */ + public final static int THROWS = 0x17; + + /** + * The sort of type references that target the type of a local variable in a + * method. See {@link #getSort getSort}. + */ + public final static int LOCAL_VARIABLE = 0x40; + + /** + * The sort of type references that target the type of a resource variable + * in a method. See {@link #getSort getSort}. + */ + public final static int RESOURCE_VARIABLE = 0x41; + + /** + * The sort of type references that target the type of the exception of a + * 'catch' clause in a method. See {@link #getSort getSort}. + */ + public final static int EXCEPTION_PARAMETER = 0x42; + + /** + * The sort of type references that target the type declared in an + * 'instanceof' instruction. See {@link #getSort getSort}. + */ + public final static int INSTANCEOF = 0x43; + + /** + * The sort of type references that target the type of the object created by + * a 'new' instruction. See {@link #getSort getSort}. + */ + public final static int NEW = 0x44; + + /** + * The sort of type references that target the receiver type of a + * constructor reference. See {@link #getSort getSort}. + */ + public final static int CONSTRUCTOR_REFERENCE = 0x45; + + /** + * The sort of type references that target the receiver type of a method + * reference. See {@link #getSort getSort}. + */ + public final static int METHOD_REFERENCE = 0x46; + + /** + * The sort of type references that target the type declared in an explicit + * or implicit cast instruction. See {@link #getSort getSort}. + */ + public final static int CAST = 0x47; + + /** + * The sort of type references that target a type parameter of a generic + * constructor in a constructor call. See {@link #getSort getSort}. + */ + public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; + + /** + * The sort of type references that target a type parameter of a generic + * method in a method call. See {@link #getSort getSort}. + */ + public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; + + /** + * The sort of type references that target a type parameter of a generic + * constructor in a constructor reference. See {@link #getSort getSort}. + */ + public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; + + /** + * The sort of type references that target a type parameter of a generic + * method in a method reference. See {@link #getSort getSort}. + */ + public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; + + /** + * The type reference value in Java class file format. + */ + private int value; + + /** + * Creates a new TypeReference. + * + * @param typeRef + * the int encoded value of the type reference, as received in a + * visit method related to type annotations, like + * visitTypeAnnotation. + */ + public TypeReference(int typeRef) { + this.value = typeRef; + } + + /** + * Returns a type reference of the given sort. + * + * @param sort + * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, + * {@link #METHOD_RECEIVER METHOD_RECEIVER}, + * {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, + * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, + * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, + * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or + * {@link #METHOD_REFERENCE METHOD_REFERENCE}. + * @return a type reference of the given sort. + */ + public static TypeReference newTypeReference(int sort) { + return new TypeReference(sort << 24); + } + + /** + * Returns a reference to a type parameter of a generic class or method. + * + * @param sort + * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. + * @param paramIndex + * the type parameter index. + * @return a reference to the given generic class or method type parameter. + */ + public static TypeReference newTypeParameterReference(int sort, + int paramIndex) { + return new TypeReference((sort << 24) | (paramIndex << 16)); + } + + /** + * Returns a reference to a type parameter bound of a generic class or + * method. + * + * @param sort + * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. + * @param paramIndex + * the type parameter index. + * @param boundIndex + * the type bound index within the above type parameters. + * @return a reference to the given generic class or method type parameter + * bound. + */ + public static TypeReference newTypeParameterBoundReference(int sort, + int paramIndex, int boundIndex) { + return new TypeReference((sort << 24) | (paramIndex << 16) + | (boundIndex << 8)); + } + + /** + * Returns a reference to the super class or to an interface of the + * 'implements' clause of a class. + * + * @param itfIndex + * the index of an interface in the 'implements' clause of a + * class, or -1 to reference the super class of the class. + * @return a reference to the given super type of a class. + */ + public static TypeReference newSuperTypeReference(int itfIndex) { + itfIndex &= 0xFFFF; + return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8)); + } + + /** + * Returns a reference to the type of a formal parameter of a method. + * + * @param paramIndex + * the formal parameter index. + * + * @return a reference to the type of the given method formal parameter. + */ + public static TypeReference newFormalParameterReference(int paramIndex) { + return new TypeReference((METHOD_FORMAL_PARAMETER << 24) + | (paramIndex << 16)); + } + + /** + * Returns a reference to the type of an exception, in a 'throws' clause of + * a method. + * + * @param exceptionIndex + * the index of an exception in a 'throws' clause of a method. + * + * @return a reference to the type of the given exception. + */ + public static TypeReference newExceptionReference(int exceptionIndex) { + return new TypeReference((THROWS << 24) | (exceptionIndex << 8)); + } + + /** + * Returns a reference to the type of the exception declared in a 'catch' + * clause of a method. + * + * @param tryCatchBlockIndex + * the index of a try catch block (using the order in which they + * are visited with visitTryCatchBlock). + * + * @return a reference to the type of the given exception. + */ + public static TypeReference newTryCatchReference(int tryCatchBlockIndex) { + return new TypeReference((EXCEPTION_PARAMETER << 24) + | (tryCatchBlockIndex << 8)); + } + + /** + * Returns a reference to the type of a type argument in a constructor or + * method call or reference. + * + * @param sort + * {@link #CAST CAST}, + * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link #METHOD_INVOCATION_TYPE_ARGUMENT + * METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link #METHOD_REFERENCE_TYPE_ARGUMENT + * METHOD_REFERENCE_TYPE_ARGUMENT}. + * @param argIndex + * the type argument index. + * + * @return a reference to the type of the given type argument. + */ + public static TypeReference newTypeArgumentReference(int sort, int argIndex) { + return new TypeReference((sort << 24) | argIndex); + } + + /** + * Returns the sort of this type reference. + * + * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, + * {@link #CLASS_EXTENDS CLASS_EXTENDS}, + * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND}, + * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}, + * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, + * {@link #METHOD_RECEIVER METHOD_RECEIVER}, + * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}, + * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, + * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, + * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER}, + * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, + * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, + * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST}, + * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link #METHOD_INVOCATION_TYPE_ARGUMENT + * METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link #METHOD_REFERENCE_TYPE_ARGUMENT + * METHOD_REFERENCE_TYPE_ARGUMENT}. + */ + public int getSort() { + return value >>> 24; + } + + /** + * Returns the index of the type parameter referenced by this type + * reference. This method must only be used for type references whose sort + * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, + * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or + * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. + * + * @return a type parameter index. + */ + public int getTypeParameterIndex() { + return (value & 0x00FF0000) >> 16; + } + + /** + * Returns the index of the type parameter bound, within the type parameter + * {@link #getTypeParameterIndex}, referenced by this type reference. This + * method must only be used for type references whose sort is + * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or + * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. + * + * @return a type parameter bound index. + */ + public int getTypeParameterBoundIndex() { + return (value & 0x0000FF00) >> 8; + } + + /** + * Returns the index of the "super type" of a class that is referenced by + * this type reference. This method must only be used for type references + * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}. + * + * @return the index of an interface in the 'implements' clause of a class, + * or -1 if this type reference references the type of the super + * class. + */ + public int getSuperTypeIndex() { + return (short) ((value & 0x00FFFF00) >> 8); + } + + /** + * Returns the index of the formal parameter whose type is referenced by + * this type reference. This method must only be used for type references + * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}. + * + * @return a formal parameter index. + */ + public int getFormalParameterIndex() { + return (value & 0x00FF0000) >> 16; + } + + /** + * Returns the index of the exception, in a 'throws' clause of a method, + * whose type is referenced by this type reference. This method must only be + * used for type references whose sort is {@link #THROWS THROWS}. + * + * @return the index of an exception in the 'throws' clause of a method. + */ + public int getExceptionIndex() { + return (value & 0x00FFFF00) >> 8; + } + + /** + * Returns the index of the try catch block (using the order in which they + * are visited with visitTryCatchBlock), whose 'catch' type is referenced by + * this type reference. This method must only be used for type references + * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} . + * + * @return the index of an exception in the 'throws' clause of a method. + */ + public int getTryCatchBlockIndex() { + return (value & 0x00FFFF00) >> 8; + } + + /** + * Returns the index of the type argument referenced by this type reference. + * This method must only be used for type references whose sort is + * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}. + * + * @return a type parameter index. + */ + public int getTypeArgumentIndex() { + return value & 0xFF; + } + + /** + * Returns the int encoded value of this type reference, suitable for use in + * visit methods related to type annotations, like visitTypeAnnotation. + * + * @return the int encoded value of this type reference. + */ + public int getValue() { + return value; + } +} diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java index dd6f26035f9a28ead004a898af60b53f64ad3510..c7d51d45b91eb27dfe0a495372d05ff4e260626f 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java @@ -30,7 +30,6 @@ * * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom - * Copyright (c) 2011 Google * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -72,14 +71,16 @@ import jdk.internal.org.objectweb.asm.Type; /** * A {@link jdk.internal.org.objectweb.asm.MethodVisitor} to insert before, after and around - * advices in methods and constructors.

The behavior for constructors is - * like this:

    + * advices in methods and constructors. + *

    + * The behavior for constructors is like this: + *

      * *
    1. as long as the INVOKESPECIAL for the object initialization has not been * reached, every bytecode instruction is dispatched in the ctor code visitor
    2. * - *
    3. when this one is reached, it is only added in the ctor code visitor and - * a JP invoke is added
    4. + *
    5. when this one is reached, it is only added in the ctor code visitor and a + * JP invoke is added
    6. * *
    7. after that, only the other code visitor receives the instructions
    8. * @@ -88,8 +89,7 @@ import jdk.internal.org.objectweb.asm.Type; * @author Eugene Kuleshov * @author Eric Bruneton */ -public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes -{ +public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes { private static final Object THIS = new Object(); @@ -110,20 +110,20 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes /** * Creates a new {@link AdviceAdapter}. * - * @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 adapter delegates calls. - * @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 Type}). + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param mv + * the method visitor to which this adapter delegates calls. + * @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 Type}). */ - protected AdviceAdapter( - final int api, - final MethodVisitor mv, - final int access, - final String name, - final String desc) - { + protected AdviceAdapter(final int api, final MethodVisitor mv, + final int access, final String name, final String desc) { super(api, mv, access, name, desc); methodAccess = access; methodDesc = desc; @@ -159,194 +159,178 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes if (constructor) { int s; switch (opcode) { - case RETURN: // empty stack - onMethodExit(opcode); - break; - - case IRETURN: // 1 before n/a after - case FRETURN: // 1 before n/a after - case ARETURN: // 1 before n/a after - case ATHROW: // 1 before n/a after - popValue(); - onMethodExit(opcode); - break; - - case LRETURN: // 2 before n/a after - case DRETURN: // 2 before n/a after - popValue(); - popValue(); - onMethodExit(opcode); - break; - - case NOP: - case LALOAD: // remove 2 add 2 - case DALOAD: // remove 2 add 2 - case LNEG: - case DNEG: - case FNEG: - case INEG: - case L2D: - case D2L: - case F2I: - case I2B: - case I2C: - case I2S: - case I2F: - case ARRAYLENGTH: - break; - - case ACONST_NULL: - case ICONST_M1: - case ICONST_0: - case ICONST_1: - case ICONST_2: - case ICONST_3: - case ICONST_4: - case ICONST_5: - case FCONST_0: - case FCONST_1: - case FCONST_2: - case F2L: // 1 before 2 after - case F2D: - case I2L: - case I2D: - pushValue(OTHER); - break; - - case LCONST_0: - case LCONST_1: - case DCONST_0: - case DCONST_1: - pushValue(OTHER); - pushValue(OTHER); - break; - - case IALOAD: // remove 2 add 1 - case FALOAD: // remove 2 add 1 - case AALOAD: // remove 2 add 1 - case BALOAD: // remove 2 add 1 - case CALOAD: // remove 2 add 1 - case SALOAD: // remove 2 add 1 - case POP: - case IADD: - case FADD: - case ISUB: - case LSHL: // 3 before 2 after - case LSHR: // 3 before 2 after - case LUSHR: // 3 before 2 after - case L2I: // 2 before 1 after - case L2F: // 2 before 1 after - case D2I: // 2 before 1 after - case D2F: // 2 before 1 after - case FSUB: - case FMUL: - case FDIV: - case FREM: - case FCMPL: // 2 before 1 after - case FCMPG: // 2 before 1 after - case IMUL: - case IDIV: - case IREM: - case ISHL: - case ISHR: - case IUSHR: - case IAND: - case IOR: - case IXOR: - case MONITORENTER: - case MONITOREXIT: - popValue(); - break; - - case POP2: - case LSUB: - case LMUL: - case LDIV: - case LREM: - case LADD: - case LAND: - case LOR: - case LXOR: - case DADD: - case DMUL: - case DSUB: - case DDIV: - case DREM: - popValue(); - popValue(); - break; - - case IASTORE: - case FASTORE: - case AASTORE: - case BASTORE: - case CASTORE: - case SASTORE: - case LCMP: // 4 before 1 after - case DCMPL: - case DCMPG: - popValue(); - popValue(); - popValue(); - break; - - case LASTORE: - case DASTORE: - popValue(); - popValue(); - popValue(); - popValue(); - break; - - case DUP: - pushValue(peekValue()); - break; - - case DUP_X1: - s = stackFrame.size(); - stackFrame.add(s - 2, stackFrame.get(s - 1)); - break; - - case DUP_X2: - s = stackFrame.size(); - stackFrame.add(s - 3, stackFrame.get(s - 1)); - break; - - case DUP2: - s = stackFrame.size(); - stackFrame.add(s - 2, stackFrame.get(s - 1)); - stackFrame.add(s - 2, stackFrame.get(s - 1)); - break; - - case DUP2_X1: - s = stackFrame.size(); - stackFrame.add(s - 3, stackFrame.get(s - 1)); - stackFrame.add(s - 3, stackFrame.get(s - 1)); - break; - - case DUP2_X2: - s = stackFrame.size(); - stackFrame.add(s - 4, stackFrame.get(s - 1)); - stackFrame.add(s - 4, stackFrame.get(s - 1)); - break; - - case SWAP: - s = stackFrame.size(); - stackFrame.add(s - 2, stackFrame.get(s - 1)); - stackFrame.remove(s); - break; + case RETURN: // empty stack + onMethodExit(opcode); + break; + case IRETURN: // 1 before n/a after + case FRETURN: // 1 before n/a after + case ARETURN: // 1 before n/a after + case ATHROW: // 1 before n/a after + popValue(); + onMethodExit(opcode); + break; + case LRETURN: // 2 before n/a after + case DRETURN: // 2 before n/a after + popValue(); + popValue(); + onMethodExit(opcode); + break; + case NOP: + case LALOAD: // remove 2 add 2 + case DALOAD: // remove 2 add 2 + case LNEG: + case DNEG: + case FNEG: + case INEG: + case L2D: + case D2L: + case F2I: + case I2B: + case I2C: + case I2S: + case I2F: + case ARRAYLENGTH: + break; + case ACONST_NULL: + case ICONST_M1: + case ICONST_0: + case ICONST_1: + case ICONST_2: + case ICONST_3: + case ICONST_4: + case ICONST_5: + case FCONST_0: + case FCONST_1: + case FCONST_2: + case F2L: // 1 before 2 after + case F2D: + case I2L: + case I2D: + pushValue(OTHER); + break; + case LCONST_0: + case LCONST_1: + case DCONST_0: + case DCONST_1: + pushValue(OTHER); + pushValue(OTHER); + break; + case IALOAD: // remove 2 add 1 + case FALOAD: // remove 2 add 1 + case AALOAD: // remove 2 add 1 + case BALOAD: // remove 2 add 1 + case CALOAD: // remove 2 add 1 + case SALOAD: // remove 2 add 1 + case POP: + case IADD: + case FADD: + case ISUB: + case LSHL: // 3 before 2 after + case LSHR: // 3 before 2 after + case LUSHR: // 3 before 2 after + case L2I: // 2 before 1 after + case L2F: // 2 before 1 after + case D2I: // 2 before 1 after + case D2F: // 2 before 1 after + case FSUB: + case FMUL: + case FDIV: + case FREM: + case FCMPL: // 2 before 1 after + case FCMPG: // 2 before 1 after + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + case MONITORENTER: + case MONITOREXIT: + popValue(); + break; + case POP2: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LADD: + case LAND: + case LOR: + case LXOR: + case DADD: + case DMUL: + case DSUB: + case DDIV: + case DREM: + popValue(); + popValue(); + break; + case IASTORE: + case FASTORE: + case AASTORE: + case BASTORE: + case CASTORE: + case SASTORE: + case LCMP: // 4 before 1 after + case DCMPL: + case DCMPG: + popValue(); + popValue(); + popValue(); + break; + case LASTORE: + case DASTORE: + popValue(); + popValue(); + popValue(); + popValue(); + break; + case DUP: + pushValue(peekValue()); + break; + case DUP_X1: + s = stackFrame.size(); + stackFrame.add(s - 2, stackFrame.get(s - 1)); + break; + case DUP_X2: + s = stackFrame.size(); + stackFrame.add(s - 3, stackFrame.get(s - 1)); + break; + case DUP2: + s = stackFrame.size(); + stackFrame.add(s - 2, stackFrame.get(s - 1)); + stackFrame.add(s - 2, stackFrame.get(s - 1)); + break; + case DUP2_X1: + s = stackFrame.size(); + stackFrame.add(s - 3, stackFrame.get(s - 1)); + stackFrame.add(s - 3, stackFrame.get(s - 1)); + break; + case DUP2_X2: + s = stackFrame.size(); + stackFrame.add(s - 4, stackFrame.get(s - 1)); + stackFrame.add(s - 4, stackFrame.get(s - 1)); + break; + case SWAP: + s = stackFrame.size(); + stackFrame.add(s - 2, stackFrame.get(s - 1)); + stackFrame.remove(s); + break; } } else { switch (opcode) { - case RETURN: - case IRETURN: - case FRETURN: - case ARETURN: - case LRETURN: - case DRETURN: - case ATHROW: - onMethodExit(opcode); - break; + case RETURN: + case IRETURN: + case FRETURN: + case ARETURN: + case LRETURN: + case DRETURN: + case ATHROW: + onMethodExit(opcode); + break; } } mv.visitInsn(opcode); @@ -357,68 +341,64 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes super.visitVarInsn(opcode, var); if (constructor) { switch (opcode) { - case ILOAD: - case FLOAD: - pushValue(OTHER); - break; - case LLOAD: - case DLOAD: - pushValue(OTHER); - pushValue(OTHER); - break; - case ALOAD: - pushValue(var == 0 ? THIS : OTHER); - break; - case ASTORE: - case ISTORE: - case FSTORE: - popValue(); - break; - case LSTORE: - case DSTORE: - popValue(); - popValue(); - break; + case ILOAD: + case FLOAD: + pushValue(OTHER); + break; + case LLOAD: + case DLOAD: + pushValue(OTHER); + pushValue(OTHER); + break; + case ALOAD: + pushValue(var == 0 ? THIS : OTHER); + break; + case ASTORE: + case ISTORE: + case FSTORE: + popValue(); + break; + case LSTORE: + case DSTORE: + popValue(); + popValue(); + break; } } } @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) { mv.visitFieldInsn(opcode, owner, name, desc); if (constructor) { char c = desc.charAt(0); boolean longOrDouble = c == 'J' || c == 'D'; switch (opcode) { - case GETSTATIC: + case GETSTATIC: + pushValue(OTHER); + if (longOrDouble) { pushValue(OTHER); - if (longOrDouble) { - pushValue(OTHER); - } - break; - case PUTSTATIC: + } + break; + case PUTSTATIC: + popValue(); + if (longOrDouble) { popValue(); - if (longOrDouble) { - popValue(); - } - break; - case PUTFIELD: + } + break; + case PUTFIELD: + popValue(); + if (longOrDouble) { popValue(); - if (longOrDouble) { - popValue(); - popValue(); - } - break; - // case GETFIELD: - default: - if (longOrDouble) { - pushValue(OTHER); - } + popValue(); + } + break; + // case GETFIELD: + default: + if (longOrDouble) { + pushValue(OTHER); + } } } } @@ -463,12 +443,8 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes } @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) { mv.visitMethodInsn(opcode, owner, name, desc); if (constructor) { Type[] types = Type.getArgumentTypes(desc); @@ -479,24 +455,22 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes } } switch (opcode) { - // case INVOKESTATIC: - // break; - - case INVOKEINTERFACE: - case INVOKEVIRTUAL: - popValue(); // objectref - break; - - case INVOKESPECIAL: - Object type = popValue(); // objectref - if (type == THIS && !superInitialized) { - onMethodEnter(); - superInitialized = true; - // once super has been initialized it is no longer - // necessary to keep track of stack state - constructor = false; - } - break; + // case INVOKESTATIC: + // break; + case INVOKEINTERFACE: + case INVOKEVIRTUAL: + popValue(); // objectref + break; + case INVOKESPECIAL: + Object type = popValue(); // objectref + if (type == THIS && !superInitialized) { + onMethodEnter(); + superInitialized = true; + // once super has been initialized it is no longer + // necessary to keep track of stack state + constructor = false; + } + break; } Type returnType = Type.getReturnType(desc); @@ -510,12 +484,8 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes } @Override - public void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs) - { + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); if (constructor) { Type[] types = Type.getArgumentTypes(desc); @@ -541,43 +511,38 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes mv.visitJumpInsn(opcode, label); if (constructor) { switch (opcode) { - case IFEQ: - case IFNE: - case IFLT: - case IFGE: - case IFGT: - case IFLE: - case IFNULL: - case IFNONNULL: - popValue(); - break; - - case IF_ICMPEQ: - case IF_ICMPNE: - case IF_ICMPLT: - case IF_ICMPGE: - case IF_ICMPGT: - case IF_ICMPLE: - case IF_ACMPEQ: - case IF_ACMPNE: - popValue(); - popValue(); - break; - - case JSR: - pushValue(OTHER); - break; + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case IFNULL: + case IFNONNULL: + popValue(); + break; + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ACMPEQ: + case IF_ACMPNE: + popValue(); + popValue(); + break; + case JSR: + pushValue(OTHER); + break; } addBranch(label); } } @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) { mv.visitLookupSwitchInsn(dflt, keys, labels); if (constructor) { popValue(); @@ -586,12 +551,8 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes } @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) { mv.visitTableSwitchInsn(min, max, dflt, labels); if (constructor) { popValue(); @@ -600,12 +561,8 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes } @Override - public void visitTryCatchBlock( - Label start, - Label end, - Label handler, - String type) - { + public void visitTryCatchBlock(Label start, Label end, Label handler, + String type) { super.visitTryCatchBlock(start, end, handler, type); if (constructor && !branches.containsKey(handler)) { List stackFrame = new ArrayList(); @@ -642,7 +599,8 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes /** * Called at the beginning of the method or after super class class call in - * the constructor.

      + * the constructor.
      + *
      * * Custom code can use or change all the local variables, but should not * change state of the stack. @@ -678,13 +636,15 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes * ... * * - *

      + *
      + *
      * * Custom code can use or change all the local variables, but should not * change state of the stack. * - * @param opcode one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, - * DRETURN or ATHROW + * @param opcode + * one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, DRETURN + * or ATHROW * */ protected void onMethodExit(int opcode) { diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java index c6861410bf153571a7869a6596a1c3bac97443ad..1371250da0a79a14c4ff7dd850c64d9a3ebb9ff9 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java @@ -73,13 +73,13 @@ import jdk.internal.org.objectweb.asm.Type; * A {@link MethodVisitor} that keeps track of stack map frame changes between * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This * adapter must be used with the - * {@link jdk.internal.org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each visitX - * instruction delegates to the next visitor in the chain, if any, and then - * simulates the effect of this instruction on the stack map frame, represented - * by {@link #locals} and {@link #stack}. The next visitor in the chain can get - * the state of the stack map frame before each instruction by reading - * the value of these fields in its visitX methods (this requires a - * reference to the AnalyzerAdapter that is before it in the chain). + * {@link jdk.internal.org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each + * visitX instruction delegates to the next visitor in the chain, if any, + * and then simulates the effect of this instruction on the stack map frame, + * represented by {@link #locals} and {@link #stack}. The next visitor in the + * chain can get the state of the stack map frame before each instruction + * by reading the value of these fields in its visitX methods (this + * requires a reference to the AnalyzerAdapter that is before it in the chain). * If this adapter is used with a class that does not contain stack map table * attributes (i.e., pre Java 6 classes) then this adapter may not be able to * compute the stack map frame for each instruction. In this case no exception @@ -95,25 +95,25 @@ public class AnalyzerAdapter extends MethodVisitor { * frame. 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 + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by * two elements, the second one being TOP). 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). This field is null for unreacheable + * this uninitialized value). This field is null for unreachable * instructions. */ public List locals; /** - * List of the operand stack slots for current execution - * frame. Primitive types are represented by {@link Opcodes#TOP}, + * List of the operand stack slots for current execution frame. + * 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 + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by * two elements, the second one being TOP). 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). This field is null for unreacheable + * this uninitialized value). This field is null for unreachable * instructions. */ public List stack; @@ -131,7 +131,7 @@ public class AnalyzerAdapter extends MethodVisitor { * types, and the associated internal name represents the NEW operand, i.e. * the final, initialized type value. */ - public Map uninitializedTypes; + public Map uninitializedTypes; /** * The maximum stack size of this method. @@ -154,43 +154,44 @@ public class AnalyzerAdapter extends MethodVisitor { * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)} * version. * - * @param owner the owner's class name. - * @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 Type}). - * @param mv the method visitor to which this adapter delegates calls. May - * be null. + * @param owner + * the owner's class name. + * @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 Type}). + * @param mv + * the method visitor to which this adapter delegates calls. May + * be null. */ - public AnalyzerAdapter( - final String owner, - final int access, - final String name, - final String desc, - final MethodVisitor mv) - { - this(Opcodes.ASM4, owner, access, name, desc, mv); + public AnalyzerAdapter(final String owner, final int access, + final String name, final String desc, final MethodVisitor mv) { + this(Opcodes.ASM5, owner, access, name, desc, mv); } /** * Creates a new {@link AnalyzerAdapter}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param owner the owner's class name. - * @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 Type}). - * @param mv the method visitor to which this adapter delegates calls. May - * be null. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param owner + * the owner's class name. + * @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 Type}). + * @param mv + * the method visitor to which this adapter delegates calls. May + * be null. */ - protected AnalyzerAdapter( - final int api, - final String owner, - final int access, - final String name, - final String desc, - final MethodVisitor mv) - { + protected AnalyzerAdapter(final int api, final String owner, + final int access, final String name, final String desc, + final MethodVisitor mv) { super(api, mv); this.owner = owner; locals = new ArrayList(); @@ -208,44 +209,40 @@ public class AnalyzerAdapter extends MethodVisitor { for (int i = 0; i < types.length; ++i) { Type type = types[i]; switch (type.getSort()) { - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - case Type.INT: - locals.add(Opcodes.INTEGER); - break; - case Type.FLOAT: - locals.add(Opcodes.FLOAT); - break; - case Type.LONG: - locals.add(Opcodes.LONG); - locals.add(Opcodes.TOP); - break; - case Type.DOUBLE: - locals.add(Opcodes.DOUBLE); - locals.add(Opcodes.TOP); - break; - case Type.ARRAY: - locals.add(types[i].getDescriptor()); - break; - // case Type.OBJECT: - default: - locals.add(types[i].getInternalName()); + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + case Type.INT: + locals.add(Opcodes.INTEGER); + break; + case Type.FLOAT: + locals.add(Opcodes.FLOAT); + break; + case Type.LONG: + locals.add(Opcodes.LONG); + locals.add(Opcodes.TOP); + break; + case Type.DOUBLE: + locals.add(Opcodes.DOUBLE); + locals.add(Opcodes.TOP); + break; + case Type.ARRAY: + locals.add(types[i].getDescriptor()); + break; + // case Type.OBJECT: + default: + locals.add(types[i].getInternalName()); } } } @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 (type != Opcodes.F_NEW) { // uncompressed frame - throw new IllegalStateException("ClassReader.accept() should be called with EXPAND_FRAMES flag"); + throw new IllegalStateException( + "ClassReader.accept() should be called with EXPAND_FRAMES flag"); } if (mv != null) { @@ -264,11 +261,8 @@ public class AnalyzerAdapter extends MethodVisitor { maxStack = Math.max(maxStack, this.stack.size()); } - private static void visitFrameTypes( - final int n, - final Object[] types, - final List result) - { + private static void visitFrameTypes(final int n, final Object[] types, + final List result) { for (int i = 0; i < n; ++i) { Object type = types[i]; result.add(type); @@ -285,8 +279,7 @@ public class AnalyzerAdapter extends MethodVisitor { } execute(opcode, 0, null); if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) - || opcode == Opcodes.ATHROW) - { + || opcode == Opcodes.ATHROW) { this.locals = null; this.stack = null; } @@ -330,12 +323,8 @@ public class AnalyzerAdapter 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) { if (mv != null) { mv.visitFieldInsn(opcode, owner, name, desc); } @@ -343,12 +332,8 @@ public class AnalyzerAdapter 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) { if (mv != null) { mv.visitMethodInsn(opcode, owner, name, desc); } @@ -383,12 +368,8 @@ public class AnalyzerAdapter 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) { if (mv != null) { mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); } @@ -471,12 +452,8 @@ public class AnalyzerAdapter 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) { if (mv != null) { mv.visitTableSwitchInsn(min, max, dflt, labels); } @@ -486,11 +463,8 @@ public class AnalyzerAdapter 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) { if (mv != null) { mv.visitLookupSwitchInsn(dflt, keys, labels); } @@ -539,40 +513,40 @@ public class AnalyzerAdapter extends MethodVisitor { private void pushDesc(final String desc) { int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; switch (desc.charAt(index)) { - case 'V': - return; - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - push(Opcodes.INTEGER); - return; - case 'F': - push(Opcodes.FLOAT); - return; - case 'J': - push(Opcodes.LONG); - push(Opcodes.TOP); - return; - case 'D': - push(Opcodes.DOUBLE); - push(Opcodes.TOP); - return; - case '[': - if (index == 0) { - push(desc); - } else { - push(desc.substring(index, desc.length())); - } - break; - // case 'L': - default: - if (index == 0) { - push(desc.substring(1, desc.length() - 1)); - } else { - push(desc.substring(index + 1, desc.length() - 1)); - } + case 'V': + return; + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + push(Opcodes.INTEGER); + return; + case 'F': + push(Opcodes.FLOAT); + return; + case 'J': + push(Opcodes.LONG); + push(Opcodes.TOP); + return; + case 'D': + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + return; + case '[': + if (index == 0) { + push(desc); + } else { + push(desc.substring(index, desc.length())); + } + break; + // case 'L': + default: + if (index == 0) { + push(desc.substring(1, desc.length() - 1)); + } else { + push(desc.substring(index + 1, desc.length() - 1)); + } } } @@ -611,364 +585,364 @@ public class AnalyzerAdapter extends MethodVisitor { } Object 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(Opcodes.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: - push(Opcodes.INTEGER); - break; - case Opcodes.LCONST_0: - case Opcodes.LCONST_1: - push(Opcodes.LONG); - push(Opcodes.TOP); - break; - case Opcodes.FCONST_0: - case Opcodes.FCONST_1: - case Opcodes.FCONST_2: - push(Opcodes.FLOAT); - break; - case Opcodes.DCONST_0: - case Opcodes.DCONST_1: - push(Opcodes.DOUBLE); - push(Opcodes.TOP); - break; - case Opcodes.ILOAD: - case Opcodes.FLOAD: - case Opcodes.ALOAD: - push(get(iarg)); - break; - case Opcodes.LLOAD: - case Opcodes.DLOAD: - push(get(iarg)); - push(Opcodes.TOP); - break; - case Opcodes.IALOAD: - case Opcodes.BALOAD: - case Opcodes.CALOAD: - case Opcodes.SALOAD: - pop(2); - push(Opcodes.INTEGER); - break; - case Opcodes.LALOAD: - case Opcodes.D2L: - pop(2); - push(Opcodes.LONG); - push(Opcodes.TOP); - break; - case Opcodes.FALOAD: - pop(2); - push(Opcodes.FLOAT); - break; - case Opcodes.DALOAD: - case Opcodes.L2D: - pop(2); - push(Opcodes.DOUBLE); - push(Opcodes.TOP); - break; - case Opcodes.AALOAD: - pop(1); - t1 = pop(); - if (t1 instanceof String) { - pushDesc(((String) t1).substring(1)); - } else { - push("java/lang/Object"); - } - break; - case Opcodes.ISTORE: - case Opcodes.FSTORE: - case Opcodes.ASTORE: - t1 = pop(); - set(iarg, t1); - if (iarg > 0) { - t2 = get(iarg - 1); - if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { - set(iarg - 1, Opcodes.TOP); - } - } - break; - case Opcodes.LSTORE: - case Opcodes.DSTORE: - pop(1); - t1 = pop(); - set(iarg, t1); - set(iarg + 1, Opcodes.TOP); - if (iarg > 0) { - t2 = get(iarg - 1); - if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { - set(iarg - 1, Opcodes.TOP); - } + 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(Opcodes.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: + push(Opcodes.INTEGER); + break; + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + push(Opcodes.LONG); + push(Opcodes.TOP); + break; + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + push(Opcodes.FLOAT); + break; + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + break; + case Opcodes.ILOAD: + case Opcodes.FLOAD: + case Opcodes.ALOAD: + push(get(iarg)); + break; + case Opcodes.LLOAD: + case Opcodes.DLOAD: + push(get(iarg)); + push(Opcodes.TOP); + break; + case Opcodes.IALOAD: + case Opcodes.BALOAD: + case Opcodes.CALOAD: + case Opcodes.SALOAD: + pop(2); + push(Opcodes.INTEGER); + break; + case Opcodes.LALOAD: + case Opcodes.D2L: + pop(2); + push(Opcodes.LONG); + push(Opcodes.TOP); + break; + case Opcodes.FALOAD: + pop(2); + push(Opcodes.FLOAT); + break; + case Opcodes.DALOAD: + case Opcodes.L2D: + pop(2); + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + break; + case Opcodes.AALOAD: + pop(1); + t1 = pop(); + if (t1 instanceof String) { + pushDesc(((String) t1).substring(1)); + } else { + push("java/lang/Object"); + } + break; + case Opcodes.ISTORE: + case Opcodes.FSTORE: + case Opcodes.ASTORE: + t1 = pop(); + set(iarg, t1); + if (iarg > 0) { + t2 = get(iarg - 1); + if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { + set(iarg - 1, Opcodes.TOP); } - 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(Opcodes.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(Opcodes.LONG); - push(Opcodes.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(Opcodes.FLOAT); - break; - case Opcodes.DADD: - case Opcodes.DSUB: - case Opcodes.DMUL: - case Opcodes.DDIV: - case Opcodes.DREM: - pop(4); - push(Opcodes.DOUBLE); - push(Opcodes.TOP); - break; - case Opcodes.LSHL: - case Opcodes.LSHR: - case Opcodes.LUSHR: - pop(3); - push(Opcodes.LONG); - push(Opcodes.TOP); - break; - case Opcodes.IINC: - set(iarg, Opcodes.INTEGER); - break; - case Opcodes.I2L: - case Opcodes.F2L: - pop(1); - push(Opcodes.LONG); - push(Opcodes.TOP); - break; - case Opcodes.I2F: - pop(1); - push(Opcodes.FLOAT); - break; - case Opcodes.I2D: - case Opcodes.F2D: - pop(1); - push(Opcodes.DOUBLE); - push(Opcodes.TOP); - break; - case Opcodes.F2I: - case Opcodes.ARRAYLENGTH: - case Opcodes.INSTANCEOF: - pop(1); - push(Opcodes.INTEGER); - break; - case Opcodes.LCMP: - case Opcodes.DCMPL: - case Opcodes.DCMPG: - pop(4); - push(Opcodes.INTEGER); - break; - case Opcodes.JSR: - case Opcodes.RET: - throw new RuntimeException("JSR/RET are not supported"); - case Opcodes.GETSTATIC: - pushDesc(sarg); - break; - case Opcodes.PUTSTATIC: - pop(sarg); - break; - case Opcodes.GETFIELD: - pop(1); - pushDesc(sarg); - break; - case Opcodes.PUTFIELD: - pop(sarg); - pop(); - break; - case Opcodes.NEW: - push(labels.get(0)); - break; - case Opcodes.NEWARRAY: - pop(); - switch (iarg) { - case Opcodes.T_BOOLEAN: - pushDesc("[Z"); - break; - case Opcodes.T_CHAR: - pushDesc("[C"); - break; - case Opcodes.T_BYTE: - pushDesc("[B"); - break; - case Opcodes.T_SHORT: - pushDesc("[S"); - break; - case Opcodes.T_INT: - pushDesc("[I"); - break; - case Opcodes.T_FLOAT: - pushDesc("[F"); - break; - case Opcodes.T_DOUBLE: - pushDesc("[D"); - break; - // case Opcodes.T_LONG: - default: - pushDesc("[J"); - break; + } + break; + case Opcodes.LSTORE: + case Opcodes.DSTORE: + pop(1); + t1 = pop(); + set(iarg, t1); + set(iarg + 1, Opcodes.TOP); + if (iarg > 0) { + t2 = get(iarg - 1); + if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { + set(iarg - 1, Opcodes.TOP); } - break; - case Opcodes.ANEWARRAY: - pop(); - pushDesc("[" + Type.getObjectType(sarg)); - break; - case Opcodes.CHECKCAST: - pop(); - pushDesc(Type.getObjectType(sarg).getDescriptor()); - break; - // case Opcodes.MULTIANEWARRAY: + } + 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(Opcodes.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(Opcodes.LONG); + push(Opcodes.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(Opcodes.FLOAT); + break; + case Opcodes.DADD: + case Opcodes.DSUB: + case Opcodes.DMUL: + case Opcodes.DDIV: + case Opcodes.DREM: + pop(4); + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + break; + case Opcodes.LSHL: + case Opcodes.LSHR: + case Opcodes.LUSHR: + pop(3); + push(Opcodes.LONG); + push(Opcodes.TOP); + break; + case Opcodes.IINC: + set(iarg, Opcodes.INTEGER); + break; + case Opcodes.I2L: + case Opcodes.F2L: + pop(1); + push(Opcodes.LONG); + push(Opcodes.TOP); + break; + case Opcodes.I2F: + pop(1); + push(Opcodes.FLOAT); + break; + case Opcodes.I2D: + case Opcodes.F2D: + pop(1); + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + break; + case Opcodes.F2I: + case Opcodes.ARRAYLENGTH: + case Opcodes.INSTANCEOF: + pop(1); + push(Opcodes.INTEGER); + break; + case Opcodes.LCMP: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + pop(4); + push(Opcodes.INTEGER); + break; + case Opcodes.JSR: + case Opcodes.RET: + throw new RuntimeException("JSR/RET are not supported"); + case Opcodes.GETSTATIC: + pushDesc(sarg); + break; + case Opcodes.PUTSTATIC: + pop(sarg); + break; + case Opcodes.GETFIELD: + pop(1); + pushDesc(sarg); + break; + case Opcodes.PUTFIELD: + pop(sarg); + pop(); + break; + case Opcodes.NEW: + push(labels.get(0)); + break; + case Opcodes.NEWARRAY: + pop(); + switch (iarg) { + case Opcodes.T_BOOLEAN: + pushDesc("[Z"); + break; + case Opcodes.T_CHAR: + pushDesc("[C"); + break; + case Opcodes.T_BYTE: + pushDesc("[B"); + break; + case Opcodes.T_SHORT: + pushDesc("[S"); + break; + case Opcodes.T_INT: + pushDesc("[I"); + break; + case Opcodes.T_FLOAT: + pushDesc("[F"); + break; + case Opcodes.T_DOUBLE: + pushDesc("[D"); + break; + // case Opcodes.T_LONG: default: - pop(iarg); - pushDesc(sarg); + pushDesc("[J"); break; + } + break; + case Opcodes.ANEWARRAY: + pop(); + pushDesc("[" + Type.getObjectType(sarg)); + break; + case Opcodes.CHECKCAST: + pop(); + pushDesc(Type.getObjectType(sarg).getDescriptor()); + break; + // case Opcodes.MULTIANEWARRAY: + default: + pop(iarg); + pushDesc(sarg); + break; } labels = null; } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java index 23776dd7a4281067164c3d2c7811744a60f57f03..a04a643d18b2dcec8834bd55d36f11d4c3900b17 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java @@ -75,7 +75,7 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { private int maxSize; public CodeSizeEvaluator(final MethodVisitor mv) { - this(Opcodes.ASM4, mv); + this(Opcodes.ASM5, mv); } protected CodeSizeEvaluator(final int api, final MethodVisitor mv) { @@ -140,12 +140,8 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { } @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) { minSize += 3; maxSize += 3; if (mv != null) { @@ -154,12 +150,8 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { } @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) { if (opcode == INVOKEINTERFACE) { minSize += 5; maxSize += 5; @@ -173,12 +165,8 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { } @Override - public void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs) - { + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { minSize += 5; maxSize += 5; if (mv != null) { @@ -228,12 +216,8 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { } @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) { minSize += 13 + labels.length * 4; maxSize += 16 + labels.length * 4; if (mv != null) { @@ -242,11 +226,8 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { } @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) { minSize += 9 + keys.length * 8; maxSize += 12 + keys.length * 8; if (mv != null) { diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java index d86c1981d2790668a71540bd7e30f04977500af8..7e30acbbe723165b8e5c5e889c77b392a73a4b43 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java @@ -30,7 +30,6 @@ * * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom - * Copyright (c) 2011 Google * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -99,7 +98,8 @@ import jdk.internal.org.objectweb.asm.Type; * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw); * mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class)); * mg.push("Hello world!"); - * mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)")); + * mg.invokeVirtual(Type.getType(PrintStream.class), + * Method.getMethod("void println (String)")); * mg.returnValue(); * mg.endMethod(); * @@ -117,35 +117,48 @@ public class GeneratorAdapter extends LocalVariablesSorter { private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte"); - private static final Type BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean"); + private static final Type BOOLEAN_TYPE = Type + .getObjectType("java/lang/Boolean"); - private static final Type SHORT_TYPE = Type.getObjectType("java/lang/Short"); + private static final Type SHORT_TYPE = Type + .getObjectType("java/lang/Short"); - private static final Type CHARACTER_TYPE = Type.getObjectType("java/lang/Character"); + private static final Type CHARACTER_TYPE = Type + .getObjectType("java/lang/Character"); - private static final Type INTEGER_TYPE = Type.getObjectType("java/lang/Integer"); + private static final Type INTEGER_TYPE = Type + .getObjectType("java/lang/Integer"); - private static final Type FLOAT_TYPE = Type.getObjectType("java/lang/Float"); + private static final Type FLOAT_TYPE = Type + .getObjectType("java/lang/Float"); private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long"); - private static final Type DOUBLE_TYPE = Type.getObjectType("java/lang/Double"); + private static final Type DOUBLE_TYPE = Type + .getObjectType("java/lang/Double"); - private static final Type NUMBER_TYPE = Type.getObjectType("java/lang/Number"); + private static final Type NUMBER_TYPE = Type + .getObjectType("java/lang/Number"); - private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object"); + private static final Type OBJECT_TYPE = Type + .getObjectType("java/lang/Object"); - private static final Method BOOLEAN_VALUE = Method.getMethod("boolean booleanValue()"); + private static final Method BOOLEAN_VALUE = Method + .getMethod("boolean booleanValue()"); - private static final Method CHAR_VALUE = Method.getMethod("char charValue()"); + private static final Method CHAR_VALUE = Method + .getMethod("char charValue()"); private static final Method INT_VALUE = Method.getMethod("int intValue()"); - private static final Method FLOAT_VALUE = Method.getMethod("float floatValue()"); + private static final Method FLOAT_VALUE = Method + .getMethod("float floatValue()"); - private static final Method LONG_VALUE = Method.getMethod("long longValue()"); + private static final Method LONG_VALUE = Method + .getMethod("long longValue()"); - private static final Method DOUBLE_VALUE = Method.getMethod("double doubleValue()"); + private static final Method DOUBLE_VALUE = Method + .getMethod("double doubleValue()"); /** * Constant for the {@link #math math} method. @@ -263,37 +276,37 @@ public class GeneratorAdapter extends LocalVariablesSorter { * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)} * version. * - * @param mv the method visitor to which this adapter delegates calls. - * @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 Type}). + * @param mv + * the method visitor to which this adapter delegates calls. + * @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 Type}). */ - public GeneratorAdapter( - final MethodVisitor mv, - final int access, - final String name, - final String desc) - { - this(Opcodes.ASM4, mv, access, name, desc); + public GeneratorAdapter(final MethodVisitor mv, final int access, + final String name, final String desc) { + this(Opcodes.ASM5, mv, access, name, desc); } /** * Creates a new {@link GeneratorAdapter}. * - * @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 adapter delegates calls. - * @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 Type}). - */ - protected GeneratorAdapter( - final int api, - final MethodVisitor mv, - final int access, - final String name, - final String desc) - { + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param mv + * the method visitor to which this adapter delegates calls. + * @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 Type}). + */ + protected GeneratorAdapter(final int api, final MethodVisitor mv, + final int access, final String name, final String desc) { super(api, access, desc, mv); this.access = access; this.returnType = Type.getReturnType(desc); @@ -306,15 +319,15 @@ public class GeneratorAdapter extends LocalVariablesSorter { * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)} * version. * - * @param access access flags of the adapted method. - * @param method the adapted method. - * @param mv the method visitor to which this adapter delegates calls. - */ - public GeneratorAdapter( - final int access, - final Method method, - final MethodVisitor mv) - { + * @param access + * access flags of the adapted method. + * @param method + * the adapted method. + * @param mv + * the method visitor to which this adapter delegates calls. + */ + public GeneratorAdapter(final int access, final Method method, + final MethodVisitor mv) { this(mv, access, null, method.getDescriptor()); } @@ -324,32 +337,31 @@ public class GeneratorAdapter extends LocalVariablesSorter { * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)} * version. * - * @param access access flags of the adapted method. - * @param method the adapted method. - * @param signature the signature of the adapted method (may be - * null). - * @param exceptions the exceptions thrown by the adapted method (may be - * null). - * @param cv the class visitor to which this adapter delegates calls. - */ - public GeneratorAdapter( - final int access, - final Method method, - final String signature, - final Type[] exceptions, - final ClassVisitor cv) - { - this(access, method, cv.visitMethod(access, - method.getName(), - method.getDescriptor(), - signature, - getInternalNames(exceptions))); + * @param access + * access flags of the adapted method. + * @param method + * the adapted method. + * @param signature + * the signature of the adapted method (may be null). + * @param exceptions + * the exceptions thrown by the adapted method (may be + * null). + * @param cv + * the class visitor to which this adapter delegates calls. + */ + public GeneratorAdapter(final int access, final Method method, + final String signature, final Type[] exceptions, + final ClassVisitor cv) { + this(access, method, cv + .visitMethod(access, method.getName(), method.getDescriptor(), + signature, getInternalNames(exceptions))); } /** * Returns the internal names of the given types. * - * @param types a set of types. + * @param types + * a set of types. * @return the internal names of the given types. */ private static String[] getInternalNames(final Type[] types) { @@ -370,7 +382,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to push the given value on the stack. * - * @param value the value to be pushed on the stack. + * @param value + * the value to be pushed on the stack. */ public void push(final boolean value) { push(value ? 1 : 0); @@ -379,7 +392,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to push the given value on the stack. * - * @param value the value to be pushed on the stack. + * @param value + * the value to be pushed on the stack. */ public void push(final int value) { if (value >= -1 && value <= 5) { @@ -396,7 +410,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to push the given value on the stack. * - * @param value the value to be pushed on the stack. + * @param value + * the value to be pushed on the stack. */ public void push(final long value) { if (value == 0L || value == 1L) { @@ -409,7 +424,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to push the given value on the stack. * - * @param value the value to be pushed on the stack. + * @param value + * the value to be pushed on the stack. */ public void push(final float value) { int bits = Float.floatToIntBits(value); @@ -423,7 +439,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to push the given value on the stack. * - * @param value the value to be pushed on the stack. + * @param value + * the value to be pushed on the stack. */ public void push(final double value) { long bits = Double.doubleToLongBits(value); @@ -437,7 +454,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to push the given value on the stack. * - * @param value the value to be pushed on the stack. May be null. + * @param value + * the value to be pushed on the stack. May be null. */ public void push(final String value) { if (value == null) { @@ -450,63 +468,48 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to push the given value on the stack. * - * @param value the value to be pushed on the stack. + * @param value + * the value to be pushed on the stack. */ public void push(final Type value) { if (value == null) { mv.visitInsn(Opcodes.ACONST_NULL); } else { switch (value.getSort()) { - case Type.BOOLEAN: - mv.visitFieldInsn(Opcodes.GETSTATIC, - "java/lang/Boolean", - "TYPE", - CLDESC); - break; - case Type.CHAR: - mv.visitFieldInsn(Opcodes.GETSTATIC, - "java/lang/Character", - "TYPE", - CLDESC); - break; - case Type.BYTE: - mv.visitFieldInsn(Opcodes.GETSTATIC, - "java/lang/Byte", - "TYPE", - CLDESC); - break; - case Type.SHORT: - mv.visitFieldInsn(Opcodes.GETSTATIC, - "java/lang/Short", - "TYPE", - CLDESC); - break; - case Type.INT: - mv.visitFieldInsn(Opcodes.GETSTATIC, - "java/lang/Integer", - "TYPE", - CLDESC); - break; - case Type.FLOAT: - mv.visitFieldInsn(Opcodes.GETSTATIC, - "java/lang/Float", - "TYPE", - CLDESC); - break; - case Type.LONG: - mv.visitFieldInsn(Opcodes.GETSTATIC, - "java/lang/Long", - "TYPE", - CLDESC); - break; - case Type.DOUBLE: - mv.visitFieldInsn(Opcodes.GETSTATIC, - "java/lang/Double", - "TYPE", - CLDESC); - break; - default: - mv.visitLdcInsn(value); + case Type.BOOLEAN: + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", + "TYPE", CLDESC); + break; + case Type.CHAR: + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character", + "TYPE", CLDESC); + break; + case Type.BYTE: + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE", + CLDESC); + break; + case Type.SHORT: + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE", + CLDESC); + break; + case Type.INT: + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", + "TYPE", CLDESC); + break; + case Type.FLOAT: + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE", + CLDESC); + break; + case Type.LONG: + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE", + CLDESC); + break; + case Type.DOUBLE: + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double", + "TYPE", CLDESC); + break; + default: + mv.visitLdcInsn(value); } } } @@ -514,7 +517,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to push a handle on the stack. * - * @param handle the handle to be pushed on the stack. + * @param handle + * the handle to be pushed on the stack. */ public void push(final Handle handle) { mv.visitLdcInsn(handle); @@ -528,7 +532,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Returns the index of the given method argument in the frame's local * variables array. * - * @param arg the index of a method argument. + * @param arg + * the index of a method argument. * @return the index of the given method argument in the frame's local * variables array. */ @@ -543,8 +548,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to push a local variable on the stack. * - * @param type the type of the local variable to be loaded. - * @param index an index in the frame's local variables array. + * @param type + * the type of the local variable to be loaded. + * @param index + * an index in the frame's local variables array. */ private void loadInsn(final Type type, final int index) { mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index); @@ -554,8 +561,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to store the top stack value in a local * variable. * - * @param type the type of the local variable to be stored. - * @param index an index in the frame's local variables array. + * @param type + * the type of the local variable to be stored. + * @param index + * an index in the frame's local variables array. */ private void storeInsn(final Type type, final int index) { mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index); @@ -566,7 +575,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { */ public void loadThis() { if ((access & Opcodes.ACC_STATIC) != 0) { - throw new IllegalStateException("no 'this' pointer within static method"); + throw new IllegalStateException( + "no 'this' pointer within static method"); } mv.visitVarInsn(Opcodes.ALOAD, 0); } @@ -574,7 +584,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to load the given method argument on the stack. * - * @param arg the index of a method argument. + * @param arg + * the index of a method argument. */ public void loadArg(final int arg) { loadInsn(argumentTypes[arg], getArgIndex(arg)); @@ -584,8 +595,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instructions to load the given method arguments on the * stack. * - * @param arg the index of the first method argument to be loaded. - * @param count the number of method arguments to be loaded. + * @param arg + * the index of the first method argument to be loaded. + * @param count + * the number of method arguments to be loaded. */ public void loadArgs(final int arg, final int count) { int index = getArgIndex(arg); @@ -623,7 +636,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to store the top stack value in the given * method argument. * - * @param arg the index of a method argument. + * @param arg + * the index of a method argument. */ public void storeArg(final int arg) { storeInsn(argumentTypes[arg], getArgIndex(arg)); @@ -636,8 +650,9 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Returns the type of the given local variable. * - * @param local a local variable identifier, as returned by - * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. + * @param local + * a local variable identifier, as returned by + * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. * @return the type of the given local variable. */ public Type getLocalType(final int local) { @@ -656,8 +671,9 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to load the given local variable on the stack. * - * @param local a local variable identifier, as returned by - * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. + * @param local + * a local variable identifier, as returned by + * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. */ public void loadLocal(final int local) { loadInsn(getLocalType(local), local); @@ -666,9 +682,11 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to load the given local variable on the stack. * - * @param local a local variable identifier, as returned by - * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. - * @param type the type of this local variable. + * @param local + * a local variable identifier, as returned by + * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. + * @param type + * the type of this local variable. */ public void loadLocal(final int local, final Type type) { setLocalType(local, type); @@ -679,8 +697,9 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to store the top stack value in the given local * variable. * - * @param local a local variable identifier, as returned by - * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. + * @param local + * a local variable identifier, as returned by + * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. */ public void storeLocal(final int local) { storeInsn(getLocalType(local), local); @@ -690,9 +709,11 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to store the top stack value in the given local * variable. * - * @param local a local variable identifier, as returned by - * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. - * @param type the type of this local variable. + * @param local + * a local variable identifier, as returned by + * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. + * @param type + * the type of this local variable. */ public void storeLocal(final int local, final Type type) { setLocalType(local, type); @@ -702,7 +723,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to load an element from an array. * - * @param type the type of the array element to be loaded. + * @param type + * the type of the array element to be loaded. */ public void arrayLoad(final Type type) { mv.visitInsn(type.getOpcode(Opcodes.IALOAD)); @@ -711,7 +733,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to store an element in an array. * - * @param type the type of the array element to be stored. + * @param type + * the type of the array element to be stored. */ public void arrayStore(final Type type) { mv.visitInsn(type.getOpcode(Opcodes.IASTORE)); @@ -787,8 +810,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instructions to swap the top two stack values. * - * @param prev type of the top - 1 stack value. - * @param type type of the top stack value. + * @param prev + * type of the top - 1 stack value. + * @param type + * type of the top stack value. */ public void swap(final Type prev, final Type type) { if (type.getSize() == 1) { @@ -817,9 +842,11 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to do the specified mathematical or logical * operation. * - * @param op a mathematical or logical operation. Must be one of ADD, SUB, - * MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR. - * @param type the type of the operand(s) for this operation. + * @param op + * a mathematical or logical operation. Must be one of ADD, SUB, + * MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR. + * @param type + * the type of the operand(s) for this operation. */ public void math(final int op, final Type type) { mv.visitInsn(type.getOpcode(op)); @@ -837,8 +864,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to increment the given local variable. * - * @param local the local variable to be incremented. - * @param amount the amount by which the local variable must be incremented. + * @param local + * the local variable to be incremented. + * @param amount + * the amount by which the local variable must be incremented. */ public void iinc(final int local, final int amount) { mv.visitIincInsn(local, amount); @@ -848,8 +877,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instructions to cast a numerical value from one type to * another. * - * @param from the type of the top stack value - * @param to the type into which this value must be cast. + * @param from + * the type of the top stack value + * @param to + * the type into which this value must be cast. */ public void cast(final Type from, final Type to) { if (from != to) { @@ -904,22 +935,22 @@ public class GeneratorAdapter extends LocalVariablesSorter { private static Type getBoxedType(final Type type) { switch (type.getSort()) { - case Type.BYTE: - return BYTE_TYPE; - case Type.BOOLEAN: - return BOOLEAN_TYPE; - case Type.SHORT: - return SHORT_TYPE; - case Type.CHAR: - return CHARACTER_TYPE; - case Type.INT: - return INTEGER_TYPE; - case Type.FLOAT: - return FLOAT_TYPE; - case Type.LONG: - return LONG_TYPE; - case Type.DOUBLE: - return DOUBLE_TYPE; + case Type.BYTE: + return BYTE_TYPE; + case Type.BOOLEAN: + return BOOLEAN_TYPE; + case Type.SHORT: + return SHORT_TYPE; + case Type.CHAR: + return CHARACTER_TYPE; + case Type.INT: + return INTEGER_TYPE; + case Type.FLOAT: + return FLOAT_TYPE; + case Type.LONG: + return LONG_TYPE; + case Type.DOUBLE: + return DOUBLE_TYPE; } return type; } @@ -928,7 +959,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instructions to box the top stack value. This value is * replaced by its boxed equivalent on top of the stack. * - * @param type the type of the top stack value. + * @param type + * the type of the top stack value. */ public void box(final Type type) { if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { @@ -949,8 +981,7 @@ public class GeneratorAdapter extends LocalVariablesSorter { dupX1(); swap(); } - invokeConstructor(boxed, new Method("", - Type.VOID_TYPE, + invokeConstructor(boxed, new Method("", Type.VOID_TYPE, new Type[] { type })); } } @@ -960,7 +991,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { * valueOf() method. This value is replaced by its boxed equivalent on top * of the stack. * - * @param type the type of the top stack value. + * @param type + * the type of the top stack value. */ public void valueOf(final Type type) { if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { @@ -970,8 +1002,7 @@ public class GeneratorAdapter extends LocalVariablesSorter { push((String) null); } else { Type boxed = getBoxedType(type); - invokeStatic(boxed, new Method("valueOf", - boxed, + invokeStatic(boxed, new Method("valueOf", boxed, new Type[] { type })); } } @@ -980,35 +1011,36 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instructions to unbox the top stack value. This value is * replaced by its unboxed equivalent on top of the stack. * - * @param type the type of the top stack value. + * @param type + * the type of the top stack value. */ public void unbox(final Type type) { Type t = NUMBER_TYPE; Method sig = null; switch (type.getSort()) { - case Type.VOID: - return; - case Type.CHAR: - t = CHARACTER_TYPE; - sig = CHAR_VALUE; - break; - case Type.BOOLEAN: - t = BOOLEAN_TYPE; - sig = BOOLEAN_VALUE; - break; - case Type.DOUBLE: - sig = DOUBLE_VALUE; - break; - case Type.FLOAT: - sig = FLOAT_VALUE; - break; - case Type.LONG: - sig = LONG_VALUE; - break; - case Type.INT: - case Type.SHORT: - case Type.BYTE: - sig = INT_VALUE; + case Type.VOID: + return; + case Type.CHAR: + t = CHARACTER_TYPE; + sig = CHAR_VALUE; + break; + case Type.BOOLEAN: + t = BOOLEAN_TYPE; + sig = BOOLEAN_VALUE; + break; + case Type.DOUBLE: + sig = DOUBLE_VALUE; + break; + case Type.FLOAT: + sig = FLOAT_VALUE; + break; + case Type.LONG: + sig = LONG_VALUE; + break; + case Type.INT: + case Type.SHORT: + case Type.BYTE: + sig = INT_VALUE; } if (sig == null) { checkCast(type); @@ -1034,7 +1066,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Marks the current code position with the given label. * - * @param label a label. + * @param label + * a label. */ public void mark(final Label label) { mv.visitLabel(label); @@ -1055,58 +1088,63 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instructions to jump to a label based on the comparison of * the top two stack values. * - * @param type the type of the top two stack values. - * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT, - * LE. - * @param label where to jump if the comparison result is true. + * @param type + * the type of the top two stack values. + * @param mode + * how these values must be compared. One of EQ, NE, LT, GE, GT, + * LE. + * @param label + * where to jump if the comparison result is true. */ public void ifCmp(final Type type, final int mode, final Label label) { switch (type.getSort()) { - case Type.LONG: - mv.visitInsn(Opcodes.LCMP); + case Type.LONG: + mv.visitInsn(Opcodes.LCMP); + break; + case Type.DOUBLE: + mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPL + : Opcodes.DCMPG); + break; + case Type.FLOAT: + mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPL + : Opcodes.FCMPG); + break; + case Type.ARRAY: + case Type.OBJECT: + switch (mode) { + case EQ: + mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label); + return; + case NE: + mv.visitJumpInsn(Opcodes.IF_ACMPNE, label); + return; + } + throw new IllegalArgumentException("Bad comparison for type " + + type); + default: + int intOp = -1; + switch (mode) { + case EQ: + intOp = Opcodes.IF_ICMPEQ; break; - case Type.DOUBLE: - mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPG : Opcodes.DCMPL); + case NE: + intOp = Opcodes.IF_ICMPNE; break; - case Type.FLOAT: - mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPG : Opcodes.FCMPL); + case GE: + intOp = Opcodes.IF_ICMPGE; break; - case Type.ARRAY: - case Type.OBJECT: - switch (mode) { - case EQ: - mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label); - return; - case NE: - mv.visitJumpInsn(Opcodes.IF_ACMPNE, label); - return; - } - throw new IllegalArgumentException("Bad comparison for type " - + type); - default: - int intOp = -1; - switch (mode) { - case EQ: - intOp = Opcodes.IF_ICMPEQ; - break; - case NE: - intOp = Opcodes.IF_ICMPNE; - break; - case GE: - intOp = Opcodes.IF_ICMPGE; - break; - case LT: - intOp = Opcodes.IF_ICMPLT; - break; - case LE: - intOp = Opcodes.IF_ICMPLE; - break; - case GT: - intOp = Opcodes.IF_ICMPGT; - break; - } - mv.visitJumpInsn(intOp, label); - return; + case LT: + intOp = Opcodes.IF_ICMPLT; + break; + case LE: + intOp = Opcodes.IF_ICMPLE; + break; + case GT: + intOp = Opcodes.IF_ICMPGT; + break; + } + mv.visitJumpInsn(intOp, label); + return; } mv.visitJumpInsn(mode, label); } @@ -1115,9 +1153,11 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instructions to jump to a label based on the comparison of * the top two integer stack values. * - * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT, - * LE. - * @param label where to jump if the comparison result is true. + * @param mode + * how these values must be compared. One of EQ, NE, LT, GE, GT, + * LE. + * @param label + * where to jump if the comparison result is true. */ public void ifICmp(final int mode, final Label label) { ifCmp(Type.INT_TYPE, mode, label); @@ -1127,9 +1167,11 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instructions to jump to a label based on the comparison of * the top integer stack value with zero. * - * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT, - * LE. - * @param label where to jump if the comparison result is true. + * @param mode + * how these values must be compared. One of EQ, NE, LT, GE, GT, + * LE. + * @param label + * where to jump if the comparison result is true. */ public void ifZCmp(final int mode, final Label label) { mv.visitJumpInsn(mode, label); @@ -1139,7 +1181,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to jump to the given label if the top stack * value is null. * - * @param label where to jump if the condition is true. + * @param label + * where to jump if the condition is true. */ public void ifNull(final Label label) { mv.visitJumpInsn(Opcodes.IFNULL, label); @@ -1149,7 +1192,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to jump to the given label if the top stack * value is not null. * - * @param label where to jump if the condition is true. + * @param label + * where to jump if the condition is true. */ public void ifNonNull(final Label label) { mv.visitJumpInsn(Opcodes.IFNONNULL, label); @@ -1158,7 +1202,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to jump to the given label. * - * @param label where to jump if the condition is true. + * @param label + * where to jump if the condition is true. */ public void goTo(final Label label) { mv.visitJumpInsn(Opcodes.GOTO, label); @@ -1167,8 +1212,9 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates a RET instruction. * - * @param local a local variable identifier, as returned by - * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. + * @param local + * a local variable identifier, as returned by + * {@link LocalVariablesSorter#newLocal(Type) newLocal()}. */ public void ret(final int local) { mv.visitVarInsn(Opcodes.RET, local); @@ -1177,13 +1223,13 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instructions for a switch statement. * - * @param keys the switch case keys. - * @param generator a generator to generate the code for the switch cases. + * @param keys + * the switch case keys. + * @param generator + * a generator to generate the code for the switch cases. */ - public void tableSwitch( - final int[] keys, - final TableSwitchGenerator generator) - { + public void tableSwitch(final int[] keys, + final TableSwitchGenerator generator) { float density; if (keys.length == 0) { density = 0; @@ -1197,19 +1243,20 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instructions for a switch statement. * - * @param keys the switch case keys. - * @param generator a generator to generate the code for the switch cases. - * @param useTable true to use a TABLESWITCH instruction, or - * false to use a LOOKUPSWITCH instruction. - */ - public void tableSwitch( - final int[] keys, - final TableSwitchGenerator generator, - final boolean useTable) - { + * @param keys + * the switch case keys. + * @param generator + * a generator to generate the code for the switch cases. + * @param useTable + * true to use a TABLESWITCH instruction, or + * false to use a LOOKUPSWITCH instruction. + */ + public void tableSwitch(final int[] keys, + final TableSwitchGenerator generator, final boolean useTable) { for (int i = 1; i < keys.length; ++i) { if (keys[i] < keys[i - 1]) { - throw new IllegalArgumentException("keys must be sorted ascending"); + throw new IllegalArgumentException( + "keys must be sorted ascending"); } } Label def = newLabel(); @@ -1264,20 +1311,18 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates a get field or set field instruction. * - * @param opcode the instruction's opcode. - * @param ownerType the class in which the field is defined. - * @param name the name of the field. - * @param fieldType the type of the field. - */ - private void fieldInsn( - final int opcode, - final Type ownerType, - final String name, - final Type fieldType) - { - mv.visitFieldInsn(opcode, - ownerType.getInternalName(), - name, + * @param opcode + * the instruction's opcode. + * @param ownerType + * the class in which the field is defined. + * @param name + * the name of the field. + * @param fieldType + * the type of the field. + */ + private void fieldInsn(final int opcode, final Type ownerType, + final String name, final Type fieldType) { + mv.visitFieldInsn(opcode, ownerType.getInternalName(), name, fieldType.getDescriptor()); } @@ -1285,24 +1330,28 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to push the value of a static field on the * stack. * - * @param owner the class in which the field is defined. - * @param name the name of the field. - * @param type the type of the field. - */ - public void getStatic(final Type owner, final String name, final Type type) - { + * @param owner + * the class in which the field is defined. + * @param name + * the name of the field. + * @param type + * the type of the field. + */ + public void getStatic(final Type owner, final String name, final Type type) { fieldInsn(Opcodes.GETSTATIC, owner, name, type); } /** * Generates the instruction to store the top stack value in a static field. * - * @param owner the class in which the field is defined. - * @param name the name of the field. - * @param type the type of the field. - */ - public void putStatic(final Type owner, final String name, final Type type) - { + * @param owner + * the class in which the field is defined. + * @param name + * the name of the field. + * @param type + * the type of the field. + */ + public void putStatic(final Type owner, final String name, final Type type) { fieldInsn(Opcodes.PUTSTATIC, owner, name, type); } @@ -1310,9 +1359,12 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to push the value of a non static field on the * stack. * - * @param owner the class in which the field is defined. - * @param name the name of the field. - * @param type the type of the field. + * @param owner + * the class in which the field is defined. + * @param name + * the name of the field. + * @param type + * the type of the field. */ public void getField(final Type owner, final String name, final Type type) { fieldInsn(Opcodes.GETFIELD, owner, name, type); @@ -1322,9 +1374,12 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to store the top stack value in a non static * field. * - * @param owner the class in which the field is defined. - * @param name the name of the field. - * @param type the type of the field. + * @param owner + * the class in which the field is defined. + * @param name + * the name of the field. + * @param type + * the type of the field. */ public void putField(final Type owner, final String name, final Type type) { fieldInsn(Opcodes.PUTFIELD, owner, name, type); @@ -1337,29 +1392,28 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates an invoke method instruction. * - * @param opcode the instruction's opcode. - * @param type the class in which the method is defined. - * @param method the method to be invoked. - */ - private void invokeInsn( - final int opcode, - final Type type, - final Method method) - { - String owner = type.getSort() == Type.ARRAY - ? type.getDescriptor() + * @param opcode + * the instruction's opcode. + * @param type + * the class in which the method is defined. + * @param method + * the method to be invoked. + */ + private void invokeInsn(final int opcode, final Type type, + final Method method) { + String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName(); - mv.visitMethodInsn(opcode, - owner, - method.getName(), + mv.visitMethodInsn(opcode, owner, method.getName(), method.getDescriptor()); } /** * Generates the instruction to invoke a normal method. * - * @param owner the class in which the method is defined. - * @param method the method to be invoked. + * @param owner + * the class in which the method is defined. + * @param method + * the method to be invoked. */ public void invokeVirtual(final Type owner, final Method method) { invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method); @@ -1368,8 +1422,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to invoke a constructor. * - * @param type the class in which the constructor is defined. - * @param method the constructor to be invoked. + * @param type + * the class in which the constructor is defined. + * @param method + * the constructor to be invoked. */ public void invokeConstructor(final Type type, final Method method) { invokeInsn(Opcodes.INVOKESPECIAL, type, method); @@ -1378,8 +1434,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to invoke a static method. * - * @param owner the class in which the method is defined. - * @param method the method to be invoked. + * @param owner + * the class in which the method is defined. + * @param method + * the method to be invoked. */ public void invokeStatic(final Type owner, final Method method) { invokeInsn(Opcodes.INVOKESTATIC, owner, method); @@ -1388,8 +1446,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to invoke an interface method. * - * @param owner the class in which the method is defined. - * @param method the method to be invoked. + * @param owner + * the class in which the method is defined. + * @param method + * the method to be invoked. */ public void invokeInterface(final Type owner, final Method method) { invokeInsn(Opcodes.INVOKEINTERFACE, owner, method); @@ -1398,16 +1458,21 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates 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. - */ - public void invokeDynamic(String name, String desc, Handle bsm, Object... bsmArgs) { + * @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 invokeDynamic(String name, String desc, Handle bsm, + Object... bsmArgs) { mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); } @@ -1418,8 +1483,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates a type dependent instruction. * - * @param opcode the instruction's opcode. - * @param type the instruction's operand. + * @param opcode + * the instruction's opcode. + * @param type + * the instruction's operand. */ private void typeInsn(final int opcode, final Type type) { mv.visitTypeInsn(opcode, type.getInternalName()); @@ -1428,7 +1495,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to create a new object. * - * @param type the class of the object to be created. + * @param type + * the class of the object to be created. */ public void newInstance(final Type type) { typeInsn(Opcodes.NEW, type); @@ -1437,38 +1505,39 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Generates the instruction to create a new array. * - * @param type the type of the array elements. + * @param type + * the type of the array elements. */ public void newArray(final Type type) { int typ; switch (type.getSort()) { - case Type.BOOLEAN: - typ = Opcodes.T_BOOLEAN; - break; - case Type.CHAR: - typ = Opcodes.T_CHAR; - break; - case Type.BYTE: - typ = Opcodes.T_BYTE; - break; - case Type.SHORT: - typ = Opcodes.T_SHORT; - break; - case Type.INT: - typ = Opcodes.T_INT; - break; - case Type.FLOAT: - typ = Opcodes.T_FLOAT; - break; - case Type.LONG: - typ = Opcodes.T_LONG; - break; - case Type.DOUBLE: - typ = Opcodes.T_DOUBLE; - break; - default: - typeInsn(Opcodes.ANEWARRAY, type); - return; + case Type.BOOLEAN: + typ = Opcodes.T_BOOLEAN; + break; + case Type.CHAR: + typ = Opcodes.T_CHAR; + break; + case Type.BYTE: + typ = Opcodes.T_BYTE; + break; + case Type.SHORT: + typ = Opcodes.T_SHORT; + break; + case Type.INT: + typ = Opcodes.T_INT; + break; + case Type.FLOAT: + typ = Opcodes.T_FLOAT; + break; + case Type.LONG: + typ = Opcodes.T_LONG; + break; + case Type.DOUBLE: + typ = Opcodes.T_DOUBLE; + break; + default: + typeInsn(Opcodes.ANEWARRAY, type); + return; } mv.visitIntInsn(Opcodes.NEWARRAY, typ); } @@ -1495,8 +1564,10 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instructions to create and throw an exception. The * exception class must have a constructor with a single String argument. * - * @param type the class of the exception to be thrown. - * @param msg the detailed message of the exception. + * @param type + * the class of the exception to be thrown. + * @param msg + * the detailed message of the exception. */ public void throwException(final Type type, final String msg) { newInstance(type); @@ -1510,7 +1581,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to check that the top stack value is of the * given type. * - * @param type a class or interface type. + * @param type + * a class or interface type. */ public void checkCast(final Type type) { if (!type.equals(OBJECT_TYPE)) { @@ -1522,7 +1594,8 @@ public class GeneratorAdapter extends LocalVariablesSorter { * Generates the instruction to test if the top stack value is of the given * type. * - * @param type a class or interface type. + * @param type + * a class or interface type. */ public void instanceOf(final Type type) { typeInsn(Opcodes.INSTANCEOF, type); @@ -1559,20 +1632,21 @@ public class GeneratorAdapter extends LocalVariablesSorter { /** * Marks the start of an exception handler. * - * @param start beginning of the exception handler's scope (inclusive). - * @param end end of the exception handler's scope (exclusive). - * @param exception internal name of the type of exceptions handled by the - * handler. - */ - public void catchException( - final Label start, - final Label end, - final Type exception) - { + * @param start + * beginning of the exception handler's scope (inclusive). + * @param end + * end of the exception handler's scope (exclusive). + * @param exception + * internal name of the type of exceptions handled by the + * handler. + */ + public void catchException(final Label start, final Label end, + final Type exception) { if (exception == null) { mv.visitTryCatchBlock(start, end, mark(), null); } else { - mv.visitTryCatchBlock(start, end, mark(), exception.getInternalName()); + mv.visitTryCatchBlock(start, end, mark(), + exception.getInternalName()); } } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java index e563b236d33c1715a9139fccf61ca9a19726a4d7..912b622db13e896879f66c18b9550091942f2366 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java @@ -80,18 +80,21 @@ public class InstructionAdapter extends MethodVisitor { * constructor. Instead, they must use the * {@link #InstructionAdapter(int, MethodVisitor)} version. * - * @param mv the method visitor to which this adapter delegates calls. + * @param mv + * the method visitor to which this adapter delegates calls. */ public InstructionAdapter(final MethodVisitor mv) { - this(Opcodes.ASM4, mv); + this(Opcodes.ASM5, mv); } /** * Creates a new {@link InstructionAdapter}. * - * @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 adapter delegates calls. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param mv + * the method visitor to which this adapter delegates calls. */ protected InstructionAdapter(final int api, final MethodVisitor mv) { super(api, mv); @@ -100,394 +103,394 @@ public class InstructionAdapter extends MethodVisitor { @Override public void visitInsn(final int opcode) { switch (opcode) { - case Opcodes.NOP: - nop(); - break; - case Opcodes.ACONST_NULL: - aconst(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: - iconst(opcode - Opcodes.ICONST_0); - break; - case Opcodes.LCONST_0: - case Opcodes.LCONST_1: - lconst(opcode - Opcodes.LCONST_0); - break; - case Opcodes.FCONST_0: - case Opcodes.FCONST_1: - case Opcodes.FCONST_2: - fconst(opcode - Opcodes.FCONST_0); - break; - case Opcodes.DCONST_0: - case Opcodes.DCONST_1: - dconst(opcode - Opcodes.DCONST_0); - break; - case Opcodes.IALOAD: - aload(Type.INT_TYPE); - break; - case Opcodes.LALOAD: - aload(Type.LONG_TYPE); - break; - case Opcodes.FALOAD: - aload(Type.FLOAT_TYPE); - break; - case Opcodes.DALOAD: - aload(Type.DOUBLE_TYPE); - break; - case Opcodes.AALOAD: - aload(OBJECT_TYPE); - break; - case Opcodes.BALOAD: - aload(Type.BYTE_TYPE); - break; - case Opcodes.CALOAD: - aload(Type.CHAR_TYPE); - break; - case Opcodes.SALOAD: - aload(Type.SHORT_TYPE); - break; - case Opcodes.IASTORE: - astore(Type.INT_TYPE); - break; - case Opcodes.LASTORE: - astore(Type.LONG_TYPE); - break; - case Opcodes.FASTORE: - astore(Type.FLOAT_TYPE); - break; - case Opcodes.DASTORE: - astore(Type.DOUBLE_TYPE); - break; - case Opcodes.AASTORE: - astore(OBJECT_TYPE); - break; - case Opcodes.BASTORE: - astore(Type.BYTE_TYPE); - break; - case Opcodes.CASTORE: - astore(Type.CHAR_TYPE); - break; - case Opcodes.SASTORE: - astore(Type.SHORT_TYPE); - break; - case Opcodes.POP: - pop(); - break; - case Opcodes.POP2: - pop2(); - break; - case Opcodes.DUP: - dup(); - break; - case Opcodes.DUP_X1: - dupX1(); - break; - case Opcodes.DUP_X2: - dupX2(); - break; - case Opcodes.DUP2: - dup2(); - break; - case Opcodes.DUP2_X1: - dup2X1(); - break; - case Opcodes.DUP2_X2: - dup2X2(); - break; - case Opcodes.SWAP: - swap(); - break; - case Opcodes.IADD: - add(Type.INT_TYPE); - break; - case Opcodes.LADD: - add(Type.LONG_TYPE); - break; - case Opcodes.FADD: - add(Type.FLOAT_TYPE); - break; - case Opcodes.DADD: - add(Type.DOUBLE_TYPE); - break; - case Opcodes.ISUB: - sub(Type.INT_TYPE); - break; - case Opcodes.LSUB: - sub(Type.LONG_TYPE); - break; - case Opcodes.FSUB: - sub(Type.FLOAT_TYPE); - break; - case Opcodes.DSUB: - sub(Type.DOUBLE_TYPE); - break; - case Opcodes.IMUL: - mul(Type.INT_TYPE); - break; - case Opcodes.LMUL: - mul(Type.LONG_TYPE); - break; - case Opcodes.FMUL: - mul(Type.FLOAT_TYPE); - break; - case Opcodes.DMUL: - mul(Type.DOUBLE_TYPE); - break; - case Opcodes.IDIV: - div(Type.INT_TYPE); - break; - case Opcodes.LDIV: - div(Type.LONG_TYPE); - break; - case Opcodes.FDIV: - div(Type.FLOAT_TYPE); - break; - case Opcodes.DDIV: - div(Type.DOUBLE_TYPE); - break; - case Opcodes.IREM: - rem(Type.INT_TYPE); - break; - case Opcodes.LREM: - rem(Type.LONG_TYPE); - break; - case Opcodes.FREM: - rem(Type.FLOAT_TYPE); - break; - case Opcodes.DREM: - rem(Type.DOUBLE_TYPE); - break; - case Opcodes.INEG: - neg(Type.INT_TYPE); - break; - case Opcodes.LNEG: - neg(Type.LONG_TYPE); - break; - case Opcodes.FNEG: - neg(Type.FLOAT_TYPE); - break; - case Opcodes.DNEG: - neg(Type.DOUBLE_TYPE); - break; - case Opcodes.ISHL: - shl(Type.INT_TYPE); - break; - case Opcodes.LSHL: - shl(Type.LONG_TYPE); - break; - case Opcodes.ISHR: - shr(Type.INT_TYPE); - break; - case Opcodes.LSHR: - shr(Type.LONG_TYPE); - break; - case Opcodes.IUSHR: - ushr(Type.INT_TYPE); - break; - case Opcodes.LUSHR: - ushr(Type.LONG_TYPE); - break; - case Opcodes.IAND: - and(Type.INT_TYPE); - break; - case Opcodes.LAND: - and(Type.LONG_TYPE); - break; - case Opcodes.IOR: - or(Type.INT_TYPE); - break; - case Opcodes.LOR: - or(Type.LONG_TYPE); - break; - case Opcodes.IXOR: - xor(Type.INT_TYPE); - break; - case Opcodes.LXOR: - xor(Type.LONG_TYPE); - break; - case Opcodes.I2L: - cast(Type.INT_TYPE, Type.LONG_TYPE); - break; - case Opcodes.I2F: - cast(Type.INT_TYPE, Type.FLOAT_TYPE); - break; - case Opcodes.I2D: - cast(Type.INT_TYPE, Type.DOUBLE_TYPE); - break; - case Opcodes.L2I: - cast(Type.LONG_TYPE, Type.INT_TYPE); - break; - case Opcodes.L2F: - cast(Type.LONG_TYPE, Type.FLOAT_TYPE); - break; - case Opcodes.L2D: - cast(Type.LONG_TYPE, Type.DOUBLE_TYPE); - break; - case Opcodes.F2I: - cast(Type.FLOAT_TYPE, Type.INT_TYPE); - break; - case Opcodes.F2L: - cast(Type.FLOAT_TYPE, Type.LONG_TYPE); - break; - case Opcodes.F2D: - cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE); - break; - case Opcodes.D2I: - cast(Type.DOUBLE_TYPE, Type.INT_TYPE); - break; - case Opcodes.D2L: - cast(Type.DOUBLE_TYPE, Type.LONG_TYPE); - break; - case Opcodes.D2F: - cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE); - break; - case Opcodes.I2B: - cast(Type.INT_TYPE, Type.BYTE_TYPE); - break; - case Opcodes.I2C: - cast(Type.INT_TYPE, Type.CHAR_TYPE); - break; - case Opcodes.I2S: - cast(Type.INT_TYPE, Type.SHORT_TYPE); - break; - case Opcodes.LCMP: - lcmp(); - break; - case Opcodes.FCMPL: - cmpl(Type.FLOAT_TYPE); - break; - case Opcodes.FCMPG: - cmpg(Type.FLOAT_TYPE); - break; - case Opcodes.DCMPL: - cmpl(Type.DOUBLE_TYPE); - break; - case Opcodes.DCMPG: - cmpg(Type.DOUBLE_TYPE); - break; - case Opcodes.IRETURN: - areturn(Type.INT_TYPE); - break; - case Opcodes.LRETURN: - areturn(Type.LONG_TYPE); - break; - case Opcodes.FRETURN: - areturn(Type.FLOAT_TYPE); - break; - case Opcodes.DRETURN: - areturn(Type.DOUBLE_TYPE); - break; - case Opcodes.ARETURN: - areturn(OBJECT_TYPE); - break; - case Opcodes.RETURN: - areturn(Type.VOID_TYPE); - break; - case Opcodes.ARRAYLENGTH: - arraylength(); - break; - case Opcodes.ATHROW: - athrow(); - break; - case Opcodes.MONITORENTER: - monitorenter(); - break; - case Opcodes.MONITOREXIT: - monitorexit(); - break; - default: - throw new IllegalArgumentException(); + case Opcodes.NOP: + nop(); + break; + case Opcodes.ACONST_NULL: + aconst(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: + iconst(opcode - Opcodes.ICONST_0); + break; + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + lconst(opcode - Opcodes.LCONST_0); + break; + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + fconst(opcode - Opcodes.FCONST_0); + break; + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + dconst(opcode - Opcodes.DCONST_0); + break; + case Opcodes.IALOAD: + aload(Type.INT_TYPE); + break; + case Opcodes.LALOAD: + aload(Type.LONG_TYPE); + break; + case Opcodes.FALOAD: + aload(Type.FLOAT_TYPE); + break; + case Opcodes.DALOAD: + aload(Type.DOUBLE_TYPE); + break; + case Opcodes.AALOAD: + aload(OBJECT_TYPE); + break; + case Opcodes.BALOAD: + aload(Type.BYTE_TYPE); + break; + case Opcodes.CALOAD: + aload(Type.CHAR_TYPE); + break; + case Opcodes.SALOAD: + aload(Type.SHORT_TYPE); + break; + case Opcodes.IASTORE: + astore(Type.INT_TYPE); + break; + case Opcodes.LASTORE: + astore(Type.LONG_TYPE); + break; + case Opcodes.FASTORE: + astore(Type.FLOAT_TYPE); + break; + case Opcodes.DASTORE: + astore(Type.DOUBLE_TYPE); + break; + case Opcodes.AASTORE: + astore(OBJECT_TYPE); + break; + case Opcodes.BASTORE: + astore(Type.BYTE_TYPE); + break; + case Opcodes.CASTORE: + astore(Type.CHAR_TYPE); + break; + case Opcodes.SASTORE: + astore(Type.SHORT_TYPE); + break; + case Opcodes.POP: + pop(); + break; + case Opcodes.POP2: + pop2(); + break; + case Opcodes.DUP: + dup(); + break; + case Opcodes.DUP_X1: + dupX1(); + break; + case Opcodes.DUP_X2: + dupX2(); + break; + case Opcodes.DUP2: + dup2(); + break; + case Opcodes.DUP2_X1: + dup2X1(); + break; + case Opcodes.DUP2_X2: + dup2X2(); + break; + case Opcodes.SWAP: + swap(); + break; + case Opcodes.IADD: + add(Type.INT_TYPE); + break; + case Opcodes.LADD: + add(Type.LONG_TYPE); + break; + case Opcodes.FADD: + add(Type.FLOAT_TYPE); + break; + case Opcodes.DADD: + add(Type.DOUBLE_TYPE); + break; + case Opcodes.ISUB: + sub(Type.INT_TYPE); + break; + case Opcodes.LSUB: + sub(Type.LONG_TYPE); + break; + case Opcodes.FSUB: + sub(Type.FLOAT_TYPE); + break; + case Opcodes.DSUB: + sub(Type.DOUBLE_TYPE); + break; + case Opcodes.IMUL: + mul(Type.INT_TYPE); + break; + case Opcodes.LMUL: + mul(Type.LONG_TYPE); + break; + case Opcodes.FMUL: + mul(Type.FLOAT_TYPE); + break; + case Opcodes.DMUL: + mul(Type.DOUBLE_TYPE); + break; + case Opcodes.IDIV: + div(Type.INT_TYPE); + break; + case Opcodes.LDIV: + div(Type.LONG_TYPE); + break; + case Opcodes.FDIV: + div(Type.FLOAT_TYPE); + break; + case Opcodes.DDIV: + div(Type.DOUBLE_TYPE); + break; + case Opcodes.IREM: + rem(Type.INT_TYPE); + break; + case Opcodes.LREM: + rem(Type.LONG_TYPE); + break; + case Opcodes.FREM: + rem(Type.FLOAT_TYPE); + break; + case Opcodes.DREM: + rem(Type.DOUBLE_TYPE); + break; + case Opcodes.INEG: + neg(Type.INT_TYPE); + break; + case Opcodes.LNEG: + neg(Type.LONG_TYPE); + break; + case Opcodes.FNEG: + neg(Type.FLOAT_TYPE); + break; + case Opcodes.DNEG: + neg(Type.DOUBLE_TYPE); + break; + case Opcodes.ISHL: + shl(Type.INT_TYPE); + break; + case Opcodes.LSHL: + shl(Type.LONG_TYPE); + break; + case Opcodes.ISHR: + shr(Type.INT_TYPE); + break; + case Opcodes.LSHR: + shr(Type.LONG_TYPE); + break; + case Opcodes.IUSHR: + ushr(Type.INT_TYPE); + break; + case Opcodes.LUSHR: + ushr(Type.LONG_TYPE); + break; + case Opcodes.IAND: + and(Type.INT_TYPE); + break; + case Opcodes.LAND: + and(Type.LONG_TYPE); + break; + case Opcodes.IOR: + or(Type.INT_TYPE); + break; + case Opcodes.LOR: + or(Type.LONG_TYPE); + break; + case Opcodes.IXOR: + xor(Type.INT_TYPE); + break; + case Opcodes.LXOR: + xor(Type.LONG_TYPE); + break; + case Opcodes.I2L: + cast(Type.INT_TYPE, Type.LONG_TYPE); + break; + case Opcodes.I2F: + cast(Type.INT_TYPE, Type.FLOAT_TYPE); + break; + case Opcodes.I2D: + cast(Type.INT_TYPE, Type.DOUBLE_TYPE); + break; + case Opcodes.L2I: + cast(Type.LONG_TYPE, Type.INT_TYPE); + break; + case Opcodes.L2F: + cast(Type.LONG_TYPE, Type.FLOAT_TYPE); + break; + case Opcodes.L2D: + cast(Type.LONG_TYPE, Type.DOUBLE_TYPE); + break; + case Opcodes.F2I: + cast(Type.FLOAT_TYPE, Type.INT_TYPE); + break; + case Opcodes.F2L: + cast(Type.FLOAT_TYPE, Type.LONG_TYPE); + break; + case Opcodes.F2D: + cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE); + break; + case Opcodes.D2I: + cast(Type.DOUBLE_TYPE, Type.INT_TYPE); + break; + case Opcodes.D2L: + cast(Type.DOUBLE_TYPE, Type.LONG_TYPE); + break; + case Opcodes.D2F: + cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE); + break; + case Opcodes.I2B: + cast(Type.INT_TYPE, Type.BYTE_TYPE); + break; + case Opcodes.I2C: + cast(Type.INT_TYPE, Type.CHAR_TYPE); + break; + case Opcodes.I2S: + cast(Type.INT_TYPE, Type.SHORT_TYPE); + break; + case Opcodes.LCMP: + lcmp(); + break; + case Opcodes.FCMPL: + cmpl(Type.FLOAT_TYPE); + break; + case Opcodes.FCMPG: + cmpg(Type.FLOAT_TYPE); + break; + case Opcodes.DCMPL: + cmpl(Type.DOUBLE_TYPE); + break; + case Opcodes.DCMPG: + cmpg(Type.DOUBLE_TYPE); + break; + case Opcodes.IRETURN: + areturn(Type.INT_TYPE); + break; + case Opcodes.LRETURN: + areturn(Type.LONG_TYPE); + break; + case Opcodes.FRETURN: + areturn(Type.FLOAT_TYPE); + break; + case Opcodes.DRETURN: + areturn(Type.DOUBLE_TYPE); + break; + case Opcodes.ARETURN: + areturn(OBJECT_TYPE); + break; + case Opcodes.RETURN: + areturn(Type.VOID_TYPE); + break; + case Opcodes.ARRAYLENGTH: + arraylength(); + break; + case Opcodes.ATHROW: + athrow(); + break; + case Opcodes.MONITORENTER: + monitorenter(); + break; + case Opcodes.MONITOREXIT: + monitorexit(); + break; + default: + throw new IllegalArgumentException(); } } @Override public void visitIntInsn(final int opcode, final int operand) { switch (opcode) { - case Opcodes.BIPUSH: - iconst(operand); + case Opcodes.BIPUSH: + iconst(operand); + break; + case Opcodes.SIPUSH: + iconst(operand); + break; + case Opcodes.NEWARRAY: + switch (operand) { + case Opcodes.T_BOOLEAN: + newarray(Type.BOOLEAN_TYPE); break; - case Opcodes.SIPUSH: - iconst(operand); + case Opcodes.T_CHAR: + newarray(Type.CHAR_TYPE); break; - case Opcodes.NEWARRAY: - switch (operand) { - case Opcodes.T_BOOLEAN: - newarray(Type.BOOLEAN_TYPE); - break; - case Opcodes.T_CHAR: - newarray(Type.CHAR_TYPE); - break; - case Opcodes.T_BYTE: - newarray(Type.BYTE_TYPE); - break; - case Opcodes.T_SHORT: - newarray(Type.SHORT_TYPE); - break; - case Opcodes.T_INT: - newarray(Type.INT_TYPE); - break; - case Opcodes.T_FLOAT: - newarray(Type.FLOAT_TYPE); - break; - case Opcodes.T_LONG: - newarray(Type.LONG_TYPE); - break; - case Opcodes.T_DOUBLE: - newarray(Type.DOUBLE_TYPE); - break; - default: - throw new IllegalArgumentException(); - } + case Opcodes.T_BYTE: + newarray(Type.BYTE_TYPE); + break; + case Opcodes.T_SHORT: + newarray(Type.SHORT_TYPE); + break; + case Opcodes.T_INT: + newarray(Type.INT_TYPE); + break; + case Opcodes.T_FLOAT: + newarray(Type.FLOAT_TYPE); + break; + case Opcodes.T_LONG: + newarray(Type.LONG_TYPE); + break; + case Opcodes.T_DOUBLE: + newarray(Type.DOUBLE_TYPE); break; default: throw new IllegalArgumentException(); + } + break; + default: + throw new IllegalArgumentException(); } } @Override public void visitVarInsn(final int opcode, final int var) { switch (opcode) { - case Opcodes.ILOAD: - load(var, Type.INT_TYPE); - break; - case Opcodes.LLOAD: - load(var, Type.LONG_TYPE); - break; - case Opcodes.FLOAD: - load(var, Type.FLOAT_TYPE); - break; - case Opcodes.DLOAD: - load(var, Type.DOUBLE_TYPE); - break; - case Opcodes.ALOAD: - load(var, OBJECT_TYPE); - break; - case Opcodes.ISTORE: - store(var, Type.INT_TYPE); - break; - case Opcodes.LSTORE: - store(var, Type.LONG_TYPE); - break; - case Opcodes.FSTORE: - store(var, Type.FLOAT_TYPE); - break; - case Opcodes.DSTORE: - store(var, Type.DOUBLE_TYPE); - break; - case Opcodes.ASTORE: - store(var, OBJECT_TYPE); - break; - case Opcodes.RET: - ret(var); - break; - default: - throw new IllegalArgumentException(); + case Opcodes.ILOAD: + load(var, Type.INT_TYPE); + break; + case Opcodes.LLOAD: + load(var, Type.LONG_TYPE); + break; + case Opcodes.FLOAD: + load(var, Type.FLOAT_TYPE); + break; + case Opcodes.DLOAD: + load(var, Type.DOUBLE_TYPE); + break; + case Opcodes.ALOAD: + load(var, OBJECT_TYPE); + break; + case Opcodes.ISTORE: + store(var, Type.INT_TYPE); + break; + case Opcodes.LSTORE: + store(var, Type.LONG_TYPE); + break; + case Opcodes.FSTORE: + store(var, Type.FLOAT_TYPE); + break; + case Opcodes.DSTORE: + store(var, Type.DOUBLE_TYPE); + break; + case Opcodes.ASTORE: + store(var, OBJECT_TYPE); + break; + case Opcodes.RET: + ret(var); + break; + default: + throw new IllegalArgumentException(); } } @@ -495,142 +498,130 @@ public class InstructionAdapter extends MethodVisitor { public void visitTypeInsn(final int opcode, final String type) { Type t = Type.getObjectType(type); switch (opcode) { - case Opcodes.NEW: - anew(t); - break; - case Opcodes.ANEWARRAY: - newarray(t); - break; - case Opcodes.CHECKCAST: - checkcast(t); - break; - case Opcodes.INSTANCEOF: - instanceOf(t); - break; - default: - throw new IllegalArgumentException(); + case Opcodes.NEW: + anew(t); + break; + case Opcodes.ANEWARRAY: + newarray(t); + break; + case Opcodes.CHECKCAST: + checkcast(t); + break; + case Opcodes.INSTANCEOF: + instanceOf(t); + break; + default: + throw new IllegalArgumentException(); } } @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) { switch (opcode) { - case Opcodes.GETSTATIC: - getstatic(owner, name, desc); - break; - case Opcodes.PUTSTATIC: - putstatic(owner, name, desc); - break; - case Opcodes.GETFIELD: - getfield(owner, name, desc); - break; - case Opcodes.PUTFIELD: - putfield(owner, name, desc); - break; - default: - throw new IllegalArgumentException(); + case Opcodes.GETSTATIC: + getstatic(owner, name, desc); + break; + case Opcodes.PUTSTATIC: + putstatic(owner, name, desc); + break; + case Opcodes.GETFIELD: + getfield(owner, name, desc); + break; + case Opcodes.PUTFIELD: + putfield(owner, name, desc); + break; + default: + throw new IllegalArgumentException(); } } @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) { switch (opcode) { - case Opcodes.INVOKESPECIAL: - invokespecial(owner, name, desc); - break; - case Opcodes.INVOKEVIRTUAL: - invokevirtual(owner, name, desc); - break; - case Opcodes.INVOKESTATIC: - invokestatic(owner, name, desc); - break; - case Opcodes.INVOKEINTERFACE: - invokeinterface(owner, name, desc); - break; - default: - throw new IllegalArgumentException(); + case Opcodes.INVOKESPECIAL: + invokespecial(owner, name, desc); + break; + case Opcodes.INVOKEVIRTUAL: + invokevirtual(owner, name, desc); + break; + case Opcodes.INVOKESTATIC: + invokestatic(owner, name, desc); + break; + case Opcodes.INVOKEINTERFACE: + invokeinterface(owner, name, desc); + break; + default: + throw new IllegalArgumentException(); } } @Override - public void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs) - { - invokedynamic(name, desc, bsm, bsmArgs); + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { + invokedynamic(name, desc, bsm, bsmArgs); } @Override public void visitJumpInsn(final int opcode, final Label label) { switch (opcode) { - case Opcodes.IFEQ: - ifeq(label); - break; - case Opcodes.IFNE: - ifne(label); - break; - case Opcodes.IFLT: - iflt(label); - break; - case Opcodes.IFGE: - ifge(label); - break; - case Opcodes.IFGT: - ifgt(label); - break; - case Opcodes.IFLE: - ifle(label); - break; - case Opcodes.IF_ICMPEQ: - ificmpeq(label); - break; - case Opcodes.IF_ICMPNE: - ificmpne(label); - break; - case Opcodes.IF_ICMPLT: - ificmplt(label); - break; - case Opcodes.IF_ICMPGE: - ificmpge(label); - break; - case Opcodes.IF_ICMPGT: - ificmpgt(label); - break; - case Opcodes.IF_ICMPLE: - ificmple(label); - break; - case Opcodes.IF_ACMPEQ: - ifacmpeq(label); - break; - case Opcodes.IF_ACMPNE: - ifacmpne(label); - break; - case Opcodes.GOTO: - goTo(label); - break; - case Opcodes.JSR: - jsr(label); - break; - case Opcodes.IFNULL: - ifnull(label); - break; - case Opcodes.IFNONNULL: - ifnonnull(label); - break; - default: - throw new IllegalArgumentException(); + case Opcodes.IFEQ: + ifeq(label); + break; + case Opcodes.IFNE: + ifne(label); + break; + case Opcodes.IFLT: + iflt(label); + break; + case Opcodes.IFGE: + ifge(label); + break; + case Opcodes.IFGT: + ifgt(label); + break; + case Opcodes.IFLE: + ifle(label); + break; + case Opcodes.IF_ICMPEQ: + ificmpeq(label); + break; + case Opcodes.IF_ICMPNE: + ificmpne(label); + break; + case Opcodes.IF_ICMPLT: + ificmplt(label); + break; + case Opcodes.IF_ICMPGE: + ificmpge(label); + break; + case Opcodes.IF_ICMPGT: + ificmpgt(label); + break; + case Opcodes.IF_ICMPLE: + ificmple(label); + break; + case Opcodes.IF_ACMPEQ: + ifacmpeq(label); + break; + case Opcodes.IF_ACMPNE: + ifacmpne(label); + break; + case Opcodes.GOTO: + goTo(label); + break; + case Opcodes.JSR: + jsr(label); + break; + case Opcodes.IFNULL: + ifnull(label); + break; + case Opcodes.IFNONNULL: + ifnonnull(label); + break; + default: + throw new IllegalArgumentException(); } } @@ -682,21 +673,14 @@ public class InstructionAdapter 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) { tableswitch(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) { lookupswitch(dflt, keys, labels); } @@ -996,20 +980,13 @@ public class InstructionAdapter extends MethodVisitor { mv.visitVarInsn(Opcodes.RET, var); } - public void tableswitch( - final int min, - final int max, - final Label dflt, - final Label... labels) - { + public void tableswitch(final int min, final int max, final Label dflt, + final Label... labels) { mv.visitTableSwitchInsn(min, max, dflt, labels); } - public void lookupswitch( - final Label dflt, - final int[] keys, - final Label[] labels) - { + public void lookupswitch(final Label dflt, final int[] keys, + final Label[] labels) { mv.visitLookupSwitchInsn(dflt, keys, labels); } @@ -1017,76 +994,48 @@ public class InstructionAdapter extends MethodVisitor { mv.visitInsn(t.getOpcode(Opcodes.IRETURN)); } - public void getstatic( - final String owner, - final String name, - final String desc) - { + public void getstatic(final String owner, final String name, + final String desc) { mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc); } - public void putstatic( - final String owner, - final String name, - final String desc) - { + public void putstatic(final String owner, final String name, + final String desc) { mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc); } - public void getfield( - final String owner, - final String name, - final String desc) - { + public void getfield(final String owner, final String name, + final String desc) { mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc); } - public void putfield( - final String owner, - final String name, - final String desc) - { + public void putfield(final String owner, final String name, + final String desc) { mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc); } - public void invokevirtual( - final String owner, - final String name, - final String desc) - { + public void invokevirtual(final String owner, final String name, + final String desc) { mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc); } - public void invokespecial( - final String owner, - final String name, - final String desc) - { + public void invokespecial(final String owner, final String name, + final String desc) { mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc); } - public void invokestatic( - final String owner, - final String name, - final String desc) - { + public void invokestatic(final String owner, final String name, + final String desc) { mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc); } - public void invokeinterface( - final String owner, - final String name, - final String desc) - { + public void invokeinterface(final String owner, final String name, + final String desc) { mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc); } - public void invokedynamic( - String name, - String desc, - Handle bsm, - Object[] bsmArgs) - { + public void invokedynamic(String name, String desc, Handle bsm, + Object[] bsmArgs) { mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); } @@ -1097,33 +1046,33 @@ public class InstructionAdapter extends MethodVisitor { public void newarray(final Type type) { int typ; switch (type.getSort()) { - case Type.BOOLEAN: - typ = Opcodes.T_BOOLEAN; - break; - case Type.CHAR: - typ = Opcodes.T_CHAR; - break; - case Type.BYTE: - typ = Opcodes.T_BYTE; - break; - case Type.SHORT: - typ = Opcodes.T_SHORT; - break; - case Type.INT: - typ = Opcodes.T_INT; - break; - case Type.FLOAT: - typ = Opcodes.T_FLOAT; - break; - case Type.LONG: - typ = Opcodes.T_LONG; - break; - case Type.DOUBLE: - typ = Opcodes.T_DOUBLE; - break; - default: - mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName()); - return; + case Type.BOOLEAN: + typ = Opcodes.T_BOOLEAN; + break; + case Type.CHAR: + typ = Opcodes.T_CHAR; + break; + case Type.BYTE: + typ = Opcodes.T_BYTE; + break; + case Type.SHORT: + typ = Opcodes.T_SHORT; + break; + case Type.INT: + typ = Opcodes.T_INT; + break; + case Type.FLOAT: + typ = Opcodes.T_FLOAT; + break; + case Type.LONG: + typ = Opcodes.T_LONG; + break; + case Type.DOUBLE: + typ = Opcodes.T_DOUBLE; + break; + default: + mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName()); + return; } mv.visitIntInsn(Opcodes.NEWARRAY, typ); } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java index b8da61d51cf03fe398754f0d8b4060affd18aeb6..1a255b7096f14c817497fcda5ced6de6a802ed2e 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java @@ -96,10 +96,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { private static final boolean LOGGING = false; /** - * For each label that is jumped to by a JSR, we create a BitSet - * instance. + * For each label that is jumped to by a JSR, we create a BitSet instance. */ - private final Map subroutineHeads = new HashMap(); + private final Map subroutineHeads = new HashMap(); /** * This subroutine instance denotes the line of execution that is not @@ -120,55 +119,57 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { * {@link #JSRInlinerAdapter(int, MethodVisitor, int, String, String, String, String[])} * version. * - * @param mv the MethodVisitor to send the resulting inlined - * method code to (use null for none). - * @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 null. - * @param exceptions the internal names of the method's exception classes - * (see {@link Type#getInternalName() getInternalName}). May be - * null. + * @param mv + * the MethodVisitor to send the resulting inlined + * method code to (use null for none). + * @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 null. + * @param exceptions + * the internal names of the method's exception classes (see + * {@link Type#getInternalName() getInternalName}). May be + * null. */ - public JSRInlinerAdapter( - final MethodVisitor mv, - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { - this(Opcodes.ASM4, mv, access, name, desc, signature, exceptions); + public JSRInlinerAdapter(final MethodVisitor mv, final int access, + final String name, final String desc, final String signature, + final String[] exceptions) { + this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions); } /** * Creates a new JSRInliner. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param mv the MethodVisitor to send the resulting inlined - * method code to (use null for none). - * @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 null. - * @param exceptions the internal names of the method's exception classes - * (see {@link Type#getInternalName() getInternalName}). May be - * null. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param mv + * the MethodVisitor to send the resulting inlined + * method code to (use null for none). + * @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 null. + * @param exceptions + * the internal names of the method's exception classes (see + * {@link Type#getInternalName() getInternalName}). May be + * null. */ - protected JSRInlinerAdapter( - final int api, - final MethodVisitor mv, - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { + protected JSRInlinerAdapter(final int api, final MethodVisitor mv, + final int access, final String name, final String desc, + final String signature, final String[] exceptions) { super(api, access, name, desc, signature, exceptions); this.mv = mv; } @@ -224,9 +225,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { // Go through the head of each subroutine and find any nodes reachable // to that subroutine without following any JSR links. - for (Iterator> it = subroutineHeads.entrySet().iterator(); it.hasNext();) - { - Map.Entry entry = it.next(); + for (Iterator> it = subroutineHeads + .entrySet().iterator(); it.hasNext();) { + Map.Entry entry = it.next(); LabelNode lab = entry.getKey(); BitSet sub = entry.getValue(); int index = instructions.indexOf(lab); @@ -236,24 +237,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { /** * Performs a depth first search walking the normal byte code path starting - * at index, and adding each instruction encountered into - * the subroutine sub. After this walk is complete, iterates - * over the exception handlers to ensure that we also include those byte - * codes which are reachable through an exception that may be thrown during - * the execution of the subroutine. Invoked from - * markSubroutines(). + * at index, and adding each instruction encountered into the + * subroutine sub. After this walk is complete, iterates over + * the exception handlers to ensure that we also include those byte codes + * which are reachable through an exception that may be thrown during the + * execution of the subroutine. Invoked from markSubroutines(). * - * @param sub the subroutine whose instructions must be computed. - * @param index an instruction of this subroutine. - * @param anyvisited indexes of the already visited instructions, i.e. - * marked as part of this subroutine or any previously computed - * subroutine. + * @param sub + * the subroutine whose instructions must be computed. + * @param index + * an instruction of this subroutine. + * @param anyvisited + * indexes of the already visited instructions, i.e. marked as + * part of this subroutine or any previously computed subroutine. */ - private void markSubroutineWalk( - final BitSet sub, - final int index, - final BitSet anyvisited) - { + private void markSubroutineWalk(final BitSet sub, final int index, + final BitSet anyvisited) { if (LOGGING) { log("markSubroutineWalk: sub=" + sub + " index=" + index); } @@ -265,7 +264,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { boolean loop = true; while (loop) { loop = false; - for (Iterator it = tryCatchBlocks.iterator(); it.hasNext();) { + for (Iterator it = tryCatchBlocks.iterator(); it + .hasNext();) { TryCatchBlockNode trycatch = it.next(); if (LOGGING) { @@ -297,20 +297,19 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { /** * Performs a simple DFS of the instructions, assigning each to the - * subroutine sub. Starts from index. - * Invoked only by markSubroutineWalk(). + * subroutine sub. Starts from index. Invoked only + * by markSubroutineWalk(). * - * @param sub the subroutine whose instructions must be computed. - * @param index an instruction of this subroutine. - * @param anyvisited indexes of the already visited instructions, i.e. - * marked as part of this subroutine or any previously computed - * subroutine. + * @param sub + * the subroutine whose instructions must be computed. + * @param index + * an instruction of this subroutine. + * @param anyvisited + * indexes of the already visited instructions, i.e. marked as + * part of this subroutine or any previously computed subroutine. */ - private void markSubroutineWalkDFS( - final BitSet sub, - int index, - final BitSet anyvisited) - { + private void markSubroutineWalkDFS(final BitSet sub, int index, + final BitSet anyvisited) { while (true) { AbstractInsnNode node = instructions.get(index); @@ -330,8 +329,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { anyvisited.set(index); if (node.getType() == AbstractInsnNode.JUMP_INSN - && node.getOpcode() != JSR) - { + && node.getOpcode() != JSR) { // we do not follow recursively called subroutines here; but any // other sort of branch we do follow JumpInsnNode jnode = (JumpInsnNode) node; @@ -362,22 +360,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { // check to see if this opcode falls through to the next instruction // or not; if not, return. switch (instructions.get(index).getOpcode()) { - case GOTO: - case RET: - case TABLESWITCH: - case LOOKUPSWITCH: - case IRETURN: - case LRETURN: - case FRETURN: - case DRETURN: - case ARETURN: - case RETURN: - case ATHROW: - /* - * note: this either returns from this subroutine, or a - * parent subroutine which invoked it - */ - return; + case GOTO: + case RET: + case TABLESWITCH: + case LOOKUPSWITCH: + case IRETURN: + case LRETURN: + case FRETURN: + case DRETURN: + case ARETURN: + case RETURN: + case ATHROW: + /* + * note: this either returns from this subroutine, or a parent + * subroutine which invoked it + */ + return; } // Use tail recursion here in the form of an outer while loop to @@ -403,10 +401,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { List newLocalVariables = new ArrayList(); while (!worklist.isEmpty()) { Instantiation inst = worklist.removeFirst(); - emitSubroutine(inst, - worklist, - newInstructions, - newTryCatchBlocks, + emitSubroutine(inst, worklist, newInstructions, newTryCatchBlocks, newLocalVariables); } instructions = newInstructions; @@ -416,24 +411,25 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { /** * Emits one instantiation of one subroutine, specified by - * instant. May add new instantiations that are invoked by - * this one to the worklist parameter, and new try/catch - * blocks to newTryCatchBlocks. + * instant. May add new instantiations that are invoked by this + * one to the worklist parameter, and new try/catch blocks to + * newTryCatchBlocks. * - * @param instant the instantiation that must be performed. - * @param worklist list of the instantiations that remain to be done. - * @param newInstructions the instruction list to which the instantiated - * code must be appended. - * @param newTryCatchBlocks the exception handler list to which the - * instantiated handlers must be appended. + * @param instant + * the instantiation that must be performed. + * @param worklist + * list of the instantiations that remain to be done. + * @param newInstructions + * the instruction list to which the instantiated code must be + * appended. + * @param newTryCatchBlocks + * the exception handler list to which the instantiated handlers + * must be appended. */ - private void emitSubroutine( - final Instantiation instant, - final List worklist, - final InsnList newInstructions, - final List newTryCatchBlocks, - final List newLocalVariables) - { + private void emitSubroutine(final Instantiation instant, + final List worklist, final InsnList newInstructions, + final List newTryCatchBlocks, + final List newLocalVariables) { LabelNode duplbl = null; if (LOGGING) { @@ -530,7 +526,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { } // Emit try/catch blocks that are relevant to this method. - for (Iterator it = tryCatchBlocks.iterator(); it.hasNext();) { + for (Iterator it = tryCatchBlocks.iterator(); it + .hasNext();) { TryCatchBlockNode trycatch = it.next(); if (LOGGING) { @@ -562,13 +559,12 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { throw new RuntimeException("Internal error!"); } - newTryCatchBlocks.add(new TryCatchBlockNode(start, - end, - handler, + newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler, trycatch.type)); } - for (Iterator it = localVariables.iterator(); it.hasNext();) { + for (Iterator it = localVariables.iterator(); it + .hasNext();) { LocalVariableNode lvnode = it.next(); if (LOGGING) { log("local var " + lvnode.name); @@ -582,11 +578,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { continue; } newLocalVariables.add(new LocalVariableNode(lvnode.name, - lvnode.desc, - lvnode.signature, - start, - end, - lvnode.index)); + lvnode.desc, lvnode.signature, start, end, lvnode.index)); } } @@ -693,8 +685,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { * Typically, the return value is either this or * null. this indicates that this * instantiation will generate the version of this instruction that we - * will execute, and null indicates that this - * instantiation never executes the given instruction. + * will execute, and null indicates that this instantiation + * never executes the given instruction. * * Sometimes, however, an instruction can belong to multiple * subroutines; this is called a "dual citizen" instruction (though it @@ -703,7 +695,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { * owner is the subroutine that appears lowest on the stack, and which * also owns the instruction in question. * - * @param i the index of the instruction in the original code + * @param i + * the index of the instruction in the original code * @return the "owner" of a particular instruction relative to this * instantiation. */ @@ -724,12 +717,13 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { } /** - * Looks up the label l in the gotoTable, - * thus translating it from a Label in the original code, to a Label in - * the inlined code that is appropriate for use by an instruction that + * Looks up the label l in the gotoTable, thus + * translating it from a Label in the original code, to a Label in the + * inlined code that is appropriate for use by an instruction that * branched to the original label. * - * @param l The label we will be translating + * @param l + * The label we will be translating * @return a label for use by a branch instruction in the inlined code * @see #rangeLabel */ @@ -746,7 +740,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { * the inlined code that is appropriate for use by an try/catch or * variable use annotation. * - * @param l The label we will be translating + * @param l + * The label we will be translating * @return a label for use by a try/catch or variable annotation in the * original code * @see #rangeTable diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java index 54d67a8757a6f1599b6d5e281431f103d96d382e..0353c49938298e5823aa02101e38310327c28172 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java @@ -58,10 +58,12 @@ */ package jdk.internal.org.objectweb.asm.commons; +import jdk.internal.org.objectweb.asm.AnnotationVisitor; import jdk.internal.org.objectweb.asm.Label; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; +import jdk.internal.org.objectweb.asm.TypePath; /** * A {@link MethodVisitor} that renumbers local variables in their order of @@ -77,7 +79,8 @@ import jdk.internal.org.objectweb.asm.Type; */ public class LocalVariablesSorter extends MethodVisitor { - private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object"); + private static final Type OBJECT_TYPE = Type + .getObjectType("java/lang/Object"); /** * Mapping from old to new local variable indexes. A local variable at index @@ -111,33 +114,33 @@ public class LocalVariablesSorter extends MethodVisitor { * this constructor. Instead, they must use the * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version. * - * @param access access flags of the adapted method. - * @param desc the method's descriptor (see {@link Type Type}). - * @param mv the method visitor to which this adapter delegates calls. + * @param access + * access flags of the adapted method. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param mv + * the method visitor to which this adapter delegates calls. */ - public LocalVariablesSorter( - final int access, - final String desc, - final MethodVisitor mv) - { - this(Opcodes.ASM4, access, desc, mv); + public LocalVariablesSorter(final int access, final String desc, + final MethodVisitor mv) { + this(Opcodes.ASM5, access, desc, mv); } /** * Creates a new {@link LocalVariablesSorter}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param access access flags of the adapted method. - * @param desc the method's descriptor (see {@link Type Type}). - * @param mv the method visitor to which this adapter delegates calls. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param access + * access flags of the adapted method. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param mv + * the method visitor to which this adapter delegates calls. */ - protected LocalVariablesSorter( - final int api, - final int access, - final String desc, - final MethodVisitor mv) - { + protected LocalVariablesSorter(final int api, final int access, + final String desc, final MethodVisitor mv) { super(api, mv); Type[] args = Type.getArgumentTypes(desc); nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0; @@ -151,32 +154,32 @@ public class LocalVariablesSorter extends MethodVisitor { public void visitVarInsn(final int opcode, final int var) { Type type; switch (opcode) { - case Opcodes.LLOAD: - case Opcodes.LSTORE: - type = Type.LONG_TYPE; - break; - - case Opcodes.DLOAD: - case Opcodes.DSTORE: - type = Type.DOUBLE_TYPE; - break; - - case Opcodes.FLOAD: - case Opcodes.FSTORE: - type = Type.FLOAT_TYPE; - break; - - case Opcodes.ILOAD: - case Opcodes.ISTORE: - type = Type.INT_TYPE; - break; - - default: + case Opcodes.LLOAD: + case Opcodes.LSTORE: + type = Type.LONG_TYPE; + break; + + case Opcodes.DLOAD: + case Opcodes.DSTORE: + type = Type.DOUBLE_TYPE; + break; + + case Opcodes.FLOAD: + case Opcodes.FSTORE: + type = Type.FLOAT_TYPE; + break; + + case Opcodes.ILOAD: + case Opcodes.ISTORE: + type = Type.INT_TYPE; + break; + + default: // case Opcodes.ALOAD: // case Opcodes.ASTORE: // case RET: - type = OBJECT_TYPE; - break; + type = OBJECT_TYPE; + break; } mv.visitVarInsn(opcode, remap(var, type)); } @@ -192,28 +195,32 @@ public class LocalVariablesSorter 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) { int newIndex = remap(index, Type.getType(desc)); mv.visitLocalVariable(name, desc, signature, start, end, newIndex); } @Override - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) - { + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, + TypePath typePath, Label[] start, Label[] end, int[] index, + String desc, boolean visible) { + Type t = Type.getType(desc); + int[] newIndex = new int[index.length]; + for (int i = 0; i < newIndex.length; ++i) { + newIndex[i] = remap(index[i], t); + } + return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end, + newIndex, desc, visible); + } + + @Override + public void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack) { if (type != Opcodes.F_NEW) { // uncompressed frame - throw new IllegalStateException("ClassReader.accept() should be called with EXPAND_FRAMES flag"); + throw new IllegalStateException( + "ClassReader.accept() should be called with EXPAND_FRAMES flag"); } if (!changed) { // optimization for the case where mapping = identity @@ -225,6 +232,8 @@ public class LocalVariablesSorter extends MethodVisitor { Object[] oldLocals = new Object[newLocals.length]; System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length); + updateNewLocals(newLocals); + // copies types from 'local' to 'newLocals' // 'newLocals' already contains the variables added with 'newLocal' @@ -280,50 +289,74 @@ public class LocalVariablesSorter extends MethodVisitor { /** * Creates a new local variable of the given type. * - * @param type the type of the local variable to be created. + * @param type + * the type of the local variable to be created. * @return the identifier of the newly created local variable. */ public int newLocal(final Type type) { Object t; switch (type.getSort()) { - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - case Type.INT: - t = Opcodes.INTEGER; - break; - case Type.FLOAT: - t = Opcodes.FLOAT; - break; - case Type.LONG: - t = Opcodes.LONG; - break; - case Type.DOUBLE: - t = Opcodes.DOUBLE; - break; - case Type.ARRAY: - t = type.getDescriptor(); - break; - // case Type.OBJECT: - default: - t = type.getInternalName(); - break; + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + case Type.INT: + t = Opcodes.INTEGER; + break; + case Type.FLOAT: + t = Opcodes.FLOAT; + break; + case Type.LONG: + t = Opcodes.LONG; + break; + case Type.DOUBLE: + t = Opcodes.DOUBLE; + break; + case Type.ARRAY: + t = type.getDescriptor(); + break; + // case Type.OBJECT: + default: + t = type.getInternalName(); + break; } - int local = nextLocal; - nextLocal += type.getSize(); + int local = newLocalMapping(type); setLocalType(local, type); setFrameLocal(local, t); return local; } /** - * Sets the current type of the given local variable. The default - * implementation of this method does nothing. + * Notifies subclasses that a new stack map frame is being visited. The + * array argument contains the stack map frame types corresponding to the + * local variables added with {@link #newLocal}. This method can update + * these types in place for the stack map frame being visited. The default + * implementation of this method does nothing, i.e. a local variable added + * with {@link #newLocal} will have the same type in all stack map frames. + * But this behavior is not always the desired one, for instance if a local + * variable is added in the middle of a try/catch block: the frame for the + * exception handler should have a TOP type for this new local. + * + * @param newLocals + * the stack map frame types corresponding to the local variables + * added with {@link #newLocal} (and null for the others). The + * format of this array is the same as in + * {@link MethodVisitor#visitFrame}, except that long and double + * types use two slots. The types for the current stack map frame + * must be updated in place in this array. + */ + protected void updateNewLocals(Object[] newLocals) { + } + + /** + * Notifies subclasses that a local variable has been added or remapped. The + * default implementation of this method does nothing. * - * @param local a local variable identifier, as returned by {@link #newLocal - * newLocal()}. - * @param type the type of the value being stored in the local variable + * @param local + * a local variable identifier, as returned by {@link #newLocal + * newLocal()}. + * @param type + * the type of the value being stored in the local variable. */ protected void setLocalType(final int local, final Type type) { } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java index f13f97b4d57ef8afd1b05bdd8079803d2038ef64..df97a36575fdd59f0b792f901e0002a8780353dc 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java @@ -103,8 +103,10 @@ public class Method { /** * Creates a new {@link Method}. * - * @param name the method's name. - * @param desc the method's descriptor. + * @param name + * the method's name. + * @param desc + * the method's descriptor. */ public Method(final String name, final String desc) { this.name = name; @@ -114,22 +116,23 @@ public class Method { /** * Creates a new {@link Method}. * - * @param name the method's name. - * @param returnType the method's return type. - * @param argumentTypes the method's argument types. + * @param name + * the method's name. + * @param returnType + * the method's return type. + * @param argumentTypes + * the method's argument types. */ - public Method( - final String name, - final Type returnType, - final Type[] argumentTypes) - { + public Method(final String name, final Type returnType, + final Type[] argumentTypes) { this(name, Type.getMethodDescriptor(returnType, argumentTypes)); } /** * Creates a new {@link Method}. * - * @param m a java.lang.reflect method descriptor + * @param m + * a java.lang.reflect method descriptor * @return a {@link Method} corresponding to the given Java method * declaration. */ @@ -140,7 +143,8 @@ public class Method { /** * Creates a new {@link Method}. * - * @param c a java.lang.reflect constructor descriptor + * @param c + * a java.lang.reflect constructor descriptor * @return a {@link Method} corresponding to the given Java constructor * declaration. */ @@ -152,20 +156,20 @@ public class Method { * Returns a {@link Method} corresponding to the given Java method * declaration. * - * @param method a Java method declaration, without argument names, of the - * form "returnType name (argumentType1, ... argumentTypeN)", where - * the types are in plain Java (e.g. "int", "float", - * "java.util.List", ...). Classes of the java.lang package can be - * specified by their unqualified name; all other classes names must - * be fully qualified. + * @param method + * a Java method declaration, without argument names, of the form + * "returnType name (argumentType1, ... argumentTypeN)", where + * the types are in plain Java (e.g. "int", "float", + * "java.util.List", ...). Classes of the java.lang package can + * be specified by their unqualified name; all other classes + * names must be fully qualified. * @return a {@link Method} corresponding to the given Java method * declaration. - * @throws IllegalArgumentException if method could not get - * parsed. + * @throws IllegalArgumentException + * if method could not get parsed. */ public static Method getMethod(final String method) - throws IllegalArgumentException - { + throws IllegalArgumentException { return getMethod(method, false); } @@ -173,26 +177,26 @@ public class Method { * Returns a {@link Method} corresponding to the given Java method * declaration. * - * @param method a Java method declaration, without argument names, of the - * form "returnType name (argumentType1, ... argumentTypeN)", where - * the types are in plain Java (e.g. "int", "float", - * "java.util.List", ...). Classes of the java.lang package may be - * specified by their unqualified name, depending on the - * defaultPackage argument; all other classes names must be fully - * qualified. - * @param defaultPackage true if unqualified class names belong to the - * default package, or false if they correspond to java.lang classes. - * For instance "Object" means "Object" if this option is true, or - * "java.lang.Object" otherwise. + * @param method + * a Java method declaration, without argument names, of the form + * "returnType name (argumentType1, ... argumentTypeN)", where + * the types are in plain Java (e.g. "int", "float", + * "java.util.List", ...). Classes of the java.lang package may + * be specified by their unqualified name, depending on the + * defaultPackage argument; all other classes names must be fully + * qualified. + * @param defaultPackage + * true if unqualified class names belong to the default package, + * or false if they correspond to java.lang classes. For instance + * "Object" means "Object" if this option is true, or + * "java.lang.Object" otherwise. * @return a {@link Method} corresponding to the given Java method * declaration. - * @throws IllegalArgumentException if method could not get - * parsed. + * @throws IllegalArgumentException + * if method could not get parsed. */ - public static Method getMethod( - final String method, - final boolean defaultPackage) throws IllegalArgumentException - { + public static Method getMethod(final String method, + final boolean defaultPackage) throws IllegalArgumentException { int space = method.indexOf(' '); int start = method.indexOf('(', space) + 1; int end = method.indexOf(')', start); diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java index 20355115d30e2d15af3d0263783133babd1b74a5..2b4f7201d6917906a1d3e52ab32196e477bd6ab2 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java @@ -66,8 +66,8 @@ import jdk.internal.org.objectweb.asm.signature.SignatureVisitor; import jdk.internal.org.objectweb.asm.signature.SignatureWriter; /** - * A class responsible for remapping types and names. - * Subclasses can override the following methods: + * A class responsible for remapping types and names. Subclasses can override + * the following methods: * *
        *
      • {@link #map(String)} - map type
      • @@ -82,34 +82,34 @@ public abstract class Remapper { public String mapDesc(String desc) { Type t = Type.getType(desc); switch (t.getSort()) { - case Type.ARRAY: - String s = mapDesc(t.getElementType().getDescriptor()); - for (int i = 0; i < t.getDimensions(); ++i) { - s = '[' + s; - } - return s; - case Type.OBJECT: - String newType = map(t.getInternalName()); - if (newType != null) { - return 'L' + newType + ';'; - } + case Type.ARRAY: + String s = mapDesc(t.getElementType().getDescriptor()); + for (int i = 0; i < t.getDimensions(); ++i) { + s = '[' + s; + } + return s; + case Type.OBJECT: + String newType = map(t.getInternalName()); + if (newType != null) { + return 'L' + newType + ';'; + } } return desc; } private Type mapType(Type t) { switch (t.getSort()) { - case Type.ARRAY: - String s = mapDesc(t.getElementType().getDescriptor()); - for (int i = 0; i < t.getDimensions(); ++i) { - s = '[' + s; - } - return Type.getType(s); - case Type.OBJECT: - s = map(t.getInternalName()); - return s != null ? Type.getObjectType(s) : t; - case Type.METHOD: - return Type.getMethodType(mapMethodDesc(t.getDescriptor())); + case Type.ARRAY: + String s = mapDesc(t.getElementType().getDescriptor()); + for (int i = 0; i < t.getDimensions(); ++i) { + s = '[' + s; + } + return Type.getType(s); + case Type.OBJECT: + s = map(t.getInternalName()); + return s != null ? Type.getObjectType(s) : t; + case Type.METHOD: + return Type.getMethodType(mapMethodDesc(t.getDescriptor())); } return t; } @@ -135,18 +135,14 @@ public abstract class Remapper { needMapping = true; } if (needMapping) { - newTypes[i] = newType == null - ? type - : newType; + newTypes[i] = newType == null ? type : newType; } } - return needMapping - ? newTypes - : types; + return needMapping ? newTypes : types; } public String mapMethodDesc(String desc) { - if("()V".equals(desc)) { + if ("()V".equals(desc)) { return desc; } @@ -156,7 +152,7 @@ public abstract class Remapper { s.append(mapDesc(args[i].getDescriptor())); } Type returnType = Type.getReturnType(desc); - if(returnType == Type.VOID_TYPE) { + if (returnType == Type.VOID_TYPE) { s.append(")V"); return s.toString(); } @@ -170,9 +166,8 @@ public abstract class Remapper { } if (value instanceof Handle) { Handle h = (Handle) value; - return new Handle(h.getTag(), - mapType(h.getOwner()), - mapMethodName(h.getOwner(), h.getName(), h.getDesc()), + return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName( + h.getOwner(), h.getName(), h.getDesc()), mapMethodDesc(h.getDesc())); } return value; @@ -180,9 +175,10 @@ public abstract class Remapper { /** * - * @param typeSignature true if signature is a FieldTypeSignature, such as - * the signature parameter of the ClassVisitor.visitField or - * MethodVisitor.visitLocalVariable methods + * @param typeSignature + * true if signature is a FieldTypeSignature, such as the + * signature parameter of the ClassVisitor.visitField or + * MethodVisitor.visitLocalVariable methods */ public String mapSignature(String signature, boolean typeSignature) { if (signature == null) { @@ -200,17 +196,19 @@ public abstract class Remapper { } protected SignatureVisitor createRemappingSignatureAdapter( - SignatureVisitor v) - { + SignatureVisitor v) { return new RemappingSignatureAdapter(v, this); } /** * Map method name to the new name. Subclasses can override. * - * @param owner owner of the method. - * @param name name of the method. - * @param desc descriptor of the method. + * @param owner + * owner of the method. + * @param name + * name of the method. + * @param desc + * descriptor of the method. * @return new name of the method */ public String mapMethodName(String owner, String name, String desc) { @@ -220,8 +218,10 @@ public abstract class Remapper { /** * Map invokedynamic method name to the new name. Subclasses can override. * - * @param name name of the invokedynamic. - * @param desc descriptor of the invokedynamic. + * @param name + * name of the invokedynamic. + * @param desc + * descriptor of the invokedynamic. * @return new invokdynamic name. */ public String mapInvokeDynamicMethodName(String name, String desc) { @@ -231,9 +231,12 @@ public abstract class Remapper { /** * Map field name to the new name. Subclasses can override. * - * @param owner owner of the field. - * @param name name of the field - * @param desc descriptor of the field + * @param owner + * owner of the field. + * @param name + * name of the field + * @param desc + * descriptor of the field * @return new name of the field. */ public String mapFieldName(String owner, String name, String desc) { @@ -242,7 +245,6 @@ public abstract class Remapper { /** * Map type name to the new name. Subclasses can override. - * */ public String map(String typeName) { return typeName; diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java index ebe510dec362d1f2950f7846dd98da2155e32801..b9a1bc874aa96f442fc63f721c9df9504c2a1efe 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java @@ -71,18 +71,13 @@ public class RemappingAnnotationAdapter extends AnnotationVisitor { protected final Remapper remapper; - public RemappingAnnotationAdapter( - final AnnotationVisitor av, - final Remapper remapper) - { - this(Opcodes.ASM4, av, remapper); + public RemappingAnnotationAdapter(final AnnotationVisitor av, + final Remapper remapper) { + this(Opcodes.ASM5, av, remapper); } - protected RemappingAnnotationAdapter( - final int api, - final AnnotationVisitor av, - final Remapper remapper) - { + protected RemappingAnnotationAdapter(final int api, + final AnnotationVisitor av, final Remapper remapper) { super(api, av); this.remapper = remapper; } @@ -100,16 +95,14 @@ public class RemappingAnnotationAdapter extends AnnotationVisitor { @Override public AnnotationVisitor visitAnnotation(String name, String desc) { AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc)); - return v == null ? null : (v == av - ? this + return v == null ? null : (v == av ? this : new RemappingAnnotationAdapter(v, remapper)); } @Override public AnnotationVisitor visitArray(String name) { AnnotationVisitor v = av.visitArray(name); - return v == null ? null : (v == av - ? this + return v == null ? null : (v == av ? this : new RemappingAnnotationAdapter(v, remapper)); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java index 44fe939757c166d62d1517244c4800972a110052..28b736be7a4bb5af5de36f670fec6aa396deaaae 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java @@ -64,6 +64,7 @@ import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; /** * A {@link ClassVisitor} for type remapping. @@ -76,96 +77,74 @@ public class RemappingClassAdapter extends ClassVisitor { protected String className; - public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) - { - this(Opcodes.ASM4, cv, remapper); + public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) { + this(Opcodes.ASM5, cv, remapper); } - protected RemappingClassAdapter( - final int api, - final ClassVisitor cv, - final Remapper remapper) - { + protected RemappingClassAdapter(final int api, final ClassVisitor cv, + final Remapper remapper) { super(api, cv); this.remapper = remapper; } @Override - 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) { this.className = name; - super.visit(version, - access, - remapper.mapType(name), - remapper.mapSignature(signature, false), - remapper.mapType(superName), - interfaces == null ? null - : remapper.mapTypes(interfaces)); + super.visit(version, access, remapper.mapType(name), remapper + .mapSignature(signature, false), remapper.mapType(superName), + interfaces == null ? null : remapper.mapTypes(interfaces)); } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - AnnotationVisitor av; - av = super.visitAnnotation(remapper.mapDesc(desc), visible); + AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc), + visible); return av == null ? null : createRemappingAnnotationAdapter(av); } @Override - public FieldVisitor visitField( - int access, - String name, - String desc, - String signature, - Object value) - { + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath, + remapper.mapDesc(desc), visible); + return av == null ? null : createRemappingAnnotationAdapter(av); + } + + @Override + public FieldVisitor visitField(int access, String name, String desc, + String signature, Object value) { FieldVisitor fv = super.visitField(access, remapper.mapFieldName(className, name, desc), - remapper.mapDesc(desc), - remapper.mapSignature(signature, true), + remapper.mapDesc(desc), remapper.mapSignature(signature, true), remapper.mapValue(value)); return fv == null ? null : createRemappingFieldAdapter(fv); } @Override - 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) { String newDesc = remapper.mapMethodDesc(desc); - MethodVisitor mv = super.visitMethod(access, - remapper.mapMethodName(className, name, desc), - newDesc, - remapper.mapSignature(signature, false), + MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName( + className, name, desc), newDesc, remapper.mapSignature( + signature, false), exceptions == null ? null : remapper.mapTypes(exceptions)); - return mv == null ? null : createRemappingMethodAdapter(access, newDesc, mv); + return mv == null ? null : createRemappingMethodAdapter(access, + newDesc, mv); } @Override - public void visitInnerClass( - String name, - String outerName, - String innerName, - int access) - { - super.visitInnerClass(remapper.mapType(name), - outerName == null ? null : remapper.mapType(outerName), - innerName, // TODO should it be changed? - access); + public void visitInnerClass(String name, String outerName, + String innerName, int access) { + // TODO should innerName be changed? + super.visitInnerClass(remapper.mapType(name), outerName == null ? null + : remapper.mapType(outerName), innerName, access); } @Override public void visitOuterClass(String owner, String name, String desc) { - super.visitOuterClass(remapper.mapType(owner), - name == null ? null : remapper.mapMethodName(owner, name, desc), + super.visitOuterClass(remapper.mapType(owner), name == null ? null + : remapper.mapMethodName(owner, name, desc), desc == null ? null : remapper.mapMethodDesc(desc)); } @@ -173,17 +152,13 @@ public class RemappingClassAdapter extends ClassVisitor { return new RemappingFieldAdapter(fv, remapper); } - protected MethodVisitor createRemappingMethodAdapter( - int access, - String newDesc, - MethodVisitor mv) - { + protected MethodVisitor createRemappingMethodAdapter(int access, + String newDesc, MethodVisitor mv) { return new RemappingMethodAdapter(access, newDesc, mv, remapper); } protected AnnotationVisitor createRemappingAnnotationAdapter( - AnnotationVisitor av) - { + AnnotationVisitor av) { return new RemappingAnnotationAdapter(av, remapper); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java index a47da7017ec2ee959ee62080d06af56fbd32a713..9d94e5ee327511ad815b6850c91f3a46e9bbd977 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java @@ -62,6 +62,7 @@ package jdk.internal.org.objectweb.asm.commons; import jdk.internal.org.objectweb.asm.AnnotationVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; /** * A {@link FieldVisitor} adapter for type remapping. @@ -72,23 +73,28 @@ public class RemappingFieldAdapter extends FieldVisitor { private final Remapper remapper; - public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) - { - this(Opcodes.ASM4, fv, remapper); + public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) { + this(Opcodes.ASM5, fv, remapper); } - protected RemappingFieldAdapter( - final int api, - final FieldVisitor fv, - final Remapper remapper) - { + protected RemappingFieldAdapter(final int api, final FieldVisitor fv, + final Remapper remapper) { super(api, fv); this.remapper = remapper; } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc), visible); + AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc), + visible); + return av == null ? null : new RemappingAnnotationAdapter(av, remapper); + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath, + remapper.mapDesc(desc), visible); return av == null ? null : new RemappingAnnotationAdapter(av, remapper); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java index d4612b1deded664a22152358d77ebd17b49dd843..319d9dedc7e869e9c7a2fb4b911e9cd586cbd86b 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java @@ -64,6 +64,7 @@ import jdk.internal.org.objectweb.asm.Handle; import jdk.internal.org.objectweb.asm.Label; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; /** * A {@link LocalVariablesSorter} for type mapping. @@ -74,59 +75,51 @@ public class RemappingMethodAdapter extends LocalVariablesSorter { protected final Remapper remapper; - public RemappingMethodAdapter( - final int access, - final String desc, - final MethodVisitor mv, - final Remapper remapper) - { - this(Opcodes.ASM4, access, desc, mv, remapper); - } - - protected RemappingMethodAdapter( - final int api, - final int access, - final String desc, - final MethodVisitor mv, - final Remapper remapper) - { + public RemappingMethodAdapter(final int access, final String desc, + final MethodVisitor mv, final Remapper remapper) { + this(Opcodes.ASM5, access, desc, mv, remapper); + } + + protected RemappingMethodAdapter(final int api, final int access, + final String desc, final MethodVisitor mv, final Remapper remapper) { super(api, access, desc, mv); this.remapper = remapper; } @Override public AnnotationVisitor visitAnnotationDefault() { - AnnotationVisitor av = mv.visitAnnotationDefault(); + AnnotationVisitor av = super.visitAnnotationDefault(); return av == null ? av : new RemappingAnnotationAdapter(av, remapper); } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - AnnotationVisitor av = mv.visitAnnotation(remapper.mapDesc(desc), visible); + AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc), + visible); return av == null ? av : new RemappingAnnotationAdapter(av, remapper); } @Override - public AnnotationVisitor visitParameterAnnotation( - int parameter, - String desc, - boolean visible) - { - AnnotationVisitor av = mv.visitParameterAnnotation(parameter, - remapper.mapDesc(desc), - visible); + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath, + remapper.mapDesc(desc), visible); + return av == null ? av : new RemappingAnnotationAdapter(av, remapper); + } + + @Override + public AnnotationVisitor visitParameterAnnotation(int parameter, + String desc, boolean visible) { + AnnotationVisitor av = super.visitParameterAnnotation(parameter, + remapper.mapDesc(desc), visible); return av == null ? av : new RemappingAnnotationAdapter(av, remapper); } @Override - public void visitFrame( - int type, - int nLocal, - Object[] local, - int nStack, - Object[] stack) - { - super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack, remapEntries(nStack, stack)); + public void visitFrame(int type, int nLocal, Object[] local, int nStack, + Object[] stack) { + super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack, + remapEntries(nStack, stack)); } private Object[] remapEntries(int n, Object[] entries) { @@ -138,9 +131,8 @@ public class RemappingMethodAdapter extends LocalVariablesSorter { } do { Object t = entries[i]; - newEntries[i++] = t instanceof String - ? remapper.mapType((String) t) - : t; + newEntries[i++] = t instanceof String ? remapper + .mapType((String) t) : t; } while (i < n); return newEntries; } @@ -149,45 +141,30 @@ public class RemappingMethodAdapter extends LocalVariablesSorter { } @Override - public void visitFieldInsn( - int opcode, - String owner, - String name, - String desc) - { - super.visitFieldInsn(opcode, - remapper.mapType(owner), + public void visitFieldInsn(int opcode, String owner, String name, + String desc) { + super.visitFieldInsn(opcode, remapper.mapType(owner), remapper.mapFieldName(owner, name, desc), remapper.mapDesc(desc)); } @Override - public void visitMethodInsn( - int opcode, - String owner, - String name, - String desc) - { - super.visitMethodInsn(opcode, - remapper.mapType(owner), + public void visitMethodInsn(int opcode, String owner, String name, + String desc) { + super.visitMethodInsn(opcode, remapper.mapType(owner), remapper.mapMethodName(owner, name, desc), remapper.mapMethodDesc(desc)); } @Override - public void visitInvokeDynamicInsn( - String name, - String desc, - Handle bsm, - Object... bsmArgs) - { - for(int i=0; i. Instead, they must use the * {@link #SerialVersionUIDAdder(int, ClassVisitor)} version. * - * @param cv a {@link ClassVisitor} to which this visitor will delegate - * calls. + * @param cv + * a {@link ClassVisitor} to which this visitor will delegate + * calls. */ public SerialVersionUIDAdder(final ClassVisitor cv) { - this(Opcodes.ASM4, cv); + this(Opcodes.ASM5, cv); } /** * Creates a new {@link SerialVersionUIDAdder}. * - * @param api the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}. - * @param cv a {@link ClassVisitor} to which this visitor will delegate - * calls. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param cv + * a {@link ClassVisitor} to which this visitor will delegate + * calls. */ protected SerialVersionUIDAdder(final int api, final ClassVisitor cv) { super(api, cv); @@ -223,14 +226,9 @@ public class SerialVersionUIDAdder extends ClassVisitor { * information (step 1,2, and 3) for SVUID computation. */ @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) { computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0; if (computeSVUID) { @@ -247,13 +245,8 @@ public class SerialVersionUIDAdder extends ClassVisitor { * 7). Also determine if there is a class initializer (step 6). */ @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) { if (computeSVUID) { if ("".equals(name)) { hasStaticInitializer = true; @@ -289,13 +282,8 @@ public class SerialVersionUIDAdder extends ClassVisitor { * if the class already has a SVUID. */ @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) { if (computeSVUID) { if ("serialVersionUID".equals(name)) { // since the class already has SVUID, we won't be computing it. @@ -309,12 +297,11 @@ public class SerialVersionUIDAdder extends ClassVisitor { * computing serialVersionUID values. */ if ((access & Opcodes.ACC_PRIVATE) == 0 - || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) - { + || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) { int mods = access - & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE - | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC - | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT); + & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE + | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC + | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT); svuidFields.add(new Item(name, mods, desc)); } } @@ -330,7 +317,8 @@ public class SerialVersionUIDAdder extends ClassVisitor { * the class file in favor of the access bits InnerClass attribute. */ @Override - public void visitInnerClass(final String aname, final String outerName, final String innerName, final int attr_access) { + public void visitInnerClass(final String aname, final String outerName, + final String innerName, final int attr_access) { if ((name != null) && name.equals(aname)) { this.access = attr_access; } @@ -345,11 +333,7 @@ public class SerialVersionUIDAdder extends ClassVisitor { // compute SVUID and add it to the class if (computeSVUID && !hasSVUID) { try { - super.visitField(Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, - "serialVersionUID", - "J", - null, - new Long(computeSVUID())); + addSVUID(computeSVUID()); } catch (Throwable e) { throw new RuntimeException("Error while computing SVUID for " + name, e); @@ -364,12 +348,30 @@ public class SerialVersionUIDAdder extends ClassVisitor { // ------------------------------------------------------------------------ /** - * Returns the value of SVUID if the class doesn't have one already. Please - * note that 0 is returned if the class already has SVUID, thus use - * isHasSVUID to determine if the class already had an SVUID. + * Returns true if the class already has a SVUID field. The result of this + * method is only valid when visitEnd is or has been called. + * + * @return true if the class already has a SVUID field. + */ + public boolean hasSVUID() { + return hasSVUID; + } + + protected void addSVUID(long svuid) { + FieldVisitor fv = super.visitField(Opcodes.ACC_FINAL + + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, new Long( + svuid)); + if (fv != null) { + fv.visitEnd(); + } + } + + /** + * Computes and returns the value of SVUID. * * @return Returns the serial version UID - * @throws IOException if an I/O error occurs + * @throws IOException + * if an I/O error occurs */ protected long computeSVUID() throws IOException { ByteArrayOutputStream bos; @@ -459,8 +461,8 @@ public class SerialVersionUIDAdder extends ClassVisitor { * five int values named sha, the hash value would be computed as * follows: * - * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF) << - * 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) << + * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF) + * << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) << * 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) << * 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) << * 56; @@ -481,7 +483,8 @@ public class SerialVersionUIDAdder extends ClassVisitor { /** * Returns the SHA-1 message digest of the given value. * - * @param value the value whose SHA message digest must be computed. + * @param value + * the value whose SHA message digest must be computed. * @return the SHA-1 message digest of the given value. */ protected byte[] computeSHAdigest(final byte[] value) { @@ -495,24 +498,24 @@ public class SerialVersionUIDAdder extends ClassVisitor { /** * Sorts the items in the collection and writes it to the data output stream * - * @param itemCollection collection of items - * @param dos a DataOutputStream value - * @param dotted a boolean value - * @exception IOException if an error occurs + * @param itemCollection + * collection of items + * @param dos + * a DataOutputStream value + * @param dotted + * a boolean value + * @exception IOException + * if an error occurs */ - private static void writeItems( - final Collection itemCollection, - final DataOutput dos, - final boolean dotted) throws IOException - { + private static void writeItems(final Collection itemCollection, + final DataOutput dos, final boolean dotted) throws IOException { int size = itemCollection.size(); Item[] items = itemCollection.toArray(new Item[size]); Arrays.sort(items); for (int i = 0; i < size; i++) { dos.writeUTF(items[i].name); dos.writeInt(items[i].access); - dos.writeUTF(dotted - ? items[i].desc.replace('/', '.') + dos.writeUTF(dotted ? items[i].desc.replace('/', '.') : items[i].desc); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java index f459734f04b2558b365424b79842ec5e9a31cfc6..3514d0907876ce46452181dbc14f479119f8b805 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java @@ -78,39 +78,26 @@ public class StaticInitMerger extends ClassVisitor { private int counter; public StaticInitMerger(final String prefix, final ClassVisitor cv) { - this(Opcodes.ASM4, prefix, cv); + this(Opcodes.ASM5, prefix, cv); } - protected StaticInitMerger( - final int api, - final String prefix, - final ClassVisitor cv) - { + protected StaticInitMerger(final int api, final String prefix, + final ClassVisitor cv) { super(api, cv); this.prefix = prefix; } @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) { cv.visit(version, access, name, signature, superName, interfaces); this.name = name; } @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) { MethodVisitor mv; if ("".equals(name)) { int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC; diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java index a5009832381bfaf0c1943d1f8e301875b242dbd0..98d2a7f370046718d5960fd163b18fd662051b98 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java @@ -72,8 +72,10 @@ public interface TableSwitchGenerator { /** * Generates the code for a switch case. * - * @param key the switch case key. - * @param end a label that corresponds to the end of the switch statement. + * @param key + * the switch case key. + * @param end + * a label that corresponds to the end of the switch statement. */ void generateCase(int key, Label end); diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java b/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java index dd024e3dc8e4bb6b2c2373fbc7bb3bb15d68d686..0b2be355877e2dfbd4e34889f5d38899ac848537 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java @@ -66,6 +66,7 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.tree.MethodNode; import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode; +import jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode; /** * A {@link MethodVisitor} adapter to sort the exception handlers. The handlers @@ -83,26 +84,15 @@ import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode; */ public class TryCatchBlockSorter extends MethodNode { - public TryCatchBlockSorter( - final MethodVisitor mv, - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { - this(Opcodes.ASM4, mv, access, name, desc, signature, exceptions); + public TryCatchBlockSorter(final MethodVisitor mv, final int access, + final String name, final String desc, final String signature, + final String[] exceptions) { + this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions); } - protected TryCatchBlockSorter( - final int api, - final MethodVisitor mv, - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { + protected TryCatchBlockSorter(final int api, final MethodVisitor mv, + final int access, final String name, final String desc, + final String signature, final String[] exceptions) { super(api, access, name, desc, signature, exceptions); this.mv = mv; } @@ -125,6 +115,10 @@ public class TryCatchBlockSorter extends MethodNode { } }; Collections.sort(tryCatchBlocks, comp); + // Updates the 'target' of each try catch block annotation. + for (int i = 0; i < tryCatchBlocks.size(); ++i) { + tryCatchBlocks.get(i).updateIndex(i); + } if (mv != null) { accept(mv); } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java b/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java index b737c1237095c472752d469f6a42196756d813f4..50bb5666ae947bb36d050badfa0c71a389d934c5 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java @@ -75,8 +75,9 @@ public class SignatureReader { /** * Constructs a {@link SignatureReader} for the given signature. * - * @param signature A ClassSignature, MethodTypeSignature, - * or FieldTypeSignature. + * @param signature + * A ClassSignature, MethodTypeSignature, or + * FieldTypeSignature. */ public SignatureReader(final String signature) { this.signature = signature; @@ -87,15 +88,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 ClassSignature (such as the + * created using a ClassSignature (such as the signature + * parameter of the {@link jdk.internal.org.objectweb.asm.ClassVisitor#visit + * ClassVisitor.visit} method) or a MethodTypeSignature (such as the * signature parameter of the - * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visit ClassVisitor.visit} method) - * or a MethodTypeSignature (such as the signature - * parameter of the - * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod} - * method). + * {@link jdk.internal.org.objectweb.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; @@ -147,12 +148,12 @@ public class SignatureReader { * method is intended to be called on a {@link SignatureReader} that was * created using a FieldTypeSignature, such as the * signature parameter of the - * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitField - * ClassVisitor.visitField} or {@link - * jdk.internal.org.objectweb.asm.MethodVisitor#visitLocalVariable + * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitField ClassVisitor.visitField} + * or {@link jdk.internal.org.objectweb.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); @@ -161,98 +162,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/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java index d3699c17922eb6ab488b6ac4d9d97e4a1ae33f10..5b9cb702abb05c4216cfc3ae104b5e6436876276 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java @@ -64,21 +64,21 @@ import jdk.internal.org.objectweb.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):
        • ClassSignature = ( - * visitFormalTypeParameter - * visitClassBound? - * visitInterfaceBound* )* ( visitSuperClass - * visitInterface* )
        • + * interface): + *
            + *
          • ClassSignature = ( visitFormalTypeParameter + * visitClassBound? visitInterfaceBound* )* ( + * visitSuperClass visitInterface* )
          • *
          • MethodSignature = ( visitFormalTypeParameter - * visitClassBound? - * visitInterfaceBound* )* ( visitParameterType* - * visitReturnType - * visitExceptionType* )
          • TypeSignature = - * visitBaseType | visitTypeVariable | - * visitArrayType | ( + * visitClassBound? visitInterfaceBound* )* ( + * visitParameterType* visitReturnType + * visitExceptionType* )
          • + *
          • TypeSignature = visitBaseType | + * visitTypeVariable | visitArrayType | ( * visitClassType visitTypeArgument* ( - * visitInnerClassType visitTypeArgument* )* - * visitEnd ) )
          + * visitInnerClassType visitTypeArgument* )* visitEnd + * ) ) + *
        * * @author Thomas Hallgren * @author Eric Bruneton @@ -102,24 +102,29 @@ public abstract class SignatureVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4}. + * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. */ protected final int api; /** * 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} or {@link Opcodes#ASM5}. */ public SignatureVisitor(final int api) { + if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { + throw new IllegalArgumentException(); + } this.api = api; } /** * 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) { } @@ -191,8 +196,9 @@ public abstract class SignatureVisitor { /** * Visits a signature corresponding to a primitive type. * - * @param descriptor the descriptor of the primitive type, or 'V' for - * void. + * @param descriptor + * the descriptor of the primitive type, or 'V' for void + * . */ public void visitBaseType(char descriptor) { } @@ -200,7 +206,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) { } @@ -219,7 +226,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) { } @@ -227,7 +235,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) { } @@ -242,7 +251,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/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java b/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java index b341e00362a57dfce20caba3d8bbc90eacf04f67..0d761663ea0a11124086def70997d186b87b50fd 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java @@ -95,7 +95,7 @@ public class SignatureWriter extends SignatureVisitor { * Constructs a new {@link SignatureWriter} object. */ public SignatureWriter() { - super(Opcodes.ASM4); + super(Opcodes.ASM5); } // ------------------------------------------------------------------------ diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java index a9654763a611c2fd218c5c582e5bd4b68d0b9c15..8ea77fcdd165143f8a1b77b1bee3b1d28d38f3a0 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java @@ -58,6 +58,7 @@ */ package jdk.internal.org.objectweb.asm.tree; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -156,6 +157,28 @@ public abstract class AbstractInsnNode { */ protected int opcode; + /** + * The runtime visible type annotations of this instruction. This field is + * only used for real instructions (i.e. not for labels, frames, or line + * number nodes). This list is a list of {@link TypeAnnotationNode} objects. + * May be null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List visibleTypeAnnotations; + + /** + * The runtime invisible type annotations of this instruction. This field is + * only used for real instructions (i.e. not for labels, frames, or line + * number nodes). This list is a list of {@link TypeAnnotationNode} objects. + * May be null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List invisibleTypeAnnotations; + /** * Previous instruction in the list to which this instruction belongs. */ @@ -177,7 +200,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; @@ -226,42 +250,106 @@ 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); + /** + * Makes the given visitor visit the annotations of this instruction. + * + * @param mv + * a method visitor. + */ + protected final void acceptAnnotations(final MethodVisitor mv) { + int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations + .size(); + for (int i = 0; i < n; ++i) { + TypeAnnotationNode an = visibleTypeAnnotations.get(i); + an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc, + true)); + } + n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations + .size(); + for (int i = 0; i < n; ++i) { + TypeAnnotationNode an = invisibleTypeAnnotations.get(i); + an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc, + false)); + } + } + /** * 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 labels); + public abstract AbstractInsnNode clone( + final Map 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 map) { + static LabelNode clone(final LabelNode label, + final Map 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 labels, final Map map) { + static LabelNode[] clone(final List labels, + final Map map) { LabelNode[] clones = new LabelNode[labels.size()]; for (int i = 0; i < clones.length; ++i) { clones[i] = map.get(labels.get(i)); } return clones; } + + /** + * Clones the annotations of the given instruction into this instruction. + * + * @param insn + * the source instruction. + * @return this instruction. + */ + protected final AbstractInsnNode cloneAnnotations( + final AbstractInsnNode insn) { + if (insn.visibleTypeAnnotations != null) { + this.visibleTypeAnnotations = new ArrayList(); + for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) { + TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i); + TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef, + src.typePath, src.desc); + src.accept(ann); + this.visibleTypeAnnotations.add(ann); + } + } + if (insn.invisibleTypeAnnotations != null) { + this.invisibleTypeAnnotations = new ArrayList(); + for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) { + TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i); + TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef, + src.typePath, src.desc); + src.accept(ann); + this.invisibleTypeAnnotations.add(ann); + } + } + return this; + } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java index 6f53ed76ca3abdf4687a2d84ea5c0b8bcaf2a18e..57b88f1b11fad2d339bc8a3bc9f62e1029565189 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java @@ -84,8 +84,8 @@ public class AnnotationNode extends AnnotationVisitor { * {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.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 null if there is no name - * value pair. + * preceding types. The list may be null if there is no name value + * pair. */ public List values; @@ -94,18 +94,21 @@ public class AnnotationNode extends AnnotationVisitor { * constructor. 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); + this(Opcodes.ASM5, desc); } /** * 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} or {@link Opcodes#ASM5}. + * @param desc + * the class descriptor of the annotation class. */ public AnnotationNode(final int api, final String desc) { super(api); @@ -115,10 +118,11 @@ 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 values) { - super(Opcodes.ASM4); + super(Opcodes.ASM5); this.values = values; } @@ -138,11 +142,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(this.desc != null ? 2 : 1); } @@ -153,10 +154,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(this.desc != null ? 2 : 1); } @@ -195,7 +194,9 @@ 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} or + * {@link Opcodes#ASM5}. */ public void check(final int api) { // nothing to do @@ -204,7 +205,8 @@ public class AnnotationNode extends AnnotationVisitor { /** * Makes the given visitor visit this annotation. * - * @param av an annotation visitor. Maybe null. + * @param av + * an annotation visitor. Maybe null. */ public void accept(final AnnotationVisitor av) { if (av != null) { @@ -222,15 +224,15 @@ public class AnnotationNode extends AnnotationVisitor { /** * Makes the given visitor visit a given annotation value. * - * @param av an annotation visitor. Maybe null. - * @param name the value name. - * @param value the actual value. + * @param av + * an annotation visitor. Maybe null. + * @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/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java index 81b36c8d40dca00a06eca8f29a040dd22da614f3..cb70518aa93179b578020dad9e163ffa580e9820 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java @@ -68,6 +68,7 @@ import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; /** * A node that represents a class. @@ -94,15 +95,15 @@ public class ClassNode extends ClassVisitor { public String name; /** - * The signature of the class. Mayt be null. + * The signature of the class. May be null. */ public String signature; /** * The internal of name of the super class (see * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). For - * interfaces, the super class is {@link Object}. May be null, - * but only for the {@link Object} class. + * interfaces, the super class is {@link Object}. May be null, but + * only for the {@link Object} class. */ public String superName; @@ -120,7 +121,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 null. */ public String sourceDebug; @@ -138,8 +139,8 @@ public class ClassNode extends ClassVisitor { public String outerMethod; /** - * The descriptor of the method that contains the class, or null - * if the class is not enclosed in a method. + * The descriptor of the method that contains the class, or null if + * the class is not enclosed in a method. */ public String outerMethodDesc; @@ -161,6 +162,24 @@ public class ClassNode extends ClassVisitor { */ public List invisibleAnnotations; + /** + * The runtime visible type annotations of this class. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List visibleTypeAnnotations; + + /** + * The runtime invisible type annotations of this class. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List invisibleTypeAnnotations; + /** * The non standard attributes of this class. This list is a list of * {@link Attribute} objects. May be null. @@ -199,14 +218,15 @@ public class ClassNode extends ClassVisitor { * version. */ public ClassNode() { - this(Opcodes.ASM4); + this(Opcodes.ASM5); } /** * 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} or {@link Opcodes#ASM5}. */ public ClassNode(final int api) { super(api); @@ -221,14 +241,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; @@ -246,21 +261,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) { @@ -276,6 +286,24 @@ public class ClassNode extends ClassVisitor { return an; } + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); + if (visible) { + if (visibleTypeAnnotations == null) { + visibleTypeAnnotations = new ArrayList(1); + } + visibleTypeAnnotations.add(an); + } else { + if (invisibleTypeAnnotations == null) { + invisibleTypeAnnotations = new ArrayList(1); + } + invisibleTypeAnnotations.add(an); + } + return an; + } + @Override public void visitAttribute(final Attribute attr) { if (attrs == null) { @@ -285,44 +313,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; @@ -342,16 +351,34 @@ 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} or + * {@link Opcodes#ASM5}. */ public void check(final int api) { - // nothing to do + if (api == Opcodes.ASM4) { + if (visibleTypeAnnotations != null + && visibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + if (invisibleTypeAnnotations != null + && invisibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + for (FieldNode f : fields) { + f.check(api); + } + for (MethodNode m : methods) { + m.check(api); + } + } } /** * 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 @@ -378,6 +405,19 @@ public class ClassNode extends ClassVisitor { AnnotationNode an = invisibleAnnotations.get(i); an.accept(cv.visitAnnotation(an.desc, false)); } + n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); + for (i = 0; i < n; ++i) { + TypeAnnotationNode an = visibleTypeAnnotations.get(i); + an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, + true)); + } + n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations + .size(); + for (i = 0; i < n; ++i) { + TypeAnnotationNode an = invisibleTypeAnnotations.get(i); + an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, + false)); + } n = attrs == null ? 0 : attrs.size(); for (i = 0; i < n; ++i) { cv.visitAttribute(attrs.get(i)); diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java index b6bcca99956e0b79845a2a7df048d9ce0dff6a61..407a1ee23067cdff9367b01a8541e6436d71f083 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java @@ -89,19 +89,20 @@ public class FieldInsnNode extends AbstractInsnNode { /** * 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 jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). - * @param name the field's name. - * @param desc the field's descriptor (see {@link jdk.internal.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 jdk.internal.org.objectweb.asm.Type#getInternalName() + * getInternalName}). + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link jdk.internal.org.objectweb.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; @@ -111,8 +112,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; @@ -124,12 +126,14 @@ public class FieldInsnNode extends AbstractInsnNode { } @Override - public void accept(final MethodVisitor cv) { - cv.visitFieldInsn(opcode, owner, name, desc); + public void accept(final MethodVisitor mv) { + mv.visitFieldInsn(opcode, owner, name, desc); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new FieldInsnNode(opcode, owner, name, desc); + return new FieldInsnNode(opcode, owner, name, desc) + .cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java index d25842b0c07391d4dc463ad7cf73817dd9f14703..a155d2c1b805016ab84b029ddc57f8a9d684330d 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java @@ -66,6 +66,7 @@ import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; /** * A node that represents a field. @@ -96,8 +97,8 @@ public class FieldNode extends FieldVisitor { public String signature; /** - * The field's initial value. This field, which may be null 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 null 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; @@ -120,6 +121,24 @@ public class FieldNode extends FieldVisitor { */ public List invisibleAnnotations; + /** + * The runtime visible type annotations of this field. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List visibleTypeAnnotations; + + /** + * The runtime invisible type annotations of this field. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List invisibleTypeAnnotations; + /** * The non standard attributes of this field. This list is a list of * {@link Attribute} objects. May be null. @@ -133,26 +152,26 @@ public class FieldNode extends FieldVisitor { * constructor. Instead, they must use the * {@link #FieldNode(int, int, String, String, String, Object)} version. * - * @param access the field's access flags (see - * {@link jdk.internal.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 jdk.internal.org.objectweb.asm.Type - * Type}). - * @param signature the field's signature. - * @param value the field's initial value. This parameter, which may be - * null 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 jdk.internal.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 jdk.internal.org.objectweb.asm.Type + * Type}). + * @param signature + * the field's signature. + * @param value + * the field's initial value. This parameter, which may be + * null 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) - { - this(Opcodes.ASM4, access, name, desc, signature, value); + public FieldNode(final int access, final String name, final String desc, + final String signature, final Object value) { + this(Opcodes.ASM5, access, name, desc, signature, value); } /** @@ -160,28 +179,28 @@ public class FieldNode extends FieldVisitor { * constructor. 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 jdk.internal.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 jdk.internal.org.objectweb.asm.Type - * Type}). - * @param signature the field's signature. - * @param value the field's initial value. This parameter, which may be - * null 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} or {@link Opcodes#ASM5}. + * @param access + * the field's access flags (see + * {@link jdk.internal.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 jdk.internal.org.objectweb.asm.Type + * Type}). + * @param signature + * the field's signature. + * @param value + * the field's initial value. This parameter, which may be + * null 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; @@ -195,10 +214,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) { @@ -214,6 +231,24 @@ public class FieldNode extends FieldVisitor { return an; } + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); + if (visible) { + if (visibleTypeAnnotations == null) { + visibleTypeAnnotations = new ArrayList(1); + } + visibleTypeAnnotations.add(an); + } else { + if (invisibleTypeAnnotations == null) { + invisibleTypeAnnotations = new ArrayList(1); + } + invisibleTypeAnnotations.add(an); + } + return an; + } + @Override public void visitAttribute(final Attribute attr) { if (attrs == null) { @@ -236,16 +271,28 @@ 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} or + * {@link Opcodes#ASM5}. */ public void check(final int api) { - // nothing to do + if (api == Opcodes.ASM4) { + if (visibleTypeAnnotations != null + && visibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + if (invisibleTypeAnnotations != null + && invisibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + } } /** * 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); @@ -263,6 +310,19 @@ public class FieldNode extends FieldVisitor { AnnotationNode an = invisibleAnnotations.get(i); an.accept(fv.visitAnnotation(an.desc, false)); } + n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); + for (i = 0; i < n; ++i) { + TypeAnnotationNode an = visibleTypeAnnotations.get(i); + an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, + true)); + } + n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations + .size(); + for (i = 0; i < n; ++i) { + TypeAnnotationNode an = invisibleTypeAnnotations.get(i); + an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, + false)); + } n = attrs == null ? 0 : attrs.size(); for (i = 0; i < n; ++i) { fv.visitAttribute(attrs.get(i)); diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java index 42975b3bf468221161e38156d7f884f318af584d..02a26b232eecdc19e4c384fcbb5b309bf9c48b9f 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java @@ -74,8 +74,9 @@ import jdk.internal.org.objectweb.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 just before i is executed.
        - *
        (*) this is mandatory only for classes whose version is greater than or - * equal to {@link Opcodes#V1_6 V1_6}. + *
        + * (*) this is mandatory only for classes whose version is greater than or equal + * to {@link Opcodes#V1_6 V1_6}. * * @author Eric Bruneton */ @@ -112,48 +113,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; } } @@ -165,31 +166,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/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java index 2c390e5693b8281b6a5f56e2011cf85983683c72..7be4de66e3dcf0bf875814c725d15056300aa573 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java @@ -83,8 +83,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); @@ -100,10 +102,11 @@ public class IincInsnNode extends AbstractInsnNode { @Override public void accept(final MethodVisitor mv) { mv.visitIincInsn(var, incr); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new IincInsnNode(var, incr); + return new IincInsnNode(var, incr).cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java index 38e19d9adc4674356c3fc1631485c8dc96da5655..88fe0a8665709ca27ba014c98f5c66eec2d4b9dd 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java @@ -75,8 +75,8 @@ public class InnerClassNode { /** * The internal name of the class to which the inner class belongs (see - * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). May - * be null. + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). May be + * null. */ public String outerName; @@ -95,24 +95,23 @@ public class InnerClassNode { /** * Constructs a new {@link InnerClassNode}. * - * @param name the internal name of an inner class (see - * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). - * @param outerName the internal name of the class to which the inner class - * belongs (see - * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). - * May be null. - * @param innerName the (simple) name of the inner class inside its - * enclosing class. May be null 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 jdk.internal.org.objectweb.asm.Type#getInternalName() + * getInternalName}). + * @param outerName + * the internal name of the class to which the inner class + * belongs (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName() + * getInternalName}). May be null. + * @param innerName + * the (simple) name of the inner class inside its enclosing + * class. May be null 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; @@ -122,7 +121,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/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java index d1c2f5c6b1dcf54500f90d1e1b89e6a0bae7f69d..2ba917cb6a314ac5fbe7ac92409bfdd0816fb37c 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java @@ -102,8 +102,8 @@ public class InsnList { /** * Returns the first instruction in this list. * - * @return the first instruction in this list, or null if the - * list is empty. + * @return the first instruction in this list, or null if the list + * is empty. */ public AbstractInsnNode getFirst() { return first; @@ -125,9 +125,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) { @@ -140,11 +142,12 @@ public class InsnList { } /** - * Returns true if the given instruction belongs to this list. - * This method always scans the instructions of this list until it finds the + * Returns true 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 true if the given instruction belongs to this list. */ public boolean contains(final AbstractInsnNode insn) { @@ -162,7 +165,8 @@ public class InsnList { * constant time. The cache is invalidated by all the methods that modify * the list. * - * @param insn an instruction of this list. + * @param insn + * an instruction of this list. * @return the index of the given instruction in this list. The result of * this method is undefined if the given instruction does not belong * to this list. Use {@link #contains contains} to test if an @@ -178,7 +182,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; @@ -227,9 +232,11 @@ public class InsnList { /** * Replaces an instruction of this list with another instruction. * - * @param location an instruction of this list. - * @param insn another instruction, which must not belong to any - * {@link InsnList}. + * @param location + * an instruction of this list. + * @param insn + * another instruction, which must not belong to any + * {@link InsnList}. */ public void set(final AbstractInsnNode location, final AbstractInsnNode insn) { AbstractInsnNode next = location.next; @@ -261,8 +268,9 @@ public class InsnList { /** * Adds the given instruction to the end of this list. * - * @param insn an instruction, which must not belong to any - * {@link InsnList}. + * @param insn + * an instruction, which must not belong to any + * {@link InsnList}. */ public void add(final AbstractInsnNode insn) { ++size; @@ -281,8 +289,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) { @@ -305,8 +314,9 @@ public class InsnList { /** * Inserts the given instruction at the begining of this list. * - * @param insn an instruction, which must not belong to any - * {@link InsnList}. + * @param insn + * an instruction, which must not belong to any + * {@link InsnList}. */ public void insert(final AbstractInsnNode insn) { ++size; @@ -325,8 +335,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) { @@ -349,12 +360,15 @@ public class InsnList { /** * Inserts the given instruction after the specified instruction. * - * @param location an instruction of this list after which insn must be - * inserted. - * @param insn the instruction to be inserted, which must not belong to - * any {@link InsnList}. + * @param location + * an instruction of this list after which insn must be + * inserted. + * @param insn + * the instruction to be inserted, which must not belong to + * any {@link InsnList}. */ - 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) { @@ -372,10 +386,12 @@ public class InsnList { /** * Inserts the given instructions after the specified instruction. * - * @param location an instruction of this list 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 of this list 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) { @@ -400,12 +416,15 @@ public class InsnList { /** * Inserts the given instruction before the specified instruction. * - * @param location an instruction of this list before which insn must be - * inserted. - * @param insn the instruction to be inserted, which must not belong to - * any {@link InsnList}. + * @param location + * an instruction of this list before which insn must be + * inserted. + * @param insn + * the instruction to be inserted, which must not belong to + * any {@link InsnList}. */ - 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) { @@ -423,37 +442,39 @@ public class InsnList { /** * Inserts the given instructions before the specified instruction. * - * @param location an instruction of this list 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 of this list 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 of this list that must be removed. + * @param insn + * the instruction of this list that must be removed. */ public void remove(final AbstractInsnNode insn) { --size; @@ -485,8 +506,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) { @@ -528,14 +550,14 @@ public class InsnList { } // this class is not generified because it will create bridges - private final class InsnListIterator implements ListIterator/**/ { + 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/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java index 62ac38546b8d69e5c9519b592733ad69306b1b52..10e0c1a6703112e5dcf4c2ffb52902066d45b9ee 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java @@ -72,20 +72,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); @@ -99,15 +101,17 @@ 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) { mv.visitInsn(opcode); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new InsnNode(opcode); + return new InsnNode(opcode).cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java index d1b88f521d197164397aac6a4ae090faea1d16d2..5e744d1212b11f13e69b823f03ff9901b2515130 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java @@ -77,9 +77,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); @@ -89,8 +91,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; @@ -104,10 +107,11 @@ public class IntInsnNode extends AbstractInsnNode { @Override public void accept(final MethodVisitor mv) { mv.visitIntInsn(opcode, operand); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new IntInsnNode(opcode, operand); + return new IntInsnNode(opcode, operand).cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java index 2370b3026d818490eec19333d8236521444cd8ab..12a40baeffd9a0c0ca0f6700e056cf12e65fec78 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java @@ -94,17 +94,17 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode { /** * Constructs a new {@link InvokeDynamicInsnNode}. * - * @param name invokedynamic name. - * @param desc invokedynamic descriptor (see {@link jdk.internal.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 jdk.internal.org.objectweb.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; @@ -120,10 +120,12 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode { @Override public void accept(final MethodVisitor mv) { mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs); + return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs) + .cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java index 265e1c88e876efbb26096df2f76043ce55c14a96..42b34ec584211803bc21e627fdc85c313efbc81e 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java @@ -79,13 +79,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); @@ -95,10 +97,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; @@ -112,10 +115,12 @@ public class JumpInsnNode extends AbstractInsnNode { @Override public void accept(final MethodVisitor mv) { mv.visitJumpInsn(opcode, label.getLabel()); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new JumpInsnNode(opcode, clone(label, labels)); + return new JumpInsnNode(opcode, clone(label, labels)) + .cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java index 7220d9172a9c5f4c2ec3dc320c1654038873d58f..ef435052819891fbe8f96a6db2f5c21ff771fc12 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java @@ -80,9 +80,10 @@ public class LdcInsnNode extends AbstractInsnNode { /** * 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); @@ -97,10 +98,11 @@ public class LdcInsnNode extends AbstractInsnNode { @Override public void accept(final MethodVisitor mv) { mv.visitLdcInsn(cst); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new LdcInsnNode(cst); + return new LdcInsnNode(cst).cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java index 7160d30283244db24c2e3fec89d95df8a90a34e8..ca5add056025fcb61e52f583e7e7745e05161219 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java @@ -84,9 +84,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/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java new file mode 100644 index 0000000000000000000000000000000000000000..6bb549b5abbb39e06f23e00e30f1a1cfb04dce12 --- /dev/null +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java @@ -0,0 +1,186 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * 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 jdk.internal.org.objectweb.asm.tree; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import jdk.internal.org.objectweb.asm.Label; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; +import jdk.internal.org.objectweb.asm.TypeReference; + +/** + * A node that represents a type annotation on a local or resource variable. + * + * @author Eric Bruneton + */ +public class LocalVariableAnnotationNode extends TypeAnnotationNode { + + /** + * The fist instructions corresponding to the continuous ranges that make + * the scope of this local variable (inclusive). Must not be null. + */ + public List start; + + /** + * The last instructions corresponding to the continuous ranges that make + * the scope of this local variable (exclusive). This list must have the + * same size as the 'start' list. Must not be null. + */ + public List end; + + /** + * The local variable's index in each range. This list must have the same + * size as the 'start' list. Must not be null. + */ + public List index; + + /** + * Constructs a new {@link LocalVariableAnnotationNode}. Subclasses must + * not use this constructor. Instead, they must use the + * {@link #LocalVariableAnnotationNode(int, TypePath, LabelNode[], LabelNode[], int[], String)} + * version. + * + * @param typeRef + * a reference to the annotated type. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param start + * the fist instructions corresponding to the continuous ranges + * that make the scope of this local variable (inclusive). + * @param end + * the last instructions corresponding to the continuous ranges + * that make the scope of this local variable (exclusive). This + * array must have the same size as the 'start' array. + * @param index + * the local variable's index in each range. This array must have + * the same size as the 'start' array. + * @param desc + * the class descriptor of the annotation class. + */ + public LocalVariableAnnotationNode(int typeRef, TypePath typePath, + LabelNode[] start, LabelNode[] end, int[] index, String desc) { + this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc); + } + + /** + * Constructs a new {@link LocalVariableAnnotationNode}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param typeRef + * a reference to the annotated type. See {@link TypeReference}. + * @param start + * the fist instructions corresponding to the continuous ranges + * that make the scope of this local variable (inclusive). + * @param end + * the last instructions corresponding to the continuous ranges + * that make the scope of this local variable (exclusive). This + * array must have the same size as the 'start' array. + * @param index + * the local variable's index in each range. This array must have + * the same size as the 'start' array. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + */ + public LocalVariableAnnotationNode(int api, int typeRef, TypePath typePath, + LabelNode[] start, LabelNode[] end, int[] index, String desc) { + super(api, typeRef, typePath, desc); + this.start = new ArrayList(start.length); + this.start.addAll(Arrays.asList(start)); + this.end = new ArrayList(end.length); + this.end.addAll(Arrays.asList(end)); + this.index = new ArrayList(index.length); + for (int i : index) { + this.index.add(i); + } + } + + /** + * Makes the given visitor visit this type annotation. + * + * @param mv + * the visitor that must visit this annotation. + * @param visible + * true if the annotation is visible at runtime. + */ + public void accept(final MethodVisitor mv, boolean visible) { + Label[] start = new Label[this.start.size()]; + Label[] end = new Label[this.end.size()]; + int[] index = new int[this.index.size()]; + for (int i = 0; i < start.length; ++i) { + start[i] = this.start.get(i).getLabel(); + end[i] = this.end.get(i).getLabel(); + index[i] = this.index.get(i); + } + accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end, + index, desc, true)); + } +} diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java index 0d3272b20209156308394fad9e7d5b8346aec8cd..45ada56960715625331a9e4ec5ad0da1b7e8f9cc 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java @@ -102,24 +102,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 - * null. - * @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 null. + * @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; @@ -131,14 +131,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/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java index 8a801dd91f3875372fed1b170cc8e2581c0845a0..b1daa382f674b0d6c12f6379de5e0e72e1ef0c9a 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java @@ -93,20 +93,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. labels[i] is - * the beginning of the handler block for the keys[i] key. + * @param dflt + * beginning of the default handler block. + * @param keys + * the values of the keys. + * @param labels + * beginnings of the handler blocks. labels[i] is the + * beginning of the handler block for the keys[i] 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(keys == null ? 0 : keys.length); - this.labels = new ArrayList(labels == null ? 0 : labels.length); + this.labels = new ArrayList(labels == null ? 0 + : labels.length); if (keys != null) { for (int i = 0; i < keys.length; ++i) { this.keys.add(new Integer(keys[i])); @@ -133,6 +134,7 @@ public class LookupSwitchInsnNode extends AbstractInsnNode { labels[i] = this.labels.get(i).getLabel(); } mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels); + acceptAnnotations(mv); } @Override @@ -140,6 +142,6 @@ public class LookupSwitchInsnNode extends AbstractInsnNode { LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt, labels), null, clone(this.labels, labels)); clone.keys.addAll(keys); - return clone; + return clone.cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java index 16d554fc1cf024f05281a9a3008e24de8cedfa9d..6f6d5dc4453b4d1fce7c503c3400efe1980c590e 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java @@ -89,20 +89,21 @@ public class MethodInsnNode extends AbstractInsnNode { /** * 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 jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). - * @param name the method's name. - * @param desc the method's descriptor (see {@link jdk.internal.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 jdk.internal.org.objectweb.asm.Type#getInternalName() + * getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link jdk.internal.org.objectweb.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; @@ -112,8 +113,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; diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java index ab60cf234ca0b5258d3397098f9823fee05abe7c..072d549265ce59c3528fdca346678828be2408a0 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java @@ -30,7 +30,6 @@ * * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom - * Copyright (c) 2011 Google * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,6 +70,8 @@ import jdk.internal.org.objectweb.asm.Label; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; +import jdk.internal.org.objectweb.asm.TypePath; +import jdk.internal.org.objectweb.asm.TypeReference; /** * A node that represents a method. @@ -107,6 +108,11 @@ public class MethodNode extends MethodVisitor { */ public List exceptions; + /** + * The method parameter info (access flags and name) + */ + public List parameters; + /** * The runtime visible annotations of this method. This list is a list of * {@link AnnotationNode} objects. May be null. @@ -125,6 +131,24 @@ public class MethodNode extends MethodVisitor { */ public List invisibleAnnotations; + /** + * The runtime visible type annotations of this method. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List visibleTypeAnnotations; + + /** + * The runtime invisible type annotations of this method. This list is a + * list of {@link TypeAnnotationNode} objects. May be null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List invisibleTypeAnnotations; + /** * The non standard attributes of this method. This list is a list of * {@link Attribute} objects. May be null. @@ -196,6 +220,22 @@ public class MethodNode extends MethodVisitor { */ public List localVariables; + /** + * The visible local variable annotations of this method. This list is a + * list of {@link LocalVariableAnnotationNode} objects. May be null + * + * @associates jdk.internal.org.objectweb.asm.tree.LocalVariableAnnotationNode + */ + public List visibleLocalVariableAnnotations; + + /** + * The invisible local variable annotations of this method. This list is a + * list of {@link LocalVariableAnnotationNode} objects. May be null + * + * @associates jdk.internal.org.objectweb.asm.tree.LocalVariableAnnotationNode + */ + public List invisibleLocalVariableAnnotations; + /** * If the accept method has been called on this object. */ @@ -207,14 +247,15 @@ public class MethodNode extends MethodVisitor { * {@link #MethodNode(int)} version. */ public MethodNode() { - this(Opcodes.ASM4); + this(Opcodes.ASM5); } /** * 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} or {@link Opcodes#ASM5}. */ public MethodNode(final int api) { super(api); @@ -226,56 +267,55 @@ public class MethodNode extends MethodVisitor { * constructor. 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 null. - * @param exceptions the internal names of the method's exception classes - * (see {@link Type#getInternalName() getInternalName}). May be - * null. + * @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 null. + * @param exceptions + * the internal names of the method's exception classes (see + * {@link Type#getInternalName() getInternalName}). May be + * null. */ - 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); + public MethodNode(final int access, final String name, final String desc, + final String signature, final String[] exceptions) { + this(Opcodes.ASM5, 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 null. - * @param exceptions the internal names of the method's exception classes - * (see {@link Type#getInternalName() getInternalName}). May be - * null. + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @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 null. + * @param exceptions + * the internal names of the method's exception classes (see + * {@link Type#getInternalName() getInternalName}). May be + * null. */ - 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(exceptions == null - ? 0 + this.exceptions = new ArrayList(exceptions == null ? 0 : exceptions.length); boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0; if (!isAbstract) { @@ -292,6 +332,14 @@ public class MethodNode extends MethodVisitor { // Implementation of the MethodVisitor abstract class // ------------------------------------------------------------------------ + @Override + public void visitParameter(String name, int access) { + if (parameters == null) { + parameters = new ArrayList(5); + } + parameters.add(new ParameterNode(name, access)); + } + @Override public AnnotationVisitor visitAnnotationDefault() { return new AnnotationNode(new ArrayList(0) { @@ -304,10 +352,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) { @@ -324,28 +370,45 @@ public class MethodNode extends MethodVisitor { } @Override - public AnnotationVisitor visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) - { + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); + if (visible) { + if (visibleTypeAnnotations == null) { + visibleTypeAnnotations = new ArrayList(1); + } + visibleTypeAnnotations.add(an); + } else { + if (invisibleTypeAnnotations == null) { + invisibleTypeAnnotations = new ArrayList(1); + } + invisibleTypeAnnotations.add(an); + } + return an; + } + + @Override + 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[])new List[params]; + visibleParameterAnnotations = (List[]) new List[params]; } if (visibleParameterAnnotations[parameter] == null) { - visibleParameterAnnotations[parameter] = new ArrayList(1); + visibleParameterAnnotations[parameter] = new ArrayList( + 1); } visibleParameterAnnotations[parameter].add(an); } else { if (invisibleParameterAnnotations == null) { int params = Type.getArgumentTypes(this.desc).length; - invisibleParameterAnnotations = (List[])new List[params]; + invisibleParameterAnnotations = (List[]) new List[params]; } if (invisibleParameterAnnotations[parameter] == null) { - invisibleParameterAnnotations[parameter] = new ArrayList(1); + invisibleParameterAnnotations[parameter] = new ArrayList( + 1); } invisibleParameterAnnotations[parameter].add(an); } @@ -365,17 +428,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))); } @@ -400,32 +456,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)); } @@ -450,26 +494,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))); } @@ -479,33 +513,89 @@ public class MethodNode extends MethodVisitor { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public AnnotationVisitor visitInsnAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + // Finds the last real instruction, i.e. the instruction targeted by + // this annotation. + AbstractInsnNode insn = instructions.getLast(); + while (insn.getOpcode() == -1) { + insn = insn.getPrevious(); + } + // Adds the annotation to this instruction. + TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); + if (visible) { + if (insn.visibleTypeAnnotations == null) { + insn.visibleTypeAnnotations = new ArrayList( + 1); + } + insn.visibleTypeAnnotations.add(an); + } else { + if (insn.invisibleTypeAnnotations == null) { + insn.invisibleTypeAnnotations = new ArrayList( + 1); + } + insn.invisibleTypeAnnotations.add(an); + } + return an; + } + + @Override + 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 AnnotationVisitor visitTryCatchAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8); + TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); + if (visible) { + if (tcb.visibleTypeAnnotations == null) { + tcb.visibleTypeAnnotations = new ArrayList( + 1); + } + tcb.visibleTypeAnnotations.add(an); + } else { + if (tcb.invisibleTypeAnnotations == null) { + tcb.invisibleTypeAnnotations = new ArrayList( + 1); + } + tcb.invisibleTypeAnnotations.add(an); + } + return an; + } + + @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)); } @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 AnnotationVisitor visitLocalVariableAnnotation(int typeRef, + TypePath typePath, Label[] start, Label[] end, int[] index, + String desc, boolean visible) { + LocalVariableAnnotationNode an = new LocalVariableAnnotationNode( + typeRef, typePath, getLabelNodes(start), getLabelNodes(end), + index, desc); + if (visible) { + if (visibleLocalVariableAnnotations == null) { + visibleLocalVariableAnnotations = new ArrayList( + 1); + } + visibleLocalVariableAnnotations.add(an); + } else { + if (invisibleLocalVariableAnnotations == null) { + invisibleLocalVariableAnnotations = new ArrayList( + 1); + } + invisibleLocalVariableAnnotations.add(an); + } + return an; } @Override @@ -529,12 +619,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; } @@ -569,24 +660,65 @@ 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} or + * {@link Opcodes#ASM5}. */ public void check(final int api) { - // nothing to do + if (api == Opcodes.ASM4) { + if (visibleTypeAnnotations != null + && visibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + if (invisibleTypeAnnotations != null + && invisibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size(); + for (int i = 0; i < n; ++i) { + TryCatchBlockNode tcb = tryCatchBlocks.get(i); + if (tcb.visibleTypeAnnotations != null + && tcb.visibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + if (tcb.invisibleTypeAnnotations != null + && tcb.invisibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + } + for (int i = 0; i < instructions.size(); ++i) { + AbstractInsnNode insn = instructions.get(i); + if (insn.visibleTypeAnnotations != null + && insn.visibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + if (insn.invisibleTypeAnnotations != null + && insn.invisibleTypeAnnotations.size() > 0) { + throw new RuntimeException(); + } + } + if (visibleLocalVariableAnnotations != null + && visibleLocalVariableAnnotations.size() > 0) { + throw new RuntimeException(); + } + if (invisibleLocalVariableAnnotations != null + && invisibleLocalVariableAnnotations.size() > 0) { + throw new RuntimeException(); + } + + } } /** * 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); @@ -596,11 +728,18 @@ 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 + // visits the method parameters int i, j, n; + n = parameters == null ? 0 : parameters.size(); + for (i = 0; i < n; i++) { + ParameterNode parameter = parameters.get(i); + mv.visitParameter(parameter.name, parameter.access); + } + // visits the method attributes if (annotationDefault != null) { AnnotationVisitor av = mv.visitAnnotationDefault(); AnnotationNode.accept(av, null, annotationDefault); @@ -618,8 +757,20 @@ public class MethodNode extends MethodVisitor { AnnotationNode an = invisibleAnnotations.get(i); an.accept(mv.visitAnnotation(an.desc, false)); } - n = visibleParameterAnnotations == null - ? 0 + n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); + for (i = 0; i < n; ++i) { + TypeAnnotationNode an = visibleTypeAnnotations.get(i); + an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, + true)); + } + n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations + .size(); + for (i = 0; i < n; ++i) { + TypeAnnotationNode an = invisibleTypeAnnotations.get(i); + an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, + false)); + } + n = visibleParameterAnnotations == null ? 0 : visibleParameterAnnotations.length; for (i = 0; i < n; ++i) { List l = visibleParameterAnnotations[i]; @@ -631,8 +782,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]; @@ -657,6 +807,7 @@ public class MethodNode extends MethodVisitor { // visits try catch blocks n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size(); for (i = 0; i < n; ++i) { + tryCatchBlocks.get(i).updateIndex(i); tryCatchBlocks.get(i).accept(mv); } // visits instructions @@ -666,6 +817,17 @@ public class MethodNode extends MethodVisitor { for (i = 0; i < n; ++i) { localVariables.get(i).accept(mv); } + // visits local variable annotations + n = visibleLocalVariableAnnotations == null ? 0 + : visibleLocalVariableAnnotations.size(); + for (i = 0; i < n; ++i) { + visibleLocalVariableAnnotations.get(i).accept(mv, true); + } + n = invisibleLocalVariableAnnotations == null ? 0 + : invisibleLocalVariableAnnotations.size(); + for (i = 0; i < n; ++i) { + invisibleLocalVariableAnnotations.get(i).accept(mv, false); + } // visits maxs mv.visitMaxs(maxStack, maxLocals); visited = true; diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java index 70e562517d2f99afde9d14b96c4e314107919075..2f969896648830dd5592e78b736e39717b003c87 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java @@ -83,8 +83,10 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode { /** * Constructs a new {@link MultiANewArrayInsnNode}. * - * @param desc an array type descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). - * @param dims number of dimensions of the array to allocate. + * @param desc + * an array type descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). + * @param dims + * number of dimensions of the array to allocate. */ public MultiANewArrayInsnNode(final String desc, final int dims) { super(Opcodes.MULTIANEWARRAY); @@ -100,11 +102,12 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode { @Override public void accept(final MethodVisitor mv) { mv.visitMultiANewArrayInsn(desc, dims); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new MultiANewArrayInsnNode(desc, dims); + return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/ParameterNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/ParameterNode.java new file mode 100644 index 0000000000000000000000000000000000000000..74873424ca4b06669a6b52940160f843bde910aa --- /dev/null +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/ParameterNode.java @@ -0,0 +1,105 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * 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 jdk.internal.org.objectweb.asm.tree; + +import jdk.internal.org.objectweb.asm.MethodVisitor; + +/** + * A node that represents a parameter access and name. + * + * @author Remi Forax + */ +public class ParameterNode { + /** + * The parameter's name. + */ + public String name; + + /** + * The parameter's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). + * Valid values are ACC_FINAL, ACC_SYNTHETIC and + * ACC_MANDATED. + */ + public int access; + + /** + * Constructs a new {@link ParameterNode}. + * + * @param access + * The parameter's access flags. Valid values are + * ACC_FINAL, ACC_SYNTHETIC or/and + * ACC_MANDATED (see {@link jdk.internal.org.objectweb.asm.Opcodes}). + * @param name + * the parameter's name. + */ + public ParameterNode(final String name, final int access) { + this.name = name; + this.access = access; + } + + /** + * Makes the given visitor visit this parameter declaration. + * + * @param mv + * a method visitor. + */ + public void accept(final MethodVisitor mv) { + mv.visitParameter(name, access); + } +} diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java index d1b80a8811542751495366cb623a54c0d9329a10..89e219c71bdf173866f23daea6fb000d27fa9c1f 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java @@ -98,18 +98,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. labels[i] is - * the beginning of the handler block for the min + i 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. labels[i] is the + * beginning of the handler block for the min + i 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; @@ -132,13 +132,12 @@ public class TableSwitchInsnNode extends AbstractInsnNode { labels[i] = this.labels.get(i).getLabel(); } mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map 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)).cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java index 6d996112cb1b2941ab7b76b831da5322dcae6993..88457569de2c06de1d93749d52845d4f6d631e98 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java @@ -58,6 +58,8 @@ */ package jdk.internal.org.objectweb.asm.tree; +import java.util.List; + import jdk.internal.org.objectweb.asm.MethodVisitor; /** @@ -88,36 +90,93 @@ public class TryCatchBlockNode { */ public String type; + /** + * The runtime visible type annotations on the exception handler type. This + * list is a list of {@link TypeAnnotationNode} objects. May be + * null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List visibleTypeAnnotations; + + /** + * The runtime invisible type annotations on the exception handler type. + * This list is a list of {@link TypeAnnotationNode} objects. May be + * null. + * + * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List invisibleTypeAnnotations; + /** * 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 null 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 null 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; this.type = type; } + /** + * Updates the index of this try catch block in the method's list of try + * catch block nodes. This index maybe stored in the 'target' field of the + * type annotations of this block. + * + * @param index + * the new index of this try catch block in the method's list of + * try catch block nodes. + */ + public void updateIndex(final int index) { + int newTypeRef = 0x42000000 | (index << 8); + if (visibleTypeAnnotations != null) { + for (TypeAnnotationNode tan : visibleTypeAnnotations) { + tan.typeRef = newTypeRef; + } + } + if (invisibleTypeAnnotations != null) { + for (TypeAnnotationNode tan : invisibleTypeAnnotations) { + tan.typeRef = newTypeRef; + } + } + } + /** * 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); + int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations + .size(); + for (int i = 0; i < n; ++i) { + TypeAnnotationNode an = visibleTypeAnnotations.get(i); + an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath, + an.desc, true)); + } + n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations + .size(); + for (int i = 0; i < n; ++i) { + TypeAnnotationNode an = invisibleTypeAnnotations.get(i); + an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath, + an.desc, false)); + } } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java new file mode 100644 index 0000000000000000000000000000000000000000..c9e21d8c5bebc5fa01a12335e357589f681fb13f --- /dev/null +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java @@ -0,0 +1,124 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * 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 jdk.internal.org.objectweb.asm.tree; + +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; +import jdk.internal.org.objectweb.asm.TypeReference; + +/** + * A node that represents a type annotationn. + * + * @author Eric Bruneton + */ +public class TypeAnnotationNode extends AnnotationNode { + + /** + * A reference to the annotated type. See {@link TypeReference}. + */ + public int typeRef; + + /** + * The path to the annotated type argument, wildcard bound, array element + * type, or static outer type within the referenced type. May be + * null if the annotation targets 'typeRef' as a whole. + */ + public TypePath typePath; + + /** + * Constructs a new {@link AnnotationNode}. Subclasses must not use this + * constructor. Instead, they must use the + * {@link #TypeAnnotationNode(int, int, TypePath, String)} version. + * + * @param typeRef + * a reference to the annotated type. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + */ + public TypeAnnotationNode(final int typeRef, final TypePath typePath, + final String desc) { + this(Opcodes.ASM5, typeRef, typePath, desc); + } + + /** + * Constructs a new {@link AnnotationNode}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param typeRef + * a reference to the annotated type. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + */ + public TypeAnnotationNode(final int api, final int typeRef, + final TypePath typePath, final String desc) { + super(api, desc); + this.typeRef = typeRef; + this.typePath = typePath; + } +} diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java index 7eb13b4e643aade351279e78cc97796f727a24c4..5bda1167fc62701d5eeced5addba591f381adf60 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java @@ -79,10 +79,12 @@ public class TypeInsnNode extends AbstractInsnNode { /** * 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 jdk.internal.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 jdk.internal.org.objectweb.asm.Type}). */ public TypeInsnNode(final int opcode, final String desc) { super(opcode); @@ -92,8 +94,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; @@ -107,10 +110,11 @@ public class TypeInsnNode extends AbstractInsnNode { @Override public void accept(final MethodVisitor mv) { mv.visitTypeInsn(opcode, desc); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new TypeInsnNode(opcode, desc); + return new TypeInsnNode(opcode, desc).cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java index eaa24883ea0087232896aa7f7b6371245a809d40..2ec81987957bf2ffc10af391075f4b286f5f7514 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java @@ -80,11 +80,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); @@ -94,9 +96,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; @@ -110,10 +113,11 @@ public class VarInsnNode extends AbstractInsnNode { @Override public void accept(final MethodVisitor mv) { mv.visitVarInsn(opcode, var); + acceptAnnotations(mv); } @Override public AbstractInsnNode clone(final Map labels) { - return new VarInsnNode(opcode, var); + return new VarInsnNode(opcode, var).cloneAnnotations(this); } } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java index ff95c4dd048f0885923c8d34071b5c046299dbbf..8f987532efdfb00d92a2472b458041e82c992473 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java @@ -30,7 +30,6 @@ * * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom - * Copyright (c) 2011 Google * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -81,9 +80,10 @@ import jdk.internal.org.objectweb.asm.tree.VarInsnNode; * A semantic bytecode analyzer. This class does not fully check that JSR and * RET instructions are valid. * - * @param type of the Value used for the analysis. + * @param + * type of the Value used for the analysis. * - * @author Eric Bruneton + * @author Eric Bruneton */ public class Analyzer implements Opcodes { @@ -108,8 +108,9 @@ public class Analyzer 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 interpreter) { this.interpreter = interpreter; @@ -118,26 +119,28 @@ public class Analyzer 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 null 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[] analyze(final String owner, final MethodNode m) - throws AnalyzerException - { + throws AnalyzerException { if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) { - frames = (Frame[])new Frame[0]; + frames = (Frame[]) new Frame[0]; return frames; } n = m.instructions.size(); insns = m.instructions; - handlers = (List[])new List[n]; - frames = (Frame[])new Frame[n]; + handlers = (List[]) new List[n]; + frames = (Frame[]) new Frame[n]; subroutines = new Subroutine[n]; queued = new boolean[n]; queue = new int[n]; @@ -218,8 +221,7 @@ public class Analyzer 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 { @@ -235,8 +237,7 @@ public class Analyzer 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); } @@ -265,31 +266,27 @@ public class Analyzer 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) { @@ -322,23 +319,23 @@ public class Analyzer 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 calls) - throws AnalyzerException - { + private void findSubroutine(int insn, final Subroutine sub, + final List 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; @@ -382,18 +379,18 @@ public class Analyzer 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++; } @@ -417,8 +414,9 @@ public class Analyzer 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 getHandlers(final int insn) { @@ -430,9 +428,12 @@ public class Analyzer 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 { } @@ -440,8 +441,10 @@ public class Analyzer 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 newFrame(final int nLocals, final int nStack) { @@ -451,7 +454,8 @@ public class Analyzer 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 newFrame(final Frame src) { @@ -464,8 +468,10 @@ public class Analyzer 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) { } @@ -477,16 +483,16 @@ public class Analyzer 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; } @@ -499,28 +505,25 @@ public class Analyzer 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 frame, - final Subroutine subroutine) throws AnalyzerException - { + private void merge(final int insn, final Frame frame, + final Subroutine subroutine) throws AnalyzerException { Frame oldFrame = frames[insn]; Subroutine oldSubroutine = subroutines[insn]; boolean changes; @@ -548,13 +551,9 @@ public class Analyzer implements Opcodes { } } - private void merge( - final int insn, - final Frame beforeJSR, - final Frame afterRET, - final Subroutine subroutineBeforeJSR, - final boolean[] access) throws AnalyzerException - { + private void merge(final int insn, final Frame beforeJSR, + final Frame afterRET, final Subroutine subroutineBeforeJSR, + final boolean[] access) throws AnalyzerException { Frame oldFrame = frames[insn]; Subroutine oldSubroutine = subroutines[insn]; boolean changes; diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java index a18f5d3a908dbce559ea27fc8c2e5ab6783e5cc6..c3678c8914b0e40e906f26f054a8bcfe36387301 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java @@ -75,17 +75,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/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java index 7df82f609d476dd491fbbbb679f27f214153ef7b..e450166ba6592824b77e39422cbde72cef4ebdcb 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java @@ -79,11 +79,10 @@ import jdk.internal.org.objectweb.asm.tree.TypeInsnNode; * @author Bing Ran */ public class BasicInterpreter extends Interpreter implements - Opcodes -{ + Opcodes { public BasicInterpreter() { - super(ASM4); + super(ASM5); } protected BasicInterpreter(final int api) { @@ -96,292 +95,286 @@ public class BasicInterpreter extends Interpreter 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 values) - throws AnalyzerException - { + public BasicValue naryOperation(final AbstractInsnNode insn, + final List 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/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java index b92fd3d5787edb0297bb45b987a00f43b62b1235..ef519228fa957da3d50bb290394379521c15ef7f 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java @@ -77,11 +77,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/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java index 8b51b4ae0d6b5814b5e8bc2a0f689f281e833524..2ccf67d4cb474eb502f053c7569eb14e4e63030a 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java @@ -76,7 +76,7 @@ import jdk.internal.org.objectweb.asm.tree.MethodInsnNode; public class BasicVerifier extends BasicInterpreter { public BasicVerifier() { - super(ASM4); + super(ASM5); } protected BasicVerifier(final int api) { @@ -84,47 +84,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); @@ -133,91 +127,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); @@ -226,125 +214,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); @@ -354,79 +342,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 values) - throws AnalyzerException - { + public BasicValue naryOperation(final AbstractInsnNode insn, + final List 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 { @@ -436,22 +418,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); } } } @@ -459,16 +437,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); } } @@ -477,12 +451,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/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java index b25d4d8b88de3618964440d79a504966c3f77a2b..2d9434fc22e24ed52629618de23ce1746bb40c06 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java @@ -73,10 +73,11 @@ import jdk.internal.org.objectweb.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 two slots in local variables, and by one slot - * in the operand stack. + * represented by two slots in local variables, and by one slot in + * the operand stack. * - * @param type of the Value used for the analysis. + * @param + * type of the Value used for the analysis. * * @author Eric Bruneton */ @@ -106,8 +107,10 @@ public class Frame { /** * 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]; @@ -117,7 +120,8 @@ public class Frame { /** * Constructs a new frame that is identical to the given frame. * - * @param src a frame. + * @param src + * a frame. */ public Frame(final Frame src) { this(src.locals, src.values.length - src.locals); @@ -127,7 +131,8 @@ public class Frame { /** * Copies the state of the given frame into this frame. * - * @param src a frame. + * @param src + * a frame. * @return this frame. */ public Frame init(final Frame src) { @@ -140,8 +145,9 @@ public class Frame { /** * Sets the expected return type of the analyzed method. * - * @param v the expected return type of the analyzed method, or - * null if the method returns void. + * @param v + * the expected return type of the analyzed method, or + * null if the method returns void. */ public void setReturn(final V v) { returnValue = v; @@ -159,13 +165,16 @@ public class Frame { /** * 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]; } @@ -173,15 +182,18 @@ public class Frame { /** * 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; } @@ -199,10 +211,11 @@ public class Frame { /** * 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]; @@ -219,11 +232,13 @@ public class Frame { * 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]; } @@ -231,468 +246,471 @@ public class Frame { /** * 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 interpreter) throws AnalyzerException - { + public void execute(final AbstractInsnNode insn, + final Interpreter interpreter) throws AnalyzerException { V value1, value2, value3, value4; List 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(); - 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(); - 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(); - 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(); + 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(); + 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(); + 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 true if this frame has been changed as a result of the * merge operation, or false otherwise. - * @throws AnalyzerException if the frames have incompatible sizes. + * @throws AnalyzerException + * if the frames have incompatible sizes. */ - public boolean merge(final Frame frame, final Interpreter interpreter) - throws AnalyzerException - { + public boolean merge(final Frame frame, + final Interpreter 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; + changes = true; } } return changes; @@ -701,9 +719,11 @@ public class Frame { /** * 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 true if this frame has been changed as a result of the * merge operation, or false otherwise. */ diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java index fd8735f925e9a9bcbb202ed2eb73962d9fa8d92a..649d5a4c5d8a2fdef89c966ecc78d215e1b5038f 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java @@ -71,7 +71,8 @@ import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode; * various semantic interpreters, without needing to duplicate the code to * simulate the transfer of values. * - * @param type of the Value used for the analysis. + * @param + * type of the Value used for the analysis. * * @author Eric Bruneton */ @@ -86,12 +87,13 @@ public abstract class Interpreter { /** * Creates a new value that represents the given type. * - * Called for method parameters (including this), - * exception handler variable and with null type - * for variables reserved by long and double types. + * Called for method parameters (including this), exception + * handler variable and with null type for variables reserved + * by long and double types. * - * @param type a primitive or reference type, or null to - * represent an uninitialized value. + * @param type + * a primitive or reference type, or null 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. */ @@ -105,9 +107,11 @@ public abstract class Interpreter { * 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; @@ -119,11 +123,14 @@ public abstract class Interpreter { * 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 equal 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; @@ -138,10 +145,13 @@ public abstract class Interpreter { * 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; @@ -157,11 +167,15 @@ public abstract class Interpreter { * 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; @@ -172,18 +186,20 @@ public abstract class Interpreter { * * 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. @@ -192,14 +208,16 @@ public abstract class Interpreter { * 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 values) throws AnalyzerException; /** * Interprets a bytecode return instruction. This method is called for the @@ -207,15 +225,17 @@ public abstract class Interpreter { * * 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 @@ -224,8 +244,10 @@ public abstract class Interpreter { * 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 v, * this method must return v. */ diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java index 29275c715c87fe6ef1516521a531169c847726f4..a93c5f2a1215db6ed504a2b4e3ae22815cc84718 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java @@ -108,15 +108,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); } @@ -124,32 +124,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 currentClassInterfaces, - final boolean isInterface) - { - this(ASM4, - currentClass, - currentSuperClass, - currentClassInterfaces, + public SimpleVerifier(final Type currentClass, + final Type currentSuperClass, + final List currentClassInterfaces, final boolean isInterface) { + this(ASM5, currentClass, currentSuperClass, currentClassInterfaces, isInterface); } - protected SimpleVerifier( - final int api, - final Type currentClass, - final Type currentSuperClass, - final List currentClassInterfaces, - final boolean isInterface) - { + protected SimpleVerifier(final int api, final Type currentClass, + final Type currentSuperClass, + final List currentClassInterfaces, final boolean isInterface) { super(api); this.currentClass = currentClass; this.currentSuperClass = currentSuperClass; @@ -162,7 +155,8 @@ public class SimpleVerifier extends BasicVerifier { * classes. This is useful if you are verifying multiple interdependent * classes. * - * @param loader a ClassLoader to use + * @param loader + * a ClassLoader to use */ public void setClassLoader(final ClassLoader loader) { this.loader = loader; @@ -177,11 +171,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); } } @@ -210,8 +204,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) { @@ -225,28 +218,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"); } } @@ -256,11 +249,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; } @@ -317,7 +308,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)); } @@ -347,8 +339,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/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java index 131f656313babd26f2341d77960d1c5cd12e0d6b..e37cecc9ec6e5d3cda49283e642ee50f2565d422 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java @@ -76,11 +76,10 @@ import jdk.internal.org.objectweb.asm.tree.MethodInsnNode; * @author Eric Bruneton */ public class SourceInterpreter extends Interpreter implements - Opcodes -{ + Opcodes { public SourceInterpreter() { - super(ASM4); + super(ASM5); } protected SourceInterpreter(final int api) { @@ -99,125 +98,118 @@ public class SourceInterpreter extends Interpreter 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 values) { + public SourceValue naryOperation(final AbstractInsnNode insn, + final List 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 s = ((SmallSet) d.insns).union((SmallSet) w.insns); + Set s = ((SmallSet) d.insns) + .union((SmallSet) w.insns); if (s == d.insns && d.size == w.size) { return d; } else { diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java index 344a329d0bea486f899e1dc304f768cbb79f8566..bb0e891ac703cb746e1145f6aa1c229bf398a57b 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java @@ -77,8 +77,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 i - * at line 5 are the txo ISTORE instructions at line 1 and 3: + * code below, the instructions that can produce the value of i at + * line 5 are the txo ISTORE instructions at line 1 and 3: * *
              * 1: i = 0;
        @@ -93,7 +93,7 @@ public class SourceValue implements Value {
             public final Set insns;
         
             public SourceValue(final int size) {
        -        this(size, SmallSet.emptySet());
        +        this(size, SmallSet. emptySet());
             }
         
             public SourceValue(final int size, final AbstractInsnNode insn) {
        diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java
        index 670e2327a6d1c94d6428ee338088cc0e9763a318..1bf517feac364c90d604703d0c72a3876844d9cc 100644
        --- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java
        +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java
        @@ -80,11 +80,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();
        diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java
        index 86f7a617342e2e4f367aa42d83559ce58f9c31fa..b7fbb89948cf8e97a86b76f3a5c70f730b679428 100644
        --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java
        +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java
        @@ -22,7 +22,7 @@
          * questions.
          */
         
        -/*
        +/**
          * This file is available under and governed by the GNU General Public
          * License version 2 only, as published by the Free Software Foundation.
          * However, the following notice accompanied the original version of this
        @@ -73,10 +73,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 labelNames);
         }
        diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java
        index 86cbedd8590d7942d5f65eaa32c3851a3c5defea..6b6bd4dc6bb5b3a4715169cf4940d1f372d707b3 100644
        --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java
        +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java
        @@ -30,7 +30,6 @@
          *
          * ASM: a very small and fast Java bytecode manipulation framework
          * Copyright (c) 2000-2011 INRIA, France Telecom
        - * Copyright (c) 2011 Google
          * All rights reserved.
          *
          * Redistribution and use in source and binary forms, with or without
        @@ -70,6 +69,7 @@ import jdk.internal.org.objectweb.asm.Handle;
         import jdk.internal.org.objectweb.asm.Label;
         import jdk.internal.org.objectweb.asm.Opcodes;
         import jdk.internal.org.objectweb.asm.Type;
        +import jdk.internal.org.objectweb.asm.TypePath;
         
         /**
          * A {@link Printer} that prints the ASM code to generate the classes if visits.
        @@ -115,17 +115,20 @@ public class ASMifier extends Printer {
              * {@link #ASMifier(int, String, int)} version.
              */
             public ASMifier() {
        -        this(Opcodes.ASM4, "cw", 0);
        +        this(Opcodes.ASM5, "cw", 0);
             }
         
             /**
              * 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} or {@link Opcodes#ASM5}.
        +     * @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);
        @@ -135,13 +138,15 @@ public class ASMifier extends Printer {
         
             /**
              * Prints the ASM source code to generate the given class to the standard
        -     * output. 

        Usage: ASMifier [-debug] <binary - * class name or class file name> + * output. + *

        + * 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; @@ -159,22 +164,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] " + ""); 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); } // ------------------------------------------------------------------------ @@ -182,14 +186,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) { @@ -212,30 +211,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); @@ -272,11 +271,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); @@ -289,25 +285,25 @@ 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); } + @Override + public ASMifier visitClassTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + return visitTypeAnnotation(typeRef, typePath, desc, visible); + } + @Override public void visitClassAttribute(final Attribute attr) { visitAttribute(attr); } @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); @@ -322,13 +318,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("); @@ -350,13 +341,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("); @@ -410,11 +396,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); @@ -427,10 +410,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"); @@ -473,13 +453,17 @@ 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); } + @Override + public ASMifier visitFieldTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + return visitTypeAnnotation(typeRef, typePath, desc, visible); + } + @Override public void visitFieldAttribute(final Attribute attr) { visitAttribute(attr); @@ -496,12 +480,19 @@ public class ASMifier extends Printer { // Methods // ------------------------------------------------------------------------ + @Override + public void visitParameter(String parameterName, int access) { + buf.setLength(0); + buf.append(name).append(".visitParameter(").append(parameterName) + .append(", "); + appendAccess(access); + text.add(buf.append(");\n").toString()); + } + @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); @@ -511,23 +502,23 @@ 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 visitMethodTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + return visitTypeAnnotation(typeRef, typePath, desc, visible); + } + + @Override + 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"); @@ -549,52 +540,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()); @@ -603,7 +589,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()); } @@ -614,43 +601,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); @@ -661,14 +640,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); @@ -679,12 +655,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); @@ -707,7 +679,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()); @@ -735,34 +708,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) { @@ -774,11 +735,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]); @@ -810,12 +768,15 @@ public class ASMifier extends Printer { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public ASMifier visitInsnAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath, + desc, visible); + } + + @Override + public void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type) { buf.setLength(0); declareLabel(start); declareLabel(end); @@ -833,14 +794,16 @@ 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 ASMifier visitTryCatchAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + return visitTypeAnnotation("visitTryCatchAnnotation", typeRef, + typePath, desc, visible); + } + + @Override + 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); @@ -856,6 +819,39 @@ public class ASMifier extends Printer { text.add(buf.toString()); } + @Override + public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath, + Label[] start, Label[] end, int[] index, String desc, + boolean visible) { + buf.setLength(0); + buf.append("{\n").append("av0 = ").append(name) + .append(".visitLocalVariableAnnotation("); + buf.append(typeRef); + buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); + buf.append("new Label[] {"); + for (int i = 0; i < start.length; ++i) { + buf.append(i == 0 ? " " : ", "); + appendLabel(start[i]); + } + buf.append(" }, new Label[] {"); + for (int i = 0; i < end.length; ++i) { + buf.append(i == 0 ? " " : ", "); + appendLabel(end[i]); + } + buf.append(" }, new int[] {"); + for (int i = 0; i < index.length; ++i) { + buf.append(i == 0 ? " " : ", ").append(index[i]); + } + buf.append(" }, "); + appendConstant(desc); + buf.append(", ").append(visible).append(");\n"); + text.add(buf.toString()); + ASMifier a = createASMifier("av", 0); + text.add(a.getText()); + text.add("}\n"); + return a; + } + @Override public void visitLineNumber(final int line, final Label start) { buf.setLength(0); @@ -868,12 +864,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()); } @@ -888,14 +880,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"); @@ -906,6 +893,28 @@ public class ASMifier extends Printer { return a; } + public ASMifier visitTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + return visitTypeAnnotation("visitTypeAnnotation", typeRef, typePath, + desc, visible); + } + + public ASMifier visitTypeAnnotation(final String method, final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + buf.setLength(0); + buf.append("{\n").append("av0 = ").append(name).append(".") + .append(method).append("("); + buf.append(typeRef); + buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); + appendConstant(desc); + buf.append(", ").append(visible).append(");\n"); + text.add(buf.toString()); + ASMifier a = createASMifier("av", 0); + text.add(a.getText()); + text.add("}\n"); + return a; + } + public void visitAttribute(final Attribute attr) { buf.setLength(0); buf.append("// ATTRIBUTE ").append(attr.type).append('\n'); @@ -925,15 +934,16 @@ public class ASMifier extends Printer { // Utility methods // ------------------------------------------------------------------------ - protected ASMifier createASMifier(final String name, final int id) { - return new ASMifier(Opcodes.ASM4, name, id); + protected ASMifier createASMifier(final String name, final int id) { + return new ASMifier(Opcodes.ASM5, 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; @@ -975,8 +985,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(" + "); } @@ -984,8 +993,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(" + "); } @@ -993,8 +1001,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(" + "); } @@ -1002,8 +1009,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(" + "); } @@ -1011,8 +1017,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(" + "); } @@ -1021,8 +1026,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(" + "); } @@ -1030,8 +1034,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(" + "); } @@ -1082,8 +1085,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 null. + * @param cst + * an {@link Integer}, {@link Float}, {@link Long}, + * {@link Double} or {@link String} object. May be null. */ protected void appendConstant(final Object cst) { appendConstant(buf, cst); @@ -1093,9 +1097,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 null. + * @param buf + * a string buffer. + * @param cst + * an {@link Integer}, {@link Float}, {@link Long}, + * {@link Double} or {@link String} object. May be null. */ static void appendConstant(final StringBuffer buf, final Object cst) { if (cst == null) { @@ -1109,14 +1115,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) { @@ -1155,8 +1163,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('}'); @@ -1208,27 +1215,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]); @@ -1241,7 +1248,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) { @@ -1257,10 +1265,11 @@ public class ASMifier extends Printer { /** * Appends the name of the given label to {@link #buf buf}. The given label - * must already have a name. One way to ensure this is to always - * call {@link #declareLabel declared} before calling this method. + * must 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/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java index eacb35d3c677361819e2dcebe868c53b8ab449f3..3650e37db39513bc4cfbae265c3ac2ebe8c7f12e 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java @@ -78,7 +78,7 @@ public class CheckAnnotationAdapter extends AnnotationVisitor { } CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) { - super(Opcodes.ASM4, av); + super(Opcodes.ASM5, av); this.named = named; } @@ -94,8 +94,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) { @@ -110,11 +109,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); @@ -127,15 +123,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)); } @@ -143,8 +136,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); } @@ -159,13 +151,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/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java index 59fb514c387aa8ab98c146b76e2876c8651a5a83..ad29ab964a74b156c92445a9336987323d4c193c 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java @@ -75,6 +75,8 @@ import jdk.internal.org.objectweb.asm.Label; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; +import jdk.internal.org.objectweb.asm.TypePath; +import jdk.internal.org.objectweb.asm.TypeReference; import jdk.internal.org.objectweb.asm.tree.ClassNode; import jdk.internal.org.objectweb.asm.tree.MethodNode; import jdk.internal.org.objectweb.asm.tree.analysis.Analyzer; @@ -88,10 +90,10 @@ import jdk.internal.org.objectweb.asm.tree.analysis.SimpleVerifier; * only on its arguments, but does not check the sequence * of method calls. For example, the invalid sequence * visitField(ACC_PUBLIC, "i", "I", null) visitField(ACC_PUBLIC, - * "i", "D", null) - * will not be detected by this class adapter. + * "i", "D", null) will not be detected by this class adapter. * - *

        CheckClassAdapter can be also used to verify bytecode + *

        + * CheckClassAdapter can be also used to verify bytecode * transformations in order to make sure transformed bytecode is sane. For * example: * @@ -109,11 +111,12 @@ import jdk.internal.org.objectweb.asm.tree.analysis.SimpleVerifier; *

        * * Above code runs transformed bytecode trough the - * CheckClassAdapter. It won't be exactly the same verification - * as JVM does, but it run data flow analysis for the code of each method and + * CheckClassAdapter. 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. * - *

        If method bytecode has errors, assertion text will show the erroneous + *

        + * 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): @@ -134,7 +137,7 @@ import jdk.internal.org.objectweb.asm.tree.analysis.SimpleVerifier; * 00071 LinkedBlockingQueue$Itr . I . . . . . . : * ILOAD 1 * 00072 ? - * INVOKESPECIAL java/lang/Integer. (I)V + * INVOKESPECIAL java/lang/Integer.<init> (I)V * ... * * @@ -143,8 +146,9 @@ import jdk.internal.org.objectweb.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. * - *

        Note that when used like that, CheckClassAdapter.verify() - * can trigger additional class loading, because it is using + *

        + * Note that when used like that, CheckClassAdapter.verify() can + * trigger additional class loading, because it is using * SimpleVerifier. * * @author Eric Bruneton @@ -188,13 +192,15 @@ public class CheckClassAdapter extends ClassVisitor { private boolean checkDataFlow; /** - * Checks a given class.

        Usage: CheckClassAdapter <binary - * class name or class file name> + * Checks a given class. + *

        + * 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) { @@ -216,27 +222,26 @@ public class CheckClassAdapter extends ClassVisitor { /** * Checks a given class. * - * @param cr a ClassReader that contains bytecode for the - * analysis. - * @param loader a ClassLoader 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 ClassReader that contains bytecode for the + * analysis. + * @param loader + * a ClassLoader 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 methods = cn.methods; List interfaces = new ArrayList(); @@ -246,9 +251,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 a = new Analyzer(verifier); if (loader != null) { @@ -270,25 +274,22 @@ public class CheckClassAdapter extends ClassVisitor { /** * Checks a given class * - * @param cr a ClassReader 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 ClassReader 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 a, - final PrintWriter pw) - { + static void printAnalyzerResult(MethodNode method, Analyzer a, + final PrintWriter pw) { Frame[] frames = a.getFrames(); Textifier t = new Textifier(); TraceMethodVisitor mv = new TraceMethodVisitor(t); @@ -339,7 +340,8 @@ public class CheckClassAdapter extends ClassVisitor { * this constructor. 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); @@ -350,33 +352,34 @@ public class CheckClassAdapter extends ClassVisitor { * this constructor. 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 true to perform basic data flow checks, or - * false 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 + * true to perform basic data flow checks, or + * false 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) - { - this(Opcodes.ASM4, cv, checkDataFlow); + public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) { + this(Opcodes.ASM5, 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 true to perform basic data flow checks, or - * false 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} or {@link Opcodes#ASM5}. + * @param cv + * the class visitor to which this adapter must delegate calls. + * @param checkDataFlow + * true to perform basic data flow checks, or + * false 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(); this.checkDataFlow = checkDataFlow; @@ -387,14 +390,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"); } @@ -404,24 +402,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) { @@ -438,21 +437,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) { @@ -465,12 +463,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) { @@ -488,52 +482,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 (!"".equals(name) && !"".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) { @@ -543,37 +529,47 @@ 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)); } + @Override + public AnnotationVisitor visitTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + checkState(); + int sort = typeRef >>> 24; + if (sort != TypeReference.CLASS_TYPE_PARAMETER + && sort != TypeReference.CLASS_TYPE_PARAMETER_BOUND + && sort != TypeReference.CLASS_EXTENDS) { + throw new IllegalArgumentException("Invalid type reference sort 0x" + + Integer.toHexString(sort)); + } + checkTypeRefAndPath(typeRef, typePath); + CheckMethodAdapter.checkDesc(desc, false); + return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef, + typePath, desc, visible)); + } + @Override 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); } @@ -595,10 +591,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."); } } @@ -607,8 +605,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) { @@ -619,14 +619,407 @@ 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 reference to a type in a type annotation. + * + * @param typeRef + * a reference to an annotated type. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + */ + static void checkTypeRefAndPath(int typeRef, TypePath typePath) { + int mask = 0; + switch (typeRef >>> 24) { + case TypeReference.CLASS_TYPE_PARAMETER: + case TypeReference.METHOD_TYPE_PARAMETER: + case TypeReference.METHOD_FORMAL_PARAMETER: + mask = 0xFFFF0000; + break; + case TypeReference.FIELD: + case TypeReference.METHOD_RETURN: + case TypeReference.METHOD_RECEIVER: + case TypeReference.LOCAL_VARIABLE: + case TypeReference.RESOURCE_VARIABLE: + case TypeReference.INSTANCEOF: + case TypeReference.NEW: + case TypeReference.CONSTRUCTOR_REFERENCE: + case TypeReference.METHOD_REFERENCE: + mask = 0xFF000000; + break; + case TypeReference.CLASS_EXTENDS: + case TypeReference.CLASS_TYPE_PARAMETER_BOUND: + case TypeReference.METHOD_TYPE_PARAMETER_BOUND: + case TypeReference.THROWS: + case TypeReference.EXCEPTION_PARAMETER: + mask = 0xFFFFFF00; + break; + case TypeReference.CAST: + case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT: + case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: + case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT: + mask = 0xFF0000FF; + break; + default: + throw new IllegalArgumentException("Invalid type reference sort 0x" + + Integer.toHexString(typeRef >>> 24)); + } + if ((typeRef & ~mask) != 0) { + throw new IllegalArgumentException("Invalid type reference 0x" + + Integer.toHexString(typeRef)); + } + if (typePath != null) { + for (int i = 0; i < typePath.getLength(); ++i) { + int step = typePath.getStep(i); + if (step != TypePath.ARRAY_ELEMENT + && step != TypePath.INNER_TYPE + && step != TypePath.TYPE_ARGUMENT + && step != TypePath.WILDCARD_BOUND) { + throw new IllegalArgumentException( + "Invalid type path step " + i + " in " + typePath); + } + if (step != TypePath.TYPE_ARGUMENT + && typePath.getStepArgument(i) != 0) { + throw new IllegalArgumentException( + "Invalid type path step argument for step " + i + + " in " + typePath); + } + } + } + } + + /** + * 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/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java index 868991eee660f7afef04d634118ba42cd586db85..b09559c0d8a94b5c39df1d0920536d297efa78f0 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java @@ -62,6 +62,8 @@ import jdk.internal.org.objectweb.asm.AnnotationVisitor; import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; +import jdk.internal.org.objectweb.asm.TypeReference; /** * A {@link FieldVisitor} that checks that its methods are properly used. @@ -75,38 +77,55 @@ public class CheckFieldAdapter extends FieldVisitor { * this constructor. 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); + this(Opcodes.ASM5, fv); } /** * 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} or {@link Opcodes#ASM5}. + * @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)); } + @Override + public AnnotationVisitor visitTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + checkEnd(); + int sort = typeRef >>> 24; + if (sort != TypeReference.FIELD) { + throw new IllegalArgumentException("Invalid type reference sort 0x" + + Integer.toHexString(sort)); + } + CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath); + CheckMethodAdapter.checkDesc(desc, false); + return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef, + typePath, desc, visible)); + } + @Override 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); } @@ -120,7 +139,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/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java index 51e92627f7a756844ba19ecc58b1a1cb0144e5f0..b59709890f4011581f00c7abdfffd8e54b8089f0 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java @@ -75,6 +75,8 @@ import jdk.internal.org.objectweb.asm.Label; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; +import jdk.internal.org.objectweb.asm.TypePath; +import jdk.internal.org.objectweb.asm.TypeReference; import jdk.internal.org.objectweb.asm.tree.MethodNode; import jdk.internal.org.objectweb.asm.tree.analysis.Analyzer; import jdk.internal.org.objectweb.asm.tree.analysis.BasicValue; @@ -103,6 +105,11 @@ public class CheckMethodAdapter extends MethodVisitor { */ public int version; + /** + * The access flags of the method. + */ + private int access; + /** * true if the visitCode method has been called. */ @@ -135,6 +142,21 @@ public class CheckMethodAdapter extends MethodVisitor { */ private Set

        - * Usage: Textifier [-debug] <binary class name or class - * file name > + * Prints a disassembled view of the given class to the standard output. + *

        + * 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; @@ -211,21 +215,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] " + ""); 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); } // ------------------------------------------------------------------------ @@ -233,38 +236,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); @@ -298,15 +290,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) { @@ -315,11 +303,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); @@ -333,14 +318,19 @@ 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); } + @Override + public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath, + String desc, boolean visible) { + text.add("\n"); + return visitTypeAnnotation(typeRef, typePath, desc, visible); + } + @Override public void visitClassAttribute(final Attribute attr) { text.add("\n"); @@ -348,15 +338,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 "); @@ -370,19 +358,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); @@ -390,10 +374,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); @@ -419,19 +401,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); @@ -444,12 +422,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); } @@ -622,11 +596,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) { @@ -638,10 +609,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) { @@ -658,9 +626,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) { @@ -683,13 +649,17 @@ 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); } + @Override + public Printer visitFieldTypeAnnotation(int typeRef, TypePath typePath, + String desc, boolean visible) { + return visitTypeAnnotation(typeRef, typePath, desc, visible); + } + @Override public void visitFieldAttribute(final Attribute attr) { visitAttribute(attr); @@ -703,6 +673,16 @@ public class Textifier extends Printer { // Methods // ------------------------------------------------------------------------ + @Override + public void visitParameter(final String name, final int access) { + buf.setLength(0); + buf.append(tab2).append("// parameter "); + appendAccess(access); + buf.append(' ').append((name == null) ? "" : name) + .append('\n'); + text.add(buf.toString()); + } + @Override public Textifier visitAnnotationDefault() { text.add(tab2 + "default="); @@ -713,19 +693,20 @@ 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 Printer visitMethodTypeAnnotation(int typeRef, TypePath typePath, + String desc, boolean visible) { + return visitTypeAnnotation(typeRef, typePath, desc, visible); + } + + @Override + public Textifier visitParameterAnnotation(final int parameter, + final String desc, final boolean visible) { buf.setLength(0); buf.append(tab2).append('@'); appendDescriptor(FIELD_DESCRIPTOR, desc); @@ -759,40 +740,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()); @@ -811,20 +787,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()); } @@ -839,12 +810,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); @@ -855,12 +822,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); @@ -871,12 +834,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); @@ -884,11 +843,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); @@ -944,22 +903,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) { @@ -974,11 +925,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) { @@ -1002,12 +950,14 @@ public class Textifier extends Printer { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public Printer visitInsnAnnotation(int typeRef, TypePath typePath, + String desc, boolean visible) { + return visitTypeAnnotation(typeRef, typePath, desc, visible); + } + + @Override + 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); @@ -1022,14 +972,28 @@ 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 Printer visitTryCatchAnnotation(int typeRef, TypePath typePath, + String desc, boolean visible) { + buf.setLength(0); + buf.append(tab2).append("TRYCATCHBLOCK @"); + appendDescriptor(FIELD_DESCRIPTOR, desc); + buf.append('('); + text.add(buf.toString()); + Textifier t = createTextifier(); + text.add(t.getText()); + buf.setLength(0); + buf.append(") : "); + appendTypeReference(typeRef); + buf.append(", ").append(typePath); + buf.append(visible ? "\n" : " // invisible\n"); + text.add(buf.toString()); + return t; + } + + @Override + 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); @@ -1046,12 +1010,37 @@ 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()); + } + + @Override + public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath, + Label[] start, Label[] end, int[] index, String desc, + boolean visible) { + buf.setLength(0); + buf.append(tab2).append("LOCALVARIABLE @"); + appendDescriptor(FIELD_DESCRIPTOR, desc); + buf.append('('); + text.add(buf.toString()); + Textifier t = createTextifier(); + text.add(t.getText()); + buf.setLength(0); + buf.append(") : "); + appendTypeReference(typeRef); + buf.append(", ").append(typePath); + for (int i = 0; i < start.length; ++i) { + buf.append(" [ "); + appendLabel(start[i]); + buf.append(" - "); + appendLabel(end[i]); + buf.append(" - ").append(index[i]).append(" ]"); } + buf.append(visible ? "\n" : " // invisible\n"); text.add(buf.toString()); + return t; } @Override @@ -1085,14 +1074,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 true if the annotation is visible at runtime. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true 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); @@ -1104,10 +1092,44 @@ public class Textifier extends Printer { return t; } + /** + * Prints a disassembled view of the given type annotation. + * + * @param typeRef + * a reference to the annotated type. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values. + */ + public Textifier visitTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + buf.setLength(0); + buf.append(tab).append('@'); + appendDescriptor(FIELD_DESCRIPTOR, desc); + buf.append('('); + text.add(buf.toString()); + Textifier t = createTextifier(); + text.add(t.getText()); + buf.setLength(0); + buf.append(") : "); + appendTypeReference(typeRef); + buf.append(", ").append(typePath); + buf.append(visible ? "\n" : " // invisible\n"); + text.add(buf.toString()); + return t; + } + /** * 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); @@ -1140,15 +1162,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 - * null. + * @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 + * null. */ 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'); } @@ -1161,7 +1184,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) { @@ -1178,40 +1202,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); @@ -1224,10 +1250,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) { @@ -1260,6 +1287,12 @@ 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_MANDATED) != 0) { + buf.append("mandated "); + } if ((access & Opcodes.ACC_ENUM) != 0) { buf.append("enum "); } @@ -1271,6 +1304,90 @@ public class Textifier extends Printer { } } + private void appendTypeReference(final int typeRef) { + TypeReference ref = new TypeReference(typeRef); + switch (ref.getSort()) { + case TypeReference.CLASS_TYPE_PARAMETER: + buf.append("CLASS_TYPE_PARAMETER ").append( + ref.getTypeParameterIndex()); + break; + case TypeReference.METHOD_TYPE_PARAMETER: + buf.append("METHOD_TYPE_PARAMETER ").append( + ref.getTypeParameterIndex()); + break; + case TypeReference.CLASS_EXTENDS: + buf.append("CLASS_EXTENDS ").append(ref.getSuperTypeIndex()); + break; + case TypeReference.CLASS_TYPE_PARAMETER_BOUND: + buf.append("CLASS_TYPE_PARAMETER_BOUND ") + .append(ref.getTypeParameterIndex()).append(", ") + .append(ref.getTypeParameterBoundIndex()); + break; + case TypeReference.METHOD_TYPE_PARAMETER_BOUND: + buf.append("METHOD_TYPE_PARAMETER_BOUND ") + .append(ref.getTypeParameterIndex()).append(", ") + .append(ref.getTypeParameterBoundIndex()); + break; + case TypeReference.FIELD: + buf.append("FIELD"); + break; + case TypeReference.METHOD_RETURN: + buf.append("METHOD_RETURN"); + break; + case TypeReference.METHOD_RECEIVER: + buf.append("METHOD_RECEIVER"); + break; + case TypeReference.METHOD_FORMAL_PARAMETER: + buf.append("METHOD_FORMAL_PARAMETER ").append( + ref.getFormalParameterIndex()); + break; + case TypeReference.THROWS: + buf.append("THROWS ").append(ref.getExceptionIndex()); + break; + case TypeReference.LOCAL_VARIABLE: + buf.append("LOCAL_VARIABLE"); + break; + case TypeReference.RESOURCE_VARIABLE: + buf.append("RESOURCE_VARIABLE"); + break; + case TypeReference.EXCEPTION_PARAMETER: + buf.append("EXCEPTION_PARAMETER ").append( + ref.getTryCatchBlockIndex()); + break; + case TypeReference.INSTANCEOF: + buf.append("INSTANCEOF"); + break; + case TypeReference.NEW: + buf.append("NEW"); + break; + case TypeReference.CONSTRUCTOR_REFERENCE: + buf.append("CONSTRUCTOR_REFERENCE"); + break; + case TypeReference.METHOD_REFERENCE: + buf.append("METHOD_REFERENCE"); + break; + case TypeReference.CAST: + buf.append("CAST ").append(ref.getTypeArgumentIndex()); + break; + case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + buf.append("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ").append( + ref.getTypeArgumentIndex()); + break; + case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT: + buf.append("METHOD_INVOCATION_TYPE_ARGUMENT ").append( + ref.getTypeArgumentIndex()); + break; + case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: + buf.append("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT ").append( + ref.getTypeArgumentIndex()); + break; + case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT: + buf.append("METHOD_REFERENCE_TYPE_ARGUMENT ").append( + ref.getTypeArgumentIndex()); + break; + } + } + private void appendFrameTypes(final int n, final Object[] o) { for (int i = 0; i < n; ++i) { if (i > 0) { @@ -1285,27 +1402,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/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java index a08a1a7c880173db9e991ef20b28d87989030729..d521c2cf484ed3b4b53c01aca7c00df6d1958eaf 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java @@ -76,7 +76,7 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor { } public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) { - super(Opcodes.ASM4, av); + super(Opcodes.ASM5, av); this.p = p; } @@ -87,33 +87,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/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java index fd2d66a24add2a2923851b235d5bbdacee9e182a..e927bff9ea5c202825c7e3bcc2c5fdf3f762c7f5 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java @@ -30,7 +30,6 @@ * * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom - * Copyright (c) 2011 Google * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -67,15 +66,20 @@ import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; /** * 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.

        The trace printed when - * visiting the Hello class is the following:

        + * chain. This may be useful for debugging purposes. + *

        + * The trace printed when visiting the Hello class is the following: + *

        + *

        * - *
         // class version 49.0 (49) // access flags 0x21 public class Hello {
        + * 
        + * // class version 49.0 (49) // access flags 0x21 public class Hello {
          *
          * // compiled from: Hello.java
          *
        @@ -85,14 +89,21 @@ import jdk.internal.org.objectweb.asm.Opcodes;
          * // 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 } 
        + * MAXSTACK = 2 MAXLOCALS = 1 } + *
        * - *
        where Hello is defined by:

        + *
        where Hello is defined by: + *

        + *

        * - *
         public class Hello {
        + * 
        + * public class Hello {
          *
        - * public static void main(String[] args) {
        - * System.out.println("hello"); } } 
        + * public static void main(String[] args) { + * System.out.println("hello"); + * } + * } + *
        * *
        * @@ -114,7 +125,8 @@ 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); @@ -123,9 +135,11 @@ public final class TraceClassVisitor extends ClassVisitor { /** * Constructs a new {@link TraceClassVisitor}. * - * @param cv the {@link ClassVisitor} to which this visitor delegates calls. - * May be null. - * @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 null. + * @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); @@ -134,32 +148,27 @@ public final class TraceClassVisitor extends ClassVisitor { /** * Constructs a new {@link TraceClassVisitor}. * - * @param cv the {@link ClassVisitor} to which this visitor delegates calls. - * May be null. - * @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 null. + * @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) - { - super(Opcodes.ASM4, cv); + public TraceClassVisitor(final ClassVisitor cv, final Printer p, + final PrintWriter pw) { + super(Opcodes.ASM5, 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); } @@ -171,26 +180,31 @@ 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); return new TraceAnnotationVisitor(av, p); } + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + Printer p = this.p.visitClassTypeAnnotation(typeRef, typePath, desc, + visible); + AnnotationVisitor av = cv == null ? null : cv.visitTypeAnnotation( + typeRef, typePath, desc, visible); + return new TraceAnnotationVisitor(av, p); + } + @Override public void visitAttribute(final Attribute attr) { p.visitClassAttribute(attr); @@ -198,55 +212,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/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java index 2b4d8cbeebbbdf382b8fac9c1f82a536509bd819..4c15f996fbfeb766b1a1e1b9997ed4aa8b868a61 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java @@ -30,7 +30,6 @@ * * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom - * Copyright (c) 2011 Google * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,6 +62,7 @@ import jdk.internal.org.objectweb.asm.AnnotationVisitor; import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; /** * A {@link FieldVisitor} that prints the fields it visits with a @@ -79,21 +79,29 @@ public final class TraceFieldVisitor extends FieldVisitor { } public TraceFieldVisitor(final FieldVisitor fv, final Printer p) { - super(Opcodes.ASM4, fv); + super(Opcodes.ASM5, 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); return new TraceAnnotationVisitor(av, p); } + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + Printer p = this.p.visitFieldTypeAnnotation(typeRef, typePath, desc, + visible); + AnnotationVisitor av = fv == null ? null : fv.visitTypeAnnotation( + typeRef, typePath, desc, visible); + return new TraceAnnotationVisitor(av, p); + } + @Override public void visitAttribute(final Attribute attr) { p.visitFieldAttribute(attr); diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java index c40964cb7f897ac137ad2f3ebfb4f39a1ae8410c..bf80e1f38ca8f0c1bf42c933fac7b0c2ab8863a4 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java @@ -30,7 +30,6 @@ * * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom - * Copyright (c) 2011 Google * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -65,6 +64,7 @@ import jdk.internal.org.objectweb.asm.Handle; import jdk.internal.org.objectweb.asm.Label; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; /** * A {@link MethodVisitor} that prints the methods it visits with a @@ -81,21 +81,35 @@ public final class TraceMethodVisitor extends MethodVisitor { } public TraceMethodVisitor(final MethodVisitor mv, final Printer p) { - super(Opcodes.ASM4, mv); + super(Opcodes.ASM5, mv); this.p = p; } @Override - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { + public void visitParameter(String name, int access) { + p.visitParameter(name, access); + super.visitParameter(name, access); + } + + @Override + 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); return new TraceAnnotationVisitor(av, p); } + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + Printer p = this.p.visitMethodTypeAnnotation(typeRef, typePath, desc, + visible); + AnnotationVisitor av = mv == null ? null : mv.visitTypeAnnotation( + typeRef, typePath, desc, visible); + return new TraceAnnotationVisitor(av, p); + } + @Override public void visitAttribute(final Attribute attr) { p.visitMethodAttribute(attr); @@ -110,17 +124,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); } @@ -131,13 +139,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); } @@ -167,34 +170,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); } @@ -224,22 +215,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); } @@ -251,29 +235,52 @@ public final class TraceMethodVisitor extends MethodVisitor { } @Override - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { + public AnnotationVisitor visitInsnAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + Printer p = this.p + .visitInsnAnnotation(typeRef, typePath, desc, visible); + AnnotationVisitor av = mv == null ? null : mv.visitInsnAnnotation( + typeRef, typePath, desc, visible); + return new TraceAnnotationVisitor(av, p); + } + + @Override + 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 AnnotationVisitor visitTryCatchAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + Printer p = this.p.visitTryCatchAnnotation(typeRef, typePath, desc, + visible); + AnnotationVisitor av = mv == null ? null : mv.visitTryCatchAnnotation( + typeRef, typePath, desc, visible); + return new TraceAnnotationVisitor(av, p); + } + + @Override + 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); } + @Override + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, + TypePath typePath, Label[] start, Label[] end, int[] index, + String desc, boolean visible) { + Printer p = this.p.visitLocalVariableAnnotation(typeRef, typePath, + start, end, index, desc, visible); + AnnotationVisitor av = mv == null ? null : mv + .visitLocalVariableAnnotation(typeRef, typePath, start, end, + index, desc, visible); + return new TraceAnnotationVisitor(av, p); + } + @Override public void visitLineNumber(final int line, final Label start) { p.visitLineNumber(line, start); diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java index 8244bcf85e4b39c8c3ab9e74f3c0a24ffd6eb66e..f4925846c59b554e41dac0d17a4e843da88e3d2c 100644 --- a/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java @@ -104,13 +104,13 @@ public final class TraceSignatureVisitor extends SignatureVisitor { private String separator = ""; public TraceSignatureVisitor(final int access) { - super(Opcodes.ASM4); + super(Opcodes.ASM5); isInterface = (access & Opcodes.ACC_INTERFACE) != 0; this.declaration = new StringBuffer(); } private TraceSignatureVisitor(final StringBuffer buf) { - super(Opcodes.ASM4); + super(Opcodes.ASM5); this.declaration = buf; } @@ -146,8 +146,7 @@ public final class TraceSignatureVisitor extends SignatureVisitor { @Override public SignatureVisitor visitInterface() { - separator = seenInterface ? ", " : isInterface - ? " extends " + separator = seenInterface ? ", " : isInterface ? " extends " : " implements "; seenInterface = true; startType(); @@ -194,34 +193,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(); } diff --git a/src/share/classes/jdk/internal/org/objectweb/asm/version.txt b/src/share/classes/jdk/internal/org/objectweb/asm/version.txt new file mode 100644 index 0000000000000000000000000000000000000000..d795ab2a10b75b45d66774cf706a3bcbdf0207bd --- /dev/null +++ b/src/share/classes/jdk/internal/org/objectweb/asm/version.txt @@ -0,0 +1,12 @@ +Path: . +Working Copy Root Path: /w/lthudson/hudson-data/jobs/objectweb-cr-pull/workspace/ASM_5_FUTURE +URL: svn://svn.forge.objectweb.org/svnroot/asm/branches/ASM_5_FUTURE +Repository Root: svn://svn.forge.objectweb.org/svnroot/asm +Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9 +Revision: 1681 +Node Kind: directory +Schedule: normal +Last Changed Author: forax +Last Changed Rev: 1681 +Last Changed Date: 2013-04-01 11:28:58 -0700 (Mon, 01 Apr 2013) +