# HG changeset patch # User ksrini # Date 1383765735 28800 # Node ID 53b88e4ac6ed779e3813a89f830400858364d9ab # Parent 9fa27f34bd3db84dfaf78dd0a0195d1b756255e8 8027227: [asm] generate CONSTANT_InterfaceMethodref for invoke{special/static) of non-abstract methods on ifaces Reviewed-by: ksrini, lagergren Contributed-by: ebruneton@free.fr, forax@univ-mlv.fr, john.r.rose@oracle.com, paul.sandoz@oracle.com diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java Wed Nov 06 11:22:15 2013 -0800 @@ -233,11 +233,14 @@ * automatically enlarged if necessary. * * @param s - * a String. + * a String whose UTF8 encoded length must be less than 65536. * @return this byte vector. */ public ByteVector putUTF8(final String s) { int charLength = s.length(); + if (charLength > 65535) { + throw new IllegalArgumentException(); + } int len = length; if (len + 2 + charLength > data.length) { enlarge(2 + charLength); @@ -267,6 +270,9 @@ byteLength += 2; } } + if (byteLength > 65535) { + throw new IllegalArgumentException(); + } data[length] = (byte) (byteLength >>> 8); data[length + 1] = (byte) byteLength; if (length + 2 + byteLength > data.length) { diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java Wed Nov 06 11:22:15 2013 -0800 @@ -1266,7 +1266,7 @@ u += 2; // generates the first (implicit) stack map frame - if (FRAMES && (stackMap != 0 || unzip)) { + if (FRAMES && stackMap != 0) { /* * for the first explicit frame the offset is not offset_delta + 1 * but only offset_delta; setting the implicit frame offset to -1 @@ -1283,8 +1283,6 @@ 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 @@ -1322,17 +1320,19 @@ } } - // visits the frame(s) for this offset, if any + // visits the frame for this offset, if any while (FRAMES && frame != null && (frame.offset == offset || frame.offset == -1)) { // if there is a frame for this offset, makes the visitor visit // it, and reads the next frame if there is one. - if (!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 (frame.offset != -1) { + if (!zip || unzip) { + mv.visitFrame(Opcodes.F_NEW, frame.localCount, + frame.local, frame.stackCount, frame.stack); + } else { + mv.visitFrame(frame.mode, frame.localDiff, frame.local, + frame.stackCount, frame.stack); + } } if (frameCount > 0) { stackMap = readFrame(stackMap, zip, unzip, frame); @@ -1434,6 +1434,7 @@ case ClassWriter.FIELDORMETH_INSN: case ClassWriter.ITFMETH_INSN: { int cpIndex = items[readUnsignedShort(u + 1)]; + boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; String iowner = readClass(cpIndex, c); cpIndex = items[readUnsignedShort(cpIndex + 2)]; String iname = readUTF8(cpIndex, c); @@ -1441,7 +1442,7 @@ if (opcode < Opcodes.INVOKEVIRTUAL) { mv.visitFieldInsn(opcode, iowner, iname, idesc); } else { - mv.visitMethodInsn(opcode, iowner, iname, idesc); + mv.visitMethodInsn(opcode, iowner, iname, idesc, itf); } if (opcode == Opcodes.INVOKEINTERFACE) { u += 5; diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java Wed Nov 06 11:22:15 2013 -0800 @@ -516,12 +516,12 @@ * true if the maximum stack size and number of local variables * must be automatically computed. */ - private final boolean computeMaxs; + private boolean computeMaxs; /** * true if the stack map frames must be recomputed from scratch. */ - private final boolean computeFrames; + private boolean computeFrames; /** * true if the stack map tables of this class are invalid. The @@ -988,9 +988,22 @@ attrs.put(this, null, 0, -1, -1, out); } if (invalidFrames) { - ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); - new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES); - return cw.toByteArray(); + anns = null; + ianns = null; + attrs = null; + innerClassesCount = 0; + innerClasses = null; + bootstrapMethodsCount = 0; + bootstrapMethods = null; + firstField = null; + lastField = null; + firstMethod = null; + lastMethod = null; + computeMaxs = false; + computeFrames = true; + invalidFrames = false; + new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES); + return toByteArray(); } return out.data; } diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java Wed Nov 06 11:22:15 2013 -0800 @@ -78,7 +78,8 @@ final int tag; /** - * The internal name of the field or method designed by this handle. + * The internal name of the class that owns the field or method designated + * by this handle. */ final String owner; @@ -105,8 +106,8 @@ * {@link Opcodes#H_NEWINVOKESPECIAL} or * {@link Opcodes#H_INVOKEINTERFACE}. * @param owner - * the internal name of the field or method designed by this - * handle. + * the internal name of the class that owns the field or method + * designated by this handle. * @param name * the name of the field or method designated by this handle. * @param desc @@ -135,9 +136,11 @@ } /** - * Returns the internal name of the field or method designed by this handle. + * Returns the internal name of the class that owns the field or method + * designated by this handle. * - * @return the internal name of the field or method designed by this handle. + * @return the internal name of the class that owns the field or method + * designated by this handle. */ public String getOwner() { return owner; diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java Wed Nov 06 11:22:15 2013 -0800 @@ -68,11 +68,11 @@ * 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, + * 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 @@ -274,13 +274,9 @@ * compressed form (all frames must use the same format, i.e. you must not * mix expanded and compressed frames within a single method): * + * * + *
+ * In both cases the first frame, corresponding to the method's parameters + * and access flags, is implicit and must not be visited. Also, it is + * illegal to visit two or more frames for the same code location (i.e., at + * least one instruction must be visited between two calls to visitFrame). * * @param type * the type of this stack map frame. Must be @@ -466,14 +468,53 @@ * @param desc * the method's descriptor (see {@link Type Type}). */ + @Deprecated public void visitMethodInsn(int opcode, String owner, String name, String desc) { + if (api >= Opcodes.ASM5) { + boolean itf = opcode == Opcodes.INVOKEINTERFACE; + visitMethodInsn(opcode, owner, name, desc, itf); + return; + } if (mv != null) { mv.visitMethodInsn(opcode, owner, name, desc); } } /** + * Visits a method instruction. A method instruction is an instruction that + * invokes a method. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner + * the internal name of the method's owner class (see + * {@link Type#getInternalName() getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param itf + * if the method's owner class is an interface. + */ + public void visitMethodInsn(int opcode, String owner, String name, + String desc, boolean itf) { + if (api < Opcodes.ASM5) { + if (itf != (opcode == Opcodes.INVOKEINTERFACE)) { + throw new IllegalArgumentException( + "INVOKESPECIAL/STATIC on interfaces require ASM 5"); + } + visitMethodInsn(opcode, owner, name, desc); + return; + } + if (mv != null) { + mv.visitMethodInsn(opcode, owner, name, desc, itf); + } + } + + /** * Visits an invokedynamic instruction. * * @param name diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java Wed Nov 06 11:22:15 2013 -0800 @@ -71,7 +71,7 @@ /** * Pseudo access flag used to denote constructors. */ - static final int ACC_CONSTRUCTOR = 262144; + static final int ACC_CONSTRUCTOR = 0x80000; /** * Frame has exactly the same locals as the previous stack map frame and @@ -298,11 +298,6 @@ private int[] previousFrame; /** - * Index of the next element to be added in {@link #frame}. - */ - private int frameIndex; - - /** * The current stack map frame. The first element contains the offset of the * instruction to which the frame corresponds, the second element is the * number of locals and the third one is the number of stack elements. The @@ -496,6 +491,9 @@ cw.lastMethod = this; this.cw = cw; this.access = access; + if ("".equals(name)) { + this.access |= ACC_CONSTRUCTOR; + } this.name = cw.newUTF8(name); this.desc = cw.newUTF8(desc); this.descriptor = desc; @@ -511,9 +509,6 @@ } this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); if (computeMaxs || computeFrames) { - if (computeFrames && "".equals(name)) { - this.access |= ACC_CONSTRUCTOR; - } // updates maxLocals int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2; if ((access & Opcodes.ACC_STATIC) != 0) { @@ -649,8 +644,11 @@ } if (type == Opcodes.F_NEW) { + if (previousFrame == null) { + visitImplicitFirstFrame(); + } currentLocals = nLocal; - startFrame(code.length, nLocal, nStack); + int frameIndex = startFrame(code.length, nLocal, nStack); for (int i = 0; i < nLocal; ++i) { if (local[i] instanceof String) { frame[frameIndex++] = Frame.OBJECT @@ -914,9 +912,8 @@ @Override public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc) { + final String name, final String desc, final boolean itf) { lastCodeOffset = code.length; - boolean itf = opcode == Opcodes.INVOKEINTERFACE; Item i = cw.newMethodItem(owner, name, desc, itf); int argSize = i.intVal; // Label currentBlock = this.currentBlock; @@ -954,7 +951,7 @@ } } // adds the instruction to the bytecode of the method - if (itf) { + if (opcode == Opcodes.INVOKEINTERFACE) { if (argSize == 0) { argSize = Type.getArgumentsAndReturnSizes(desc); i.intVal = argSize; @@ -1528,8 +1525,8 @@ } code.data[end] = (byte) Opcodes.ATHROW; // emits a frame for this unreachable block - startFrame(start, 0, 1); - frame[frameIndex++] = Frame.OBJECT + int frameIndex = startFrame(start, 0, 1); + frame[frameIndex] = Frame.OBJECT | cw.addType("java/lang/Throwable"); endFrame(); // removes the start-end range from the exception @@ -1756,7 +1753,7 @@ } } // visits the frame and its content - startFrame(f.owner.position, nLocal, nStack); + int frameIndex = startFrame(f.owner.position, nLocal, nStack); for (i = 0; nLocal > 0; ++i, --nLocal) { t = locals[i]; frame[frameIndex++] = t; @@ -1775,6 +1772,67 @@ } /** + * Visit the implicit first frame of this method. + */ + private void visitImplicitFirstFrame() { + // There can be at most descriptor.length() + 1 locals + int frameIndex = startFrame(0, descriptor.length() + 1, 0); + if ((access & Opcodes.ACC_STATIC) == 0) { + if ((access & ACC_CONSTRUCTOR) == 0) { + frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName); + } else { + frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS; + } + } + int i = 1; + loop: while (true) { + int j = i; + switch (descriptor.charAt(i++)) { + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + frame[frameIndex++] = 1; // Opcodes.INTEGER; + break; + case 'F': + frame[frameIndex++] = 2; // Opcodes.FLOAT; + break; + case 'J': + frame[frameIndex++] = 4; // Opcodes.LONG; + break; + case 'D': + frame[frameIndex++] = 3; // Opcodes.DOUBLE; + break; + case '[': + while (descriptor.charAt(i) == '[') { + ++i; + } + if (descriptor.charAt(i) == 'L') { + ++i; + while (descriptor.charAt(i) != ';') { + ++i; + } + } + frame[frameIndex++] = Frame.OBJECT + | cw.addType(descriptor.substring(j, ++i)); + break; + case 'L': + while (descriptor.charAt(i) != ';') { + ++i; + } + frame[frameIndex++] = Frame.OBJECT + | cw.addType(descriptor.substring(j + 1, i++)); + break; + default: + break loop; + } + } + frame[1] = frameIndex - 3; + endFrame(); + } + + /** * Starts the visit of a stack map frame. * * @param offset @@ -1783,8 +1841,9 @@ * the number of local variables in the frame. * @param nStack * the number of stack elements in the frame. + * @return the index of the next element to be written in this frame. */ - private void startFrame(final int offset, final int nLocal, final int nStack) { + private int startFrame(final int offset, final int nLocal, final int nStack) { int n = 3 + nLocal + nStack; if (frame == null || frame.length < n) { frame = new int[n]; @@ -1792,7 +1851,7 @@ frame[0] = offset; frame[1] = nLocal; frame[2] = nStack; - frameIndex = 3; + return 3; } /** @@ -2110,7 +2169,8 @@ */ final void put(final ByteVector out) { final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; - int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); out.putShort(access & ~mask).putShort(name).putShort(desc); if (classReaderOffset != 0) { diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -442,10 +442,31 @@ } } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { - mv.visitMethodInsn(opcode, owner, name, desc); + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, final String owner, + final String name, final String desc, final boolean itf) { + mv.visitMethodInsn(opcode, owner, name, desc, itf); if (constructor) { Type[] types = Type.getArgumentTypes(desc); for (int i = 0; i < types.length; i++) { diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -165,10 +165,15 @@ * @param mv * the method visitor to which this adapter delegates calls. May * be null. + * @throws IllegalStateException + * If a subclass calls this constructor. */ 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); + if (getClass() != AnalyzerAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -331,11 +336,32 @@ execute(opcode, 0, desc); } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, final String owner, + final String name, final String desc, final boolean itf) { if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc); + mv.visitMethodInsn(opcode, owner, name, desc, itf); } if (this.locals == null) { labels = null; diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java Wed Nov 06 11:22:15 2013 -0800 @@ -149,9 +149,30 @@ } } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, final String owner, + final String name, final String desc, final boolean itf) { if (opcode == INVOKEINTERFACE) { minSize += 5; maxSize += 5; @@ -160,7 +181,7 @@ maxSize += 3; } if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc); + mv.visitMethodInsn(opcode, owner, name, desc, itf); } } diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -284,10 +284,15 @@ * the method's name. * @param desc * the method's descriptor (see {@link Type Type}). + * @throws IllegalStateException + * If a subclass calls this constructor. */ public GeneratorAdapter(final MethodVisitor mv, final int access, final String name, final String desc) { this(Opcodes.ASM5, mv, access, name, desc); + if (getClass() != GeneratorAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -1400,11 +1405,11 @@ * the method to be invoked. */ private void invokeInsn(final int opcode, final Type type, - final Method method) { + final Method method, final boolean itf) { String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName(); mv.visitMethodInsn(opcode, owner, method.getName(), - method.getDescriptor()); + method.getDescriptor(), itf); } /** @@ -1416,7 +1421,7 @@ * the method to be invoked. */ public void invokeVirtual(final Type owner, final Method method) { - invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method); + invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method, false); } /** @@ -1428,7 +1433,7 @@ * the constructor to be invoked. */ public void invokeConstructor(final Type type, final Method method) { - invokeInsn(Opcodes.INVOKESPECIAL, type, method); + invokeInsn(Opcodes.INVOKESPECIAL, type, method, false); } /** @@ -1440,7 +1445,7 @@ * the method to be invoked. */ public void invokeStatic(final Type owner, final Method method) { - invokeInsn(Opcodes.INVOKESTATIC, owner, method); + invokeInsn(Opcodes.INVOKESTATIC, owner, method, false); } /** @@ -1452,7 +1457,7 @@ * the method to be invoked. */ public void invokeInterface(final Type owner, final Method method) { - invokeInsn(Opcodes.INVOKEINTERFACE, owner, method); + invokeInsn(Opcodes.INVOKEINTERFACE, owner, method, true); } /** diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -82,9 +82,14 @@ * * @param mv * the method visitor to which this adapter delegates calls. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public InstructionAdapter(final MethodVisitor mv) { this(Opcodes.ASM5, mv); + if (getClass() != InstructionAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -536,18 +541,39 @@ } } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, final String owner, + final String name, final String desc, final boolean itf) { switch (opcode) { case Opcodes.INVOKESPECIAL: - invokespecial(owner, name, desc); + invokespecial(owner, name, desc, itf); break; case Opcodes.INVOKEVIRTUAL: - invokevirtual(owner, name, desc); + invokevirtual(owner, name, desc, itf); break; case Opcodes.INVOKESTATIC: - invokestatic(owner, name, desc); + invokestatic(owner, name, desc, itf); break; case Opcodes.INVOKEINTERFACE: invokeinterface(owner, name, desc); @@ -1014,24 +1040,78 @@ mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc); } + @Deprecated public void invokevirtual(final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + invokevirtual(owner, name, desc, false); + return; + } mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc); } + public void invokevirtual(final String owner, final String name, + final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + if (itf) { + throw new IllegalArgumentException( + "INVOKEVIRTUAL on interfaces require ASM 5"); + } + invokevirtual(owner, name, desc); + return; + } + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf); + } + + @Deprecated + public void invokespecial(final String owner, final String name, + final String desc) { + if (api >= Opcodes.ASM5) { + invokespecial(owner, name, desc, false); + return; + } + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false); + } + public void invokespecial(final String owner, final String name, + final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + if (itf) { + throw new IllegalArgumentException( + "INVOKESPECIAL on interfaces require ASM 5"); + } + invokespecial(owner, name, desc); + return; + } + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf); + } + + @Deprecated + public void invokestatic(final String owner, final String name, final String desc) { - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc); + if (api < Opcodes.ASM5) { + invokestatic(owner, name, desc, false); + return; + } + mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false); } public void invokestatic(final String owner, final String name, - final String desc) { - mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc); + final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + if (itf) { + throw new IllegalArgumentException( + "INVOKESTATIC on interfaces require ASM 5"); + } + invokestatic(owner, name, desc); + return; + } + mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf); } public void invokeinterface(final String owner, final String name, final String desc) { - mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc); + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true); } public void invokedynamic(String name, String desc, Handle bsm, diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -136,11 +136,16 @@ * the internal names of the method's exception classes (see * {@link Type#getInternalName() getInternalName}). May be * null. + * @throws IllegalStateException + * If a subclass calls this constructor. */ 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); + if (getClass() != JSRInlinerAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -381,6 +386,17 @@ // Use tail recursion here in the form of an outer while loop to // avoid our stack growing needlessly: index++; + + // We implicitly assumed above that execution can always fall + // through to the next instruction after a JSR. But a subroutine may + // never return, in which case the code after the JSR is unreachable + // and can be anything. In particular, it can seem to fall off the + // end of the method, so we must handle this case here (we could + // instead detect whether execution can return or not from a JSR, + // but this is more complicated). + if (index >= instructions.size()) { + return; + } } } diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java Wed Nov 06 11:22:15 2013 -0800 @@ -120,10 +120,15 @@ * the method's descriptor (see {@link Type Type}). * @param mv * the method visitor to which this adapter delegates calls. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public LocalVariablesSorter(final int access, final String desc, final MethodVisitor mv) { this(Opcodes.ASM5, access, desc, mv); + if (getClass() != LocalVariablesSorter.class) { + throw new IllegalStateException(); + } } /** @@ -323,6 +328,7 @@ int local = newLocalMapping(type); setLocalType(local, type); setFrameLocal(local, t); + changed = true; return local; } diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -148,12 +148,41 @@ remapper.mapDesc(desc)); } + @Deprecated @Override - 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)); + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, String owner, String name, + String desc, boolean itf) { + // Calling super.visitMethodInsn requires to call the correct version + // depending on this.api (otherwise infinite loops can occur). To + // simplify and to make it easier to automatically remove the backward + // compatibility code, we inline the code of the overridden method here. + // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN + // LocalVariableSorter. + if (mv != null) { + mv.visitMethodInsn(opcode, remapper.mapType(owner), + remapper.mapMethodName(owner, name, desc), + remapper.mapMethodDesc(desc), itf); + } } @Override diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -95,10 +95,12 @@ @Override public void visitInnerClassType(String name) { + String remappedOuter = remapper.mapType(className) + '$'; className = className + '$' + name; String remappedName = remapper.mapType(className); - v.visitInnerClassType(remappedName.substring(remappedName - .lastIndexOf('$') + 1)); + int index = remappedName.startsWith(remappedOuter) ? remappedOuter + .length() : remappedName.lastIndexOf('$') + 1; + v.visitInnerClassType(remappedName.substring(index)); } @Override diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java Wed Nov 06 11:22:15 2013 -0800 @@ -195,9 +195,14 @@ * @param cv * a {@link ClassVisitor} to which this visitor will delegate * calls. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public SerialVersionUIDAdder(final ClassVisitor cv) { this(Opcodes.ASM5, cv); + if (getClass() != SerialVersionUIDAdder.class) { + throw new IllegalStateException(); + } } /** @@ -218,7 +223,7 @@ } // ------------------------------------------------------------------------ - // Overriden methods + // Overridden methods // ------------------------------------------------------------------------ /* @@ -234,7 +239,7 @@ if (computeSVUID) { this.name = name; this.access = access; - this.interfaces = interfaces; + this.interfaces = Arrays.copyOf(interfaces, interfaces.length); } super.visit(version, access, name, signature, superName, interfaces); diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java Wed Nov 06 11:22:15 2013 -0800 @@ -107,7 +107,8 @@ if (clinit == null) { clinit = cv.visitMethod(a, name, desc, null, null); } - clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc); + clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc, + false); } else { mv = cv.visitMethod(access, name, desc, signature, exceptions); } diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java Wed Nov 06 11:22:15 2013 -0800 @@ -66,7 +66,6 @@ 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 diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java Wed Nov 06 11:22:15 2013 -0800 @@ -96,9 +96,14 @@ * * @param desc * the class descriptor of the annotation class. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public AnnotationNode(final String desc) { this(Opcodes.ASM5, desc); + if (getClass() != AnnotationNode.class) { + throw new IllegalStateException(); + } } /** diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java Wed Nov 06 11:22:15 2013 -0800 @@ -216,9 +216,15 @@ * Constructs a new {@link ClassNode}. Subclasses must not use this * constructor. Instead, they must use the {@link #ClassNode(int)} * version. + * + * @throws IllegalStateException + * If a subclass calls this constructor. */ public ClassNode() { this(Opcodes.ASM5); + if (getClass() != ClassNode.class) { + throw new IllegalStateException(); + } } /** diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java Wed Nov 06 11:22:15 2013 -0800 @@ -168,16 +168,20 @@ * 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}. + * @throws IllegalStateException + * If a subclass calls this constructor. */ 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); + if (getClass() != FieldNode.class) { + throw new IllegalStateException(); + } } /** * Constructs a new {@link FieldNode}. Subclasses must not use this - * constructor. Instead, they must use the - * {@link #FieldNode(int, int, String, String, String, Object)} version. + * constructor. * * @param api * the ASM API version implemented by this visitor. Must be one diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java Wed Nov 06 11:22:15 2013 -0800 @@ -61,6 +61,7 @@ import java.util.Map; import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; /** * A node that represents a method instruction. A method instruction is an @@ -87,6 +88,11 @@ public String desc; /** + * If the method's owner class if an interface. + */ + public boolean itf; + + /** * Constructs a new {@link MethodInsnNode}. * * @param opcode @@ -102,12 +108,37 @@ * @param desc * the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). */ + @Deprecated public MethodInsnNode(final int opcode, final String owner, final String name, final String desc) { + this(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE); + } + + /** + * 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 itf + * if the method's owner class is an interface. + */ + public MethodInsnNode(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { super(opcode); this.owner = owner; this.name = name; this.desc = desc; + this.itf = itf; } /** @@ -128,11 +159,11 @@ @Override public void accept(final MethodVisitor mv) { - mv.visitMethodInsn(opcode, owner, name, desc); + mv.visitMethodInsn(opcode, owner, name, desc, itf); } @Override public AbstractInsnNode clone(final Map labels) { - return new MethodInsnNode(opcode, owner, name, desc); + return new MethodInsnNode(opcode, owner, name, desc, itf); } } diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java Wed Nov 06 11:22:15 2013 -0800 @@ -71,7 +71,6 @@ 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. @@ -245,9 +244,15 @@ * Constructs an uninitialized {@link MethodNode}. Subclasses must not * use this constructor. Instead, they must use the * {@link #MethodNode(int)} version. + * + * @throws IllegalStateException + * If a subclass calls this constructor. */ public MethodNode() { this(Opcodes.ASM5); + if (getClass() != MethodNode.class) { + throw new IllegalStateException(); + } } /** @@ -281,10 +286,15 @@ * the internal names of the method's exception classes (see * {@link Type#getInternalName() getInternalName}). May be * null. + * @throws IllegalStateException + * If a subclass calls this constructor. */ 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); + if (getClass() != MethodNode.class) { + throw new IllegalStateException(); + } } /** @@ -461,13 +471,28 @@ instructions.add(new FieldInsnNode(opcode, owner, name, desc)); } + @Deprecated @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc) { + public void visitMethodInsn(int opcode, String owner, String name, + String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } instructions.add(new MethodInsnNode(opcode, owner, name, desc)); } @Override + public void visitMethodInsn(int opcode, String owner, String name, + String desc, boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf)); + } + + @Override public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)); @@ -696,6 +721,12 @@ && insn.invisibleTypeAnnotations.size() > 0) { throw new RuntimeException(); } + if (insn instanceof MethodInsnNode) { + boolean itf = ((MethodInsnNode) insn).itf; + if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) { + throw new RuntimeException(); + } + } } if (visibleLocalVariableAnnotations != null && visibleLocalVariableAnnotations.size() > 0) { @@ -705,7 +736,6 @@ && invisibleLocalVariableAnnotations.size() > 0) { throw new RuntimeException(); } - } } diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java Wed Nov 06 11:22:15 2013 -0800 @@ -94,10 +94,15 @@ * null if the annotation targets 'typeRef' as a whole. * @param desc * the class descriptor of the annotation class. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public TypeAnnotationNode(final int typeRef, final TypePath typePath, final String desc) { this(Opcodes.ASM5, typeRef, typePath, desc); + if (getClass() != TypeAnnotationNode.class) { + throw new IllegalStateException(); + } } /** diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java Wed Nov 06 11:22:15 2013 -0800 @@ -163,6 +163,15 @@ } /** + * Returns the maximum stack size of this frame. + * + * @return the maximum stack size of this frame. + */ + public int getMaxStackSize() { + return values.length - locals; + } + + /** * Returns the value of the given local variable. * * @param i diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java Wed Nov 06 11:22:15 2013 -0800 @@ -113,9 +113,15 @@ * Constructs a new {@link ASMifier}. Subclasses must not use this * constructor. Instead, they must use the * {@link #ASMifier(int, String, int)} version. + * + * @throws IllegalStateException + * If a subclass calls this constructor. */ public ASMifier() { this(Opcodes.ASM5, "cw", 0); + if (getClass() != ASMifier.class) { + throw new IllegalStateException(); + } } /** @@ -483,8 +489,9 @@ @Override public void visitParameter(String parameterName, int access) { buf.setLength(0); - buf.append(name).append(".visitParameter(").append(parameterName) - .append(", "); + buf.append(name).append(".visitParameter("); + appendString(buf, parameterName); + buf.append(", "); appendAccess(access); text.add(buf.append(");\n").toString()); } @@ -639,9 +646,30 @@ text.add(buf.toString()); } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { buf.setLength(0); buf.append(this.name).append(".visitMethodInsn(") .append(OPCODES[opcode]).append(", "); @@ -650,6 +678,8 @@ appendConstant(name); buf.append(", "); appendConstant(desc); + buf.append(", "); + buf.append(itf ? "true" : "false"); buf.append(");\n"); text.add(buf.toString()); } @@ -1076,6 +1106,13 @@ buf.append("ACC_DEPRECATED"); first = false; } + if ((access & Opcodes.ACC_MANDATED) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_MANDATED"); + first = false; + } if (first) { buf.append('0'); } diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -246,7 +246,7 @@ List interfaces = new ArrayList(); for (Iterator i = cn.interfaces.iterator(); i.hasNext();) { - interfaces.add(Type.getObjectType(i.next().toString())); + interfaces.add(Type.getObjectType(i.next())); } for (int i = 0; i < methods.size(); ++i) { @@ -359,9 +359,14 @@ * false to not perform any data flow check (see * {@link CheckMethodAdapter}). This option requires valid * maxLocals and maxStack values. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) { this(Opcodes.ASM5, cv, checkDataFlow); + if (getClass() != CheckClassAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -471,7 +476,15 @@ CheckMethodAdapter.checkInternalName(outerName, "outer class name"); } if (innerName != null) { - CheckMethodAdapter.checkIdentifier(innerName, "inner class name"); + int start = 0; + while (start < innerName.length() + && Character.isDigit(innerName.charAt(start))) { + start++; + } + if (start == 0 || start < innerName.length()) { + CheckMethodAdapter.checkIdentifier(innerName, start, -1, + "inner class name"); + } } checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -79,9 +79,14 @@ * * @param fv * the field visitor to which this adapter must delegate calls. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public CheckFieldAdapter(final FieldVisitor fv) { this(Opcodes.ASM5, fv); + if (getClass() != CheckFieldAdapter.class) { + throw new IllegalStateException(); + } } /** diff -r 9fa27f34bd3d -r 53b88e4ac6ed jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java Wed Nov 06 13:25:24 2013 -0800 +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java Wed Nov 06 11:22:15 2013 -0800 @@ -143,11 +143,6 @@ private Set