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
--- 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) {
--- 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;
--- 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 @@
* <tt>true</tt> if the maximum stack size and number of local variables
* must be automatically computed.
*/
- private final boolean computeMaxs;
+ private boolean computeMaxs;
/**
* <tt>true</tt> if the stack map frames must be recomputed from scratch.
*/
- private final boolean computeFrames;
+ private boolean computeFrames;
/**
* <tt>true</tt> 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;
}
--- 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;
--- 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 @@
* <tt>visitTryCatchBlock</tt> | <tt>visitTryCatchBlockAnnotation</tt> |
* <tt>visitLocalVariable</tt> | <tt>visitLocalVariableAnnotation</tt> |
* <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In
- * addition, the <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt>
- * methods must be called in the sequential order of the bytecode instructions
- * of the visited code, <tt>visitInsnAnnotation</tt> must be called <i>after</i>
- * the annotated instruction, <tt>visitTryCatchBlock</tt> must be called
- * <i>before</i> the labels passed as arguments have been visited,
+ * addition, the <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must
+ * be called in the sequential order of the bytecode instructions of the visited
+ * code, <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated
+ * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
+ * labels passed as arguments have been visited,
* <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the
* corresponding try catch block has been visited, and the
* <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> 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):
* <ul>
- * <li>In expanded form, all frames must have the F_NEW type, and a first
- * frame corresponding to the method signature must be explicitly visited
- * before the first instruction.</li>
+ * <li>In expanded form, all frames must have the F_NEW type.</li>
* <li>In compressed form, frames are basically "deltas" from the state of
- * the previous frame (the first frame, corresponding to the method's
- * parameters and access flags, is implicit in this form, and must not be
- * visited):
+ * the previous frame:
* <ul>
* <li>{@link Opcodes#F_SAME} representing frame with exactly the same
* locals as the previous frame and with the empty stack.</li>
@@ -296,8 +292,14 @@
* same as the locals in the previous frame, except that the last 1-3 locals
* are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li>
* <li>{@link Opcodes#F_FULL} representing complete frame data.</li>
- * </ul></li>
+ * </ul>
+ * </li>
* </ul>
+ * <br>
+ * In both cases the first frame, corresponding to the method's parameters
+ * and access flags, is implicit and must not be visited. Also, it is
+ * illegal to visit two or more frames for the same code location (i.e., at
+ * least one instruction must be visited between two calls to visitFrame).
*
* @param type
* the type of this stack map frame. Must be
@@ -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
--- 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 ("<init>".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 && "<init>".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) {
--- 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++) {
--- 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 <tt>null</tt>.
+ * @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;
--- 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);
}
}
--- 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);
}
/**
--- 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,
--- 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
* <tt>null</tt>.
+ * @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;
+ }
}
}
--- 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;
}
--- 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
--- 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
--- 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);
--- 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);
}
--- 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
--- 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();
+ }
}
/**
--- 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}. <i>Subclasses must not use this
* constructor</i>. 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();
+ }
}
/**
--- 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 @@
* <tt>null</tt> if the field does not have an initial value,
* must be an {@link Integer}, a {@link Float}, a {@link Long}, a
* {@link Double} or a {@link String}.
+ * @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}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #FieldNode(int, int, String, String, String, Object)} version.
+ * constructor</i>.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
--- 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<LabelNode, LabelNode> labels) {
- return new MethodInsnNode(opcode, owner, name, desc);
+ return new MethodInsnNode(opcode, owner, name, desc, itf);
}
}
--- 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}. <i>Subclasses must not
* use this constructor</i>. 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
* <tt>null</tt>.
+ * @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();
}
-
}
}
--- 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 @@
* <tt>null</tt> 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();
+ }
}
/**
--- 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
--- 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}. <i>Subclasses must not use this
* constructor</i>. 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');
}
--- 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<Type> interfaces = new ArrayList<Type>();
for (Iterator<String> 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 @@
* <tt>false</tt> 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
--- 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();
+ }
}
/**
--- 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<Label> usedLabels;
/**
- * If an explicit first frame has been visited before the first instruction.
- */
- private boolean hasExplicitFirstFrame;
-
- /**
* Number of visited frames in expanded form.
*/
private int expandedFrames;
@@ -158,6 +153,11 @@
private int compressedFrames;
/**
+ * Number of instructions before the last visited frame.
+ */
+ private int lastFrame = -1;
+
+ /**
* The exception handler ranges. Each pair of list element contains the
* start and end labels of an exception handler block.
*/
@@ -421,10 +421,15 @@
* the method visitor to which this adapter must delegate calls.
* @param labels
* a map of already visited labels (in other methods).
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public CheckMethodAdapter(final MethodVisitor mv,
final Map<Label, Integer> labels) {
this(Opcodes.ASM5, mv, labels);
+ if (getClass() != CheckMethodAdapter.class) {
+ throw new IllegalStateException();
+ }
}
/**
@@ -465,7 +470,7 @@
public CheckMethodAdapter(final int access, final String name,
final String desc, final MethodVisitor cmv,
final Map<Label, Integer> labels) {
- this(new MethodNode(access, name, desc, null, null) {
+ this(new MethodNode(Opcodes.ASM5, access, name, desc, null, null) {
@Override
public void visitEnd() {
Analyzer<BasicValue> a = new Analyzer<BasicValue>(
@@ -499,6 +504,7 @@
}
CheckClassAdapter.checkAccess(access, Opcodes.ACC_FINAL
+ Opcodes.ACC_MANDATED + Opcodes.ACC_SYNTHETIC);
+ super.visitParameter(name, access);
}
@Override
@@ -566,6 +572,11 @@
@Override
public void visitFrame(final int type, final int nLocal,
final Object[] local, final int nStack, final Object[] stack) {
+ if (insnCount == lastFrame) {
+ throw new IllegalStateException(
+ "At most one frame can be visited at a given code location.");
+ }
+ lastFrame = insnCount;
int mLocal;
int mStack;
switch (type) {
@@ -621,13 +632,6 @@
checkFrameValue(stack[i]);
}
if (type == Opcodes.F_NEW) {
- if (insnCount == 0) {
- hasExplicitFirstFrame = true;
- } else if (!hasExplicitFirstFrame) {
- throw new RuntimeException(
- "In expanded form, a first frame must be explicitly "
- + "visited before the first instruction.");
- }
++expandedFrames;
} else {
++compressedFrames;
@@ -709,9 +713,30 @@
++insnCount;
}
+ @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;
+ }
+ doVisitMethodInsn(opcode, owner, name, desc,
+ opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @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;
+ }
+ doVisitMethodInsn(opcode, owner, name, desc, itf);
+ }
+
+ private void doVisitMethodInsn(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
checkStartCode();
checkEndCode();
checkOpcode(opcode, 5);
@@ -720,7 +745,21 @@
}
checkInternalName(owner, "owner");
checkMethodDesc(desc);
- super.visitMethodInsn(opcode, owner, name, desc);
+ if (opcode == Opcodes.INVOKEVIRTUAL && itf) {
+ throw new IllegalArgumentException(
+ "INVOKEVIRTUAL can't be used with interfaces");
+ }
+ if (opcode == Opcodes.INVOKEINTERFACE && !itf) {
+ throw new IllegalArgumentException(
+ "INVOKEINTERFACE can't be used with classes");
+ }
+ // 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.
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
++insnCount;
}
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java Wed Nov 06 13:25:24 2013 -0800
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java Wed Nov 06 11:22:15 2013 -0800
@@ -401,8 +401,33 @@
* Method instruction. See
* {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMethodInsn}.
*/
- public abstract void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc);
+ @Deprecated
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ if (api >= Opcodes.ASM5) {
+ boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ throw new RuntimeException("Must be overriden");
+ }
+
+ /**
+ * Method instruction. See
+ * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMethodInsn}.
+ */
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final 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;
+ }
+ throw new RuntimeException("Must be overriden");
+ }
/**
* Method instruction. See
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java Wed Nov 06 13:25:24 2013 -0800
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java Wed Nov 06 11:22:15 2013 -0800
@@ -172,9 +172,15 @@
* Constructs a new {@link Textifier}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the {@link #Textifier(int)}
* version.
+ *
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public Textifier() {
this(Opcodes.ASM5);
+ if (getClass() != Textifier.class) {
+ throw new IllegalStateException();
+ }
}
/**
@@ -821,14 +827,36 @@
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(tab2).append(OPCODES[opcode]).append(' ');
appendDescriptor(INTERNAL_NAME, owner);
buf.append('.').append(name).append(' ');
appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append(' ').append(itf ? "itf" : "");
buf.append('\n');
text.add(buf.toString());
}
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java Wed Nov 06 13:25:24 2013 -0800
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java Wed Nov 06 11:22:15 2013 -0800
@@ -176,11 +176,31 @@
super.visitFieldInsn(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;
+ }
p.visitMethodInsn(opcode, owner, name, desc);
- super.visitMethodInsn(opcode, owner, name, desc);
+ if (mv != null) {
+ mv.visitMethodInsn(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;
+ }
+ p.visitMethodInsn(opcode, owner, name, desc, itf);
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
}
@Override
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt Wed Nov 06 13:25:24 2013 -0800
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt Wed Nov 06 11:22:15 2013 -0800
@@ -1,12 +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
+Working Copy Root Path: /hudson/jobs/objectweb-pull/workspace/ASM_5_0_BETA
+URL: svn://svn.forge.objectweb.org/svnroot/asm/trunk/asm
Repository Root: svn://svn.forge.objectweb.org/svnroot/asm
Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9
-Revision: 1681
+Revision: 1700
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)
+Last Changed Author: ebruneton
+Last Changed Rev: 1700
+Last Changed Date: 2013-10-29 20:22:52 +0100 (Tue, 29 Oct 2013)