# HG changeset patch
# Parent 9f3a25de641274bea7e6ab26a784b37c3ae84177
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java
@@ -70,7 +70,7 @@
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
@@ -85,7 +85,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public AnnotationVisitor(final int api) {
this(api, null);
@@ -96,13 +96,13 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param av
* the annotation visitor to which this visitor must delegate
* method calls. May be null.
*/
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
- if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
@@ -118,7 +118,7 @@
* the actual value, whose type must be {@link Byte},
* {@link Boolean}, {@link Character}, {@link Short},
* {@link Integer} , {@link Long}, {@link Float}, {@link Double},
- * {@link String} or {@link Type} or OBJECT or ARRAY sort. This
+ * {@link String} or {@link Type} of OBJECT or ARRAY sort. This
* value can also be an array of byte, boolean, short, char, int,
* long, float or double values (this is equivalent to using
* {@link #visitArray visitArray} and visiting each array element
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java
@@ -133,7 +133,7 @@
*/
AnnotationWriter(final ClassWriter cw, final boolean named,
final ByteVector bv, final ByteVector parent, final int offset) {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM6);
this.cw = cw;
this.named = named;
this.bv = bv;
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java
@@ -134,6 +134,21 @@
public static final int EXPAND_FRAMES = 8;
/**
+ * Flag to expand the ASM pseudo instructions into an equivalent sequence of
+ * standard bytecode instructions. When resolving a forward jump it may
+ * happen that the signed 2 bytes offset reserved for it is not sufficient
+ * to store the bytecode offset. In this case the jump instruction is
+ * replaced with a temporary ASM pseudo instruction using an unsigned 2
+ * bytes offset (see Label#resolve). This internal flag is used to re-read
+ * classes containing such instructions, in order to replace them with
+ * standard instructions. In addition, when this flag is used, GOTO_W and
+ * JSR_W are not converted into GOTO and JSR, to make sure that
+ * infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
+ * converted back to a GOTO_W in ClassWriter cannot occur.
+ */
+ static final int EXPAND_ASM_INSNS = 256;
+
+ /**
* The class to be parsed. The content of this array must not be
* modified. This field is intended for {@link Attribute} sub classes, and
* is normally not needed by class generators or adapters.
@@ -234,6 +249,8 @@
// case ClassWriter.CLASS:
// case ClassWriter.STR:
// case ClassWriter.MTYPE
+ // case ClassWriter.PACKAGE:
+ // case ClassWriter.MODULE:
default:
size = 3;
break;
@@ -377,7 +394,9 @@
break;
// case ClassWriter.STR:
// case ClassWriter.CLASS:
- // case ClassWriter.MTYPE
+ // case ClassWriter.MTYPE:
+ // case ClassWriter.MODULE:
+ // case ClassWriter.PACKAGE:
default:
item.set(tag, readUTF8(index, buf), null, null);
break;
@@ -584,11 +603,14 @@
String enclosingOwner = null;
String enclosingName = null;
String enclosingDesc = null;
+ String moduleMainClass = null;
int anns = 0;
int ianns = 0;
int tanns = 0;
int itanns = 0;
int innerClasses = 0;
+ int module = 0;
+ int packages = 0;
Attribute attributes = null;
u = getAttributes();
@@ -629,6 +651,12 @@
} else if (ANNOTATIONS
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8;
+ } else if ("Module".equals(attrName)) {
+ module = u + 8;
+ } else if ("ModuleMainClass".equals(attrName)) {
+ moduleMainClass = readClass(u + 8, c);
+ } else if ("ModulePackages".equals(attrName)) {
+ packages = u + 10;
} else if ("BootstrapMethods".equals(attrName)) {
int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
@@ -657,6 +685,12 @@
classVisitor.visitSource(sourceFile, sourceDebug);
}
+ // visits the module info and associated attributes
+ if (module != 0) {
+ readModule(classVisitor, context, module,
+ moduleMainClass, packages);
+ }
+
// visits the outer class
if (enclosingOwner != null) {
classVisitor.visitOuterClass(enclosingOwner, enclosingName,
@@ -727,6 +761,120 @@
}
/**
+ * Reads the module attribute and visit it.
+ *
+ * @param classVisitor
+ * the current class visitor
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * start offset of the module attribute in the class file.
+ * @param mainClass
+ * name of the main class of a module or null.
+ * @param packages
+ * start offset of the concealed package attribute.
+ */
+ private void readModule(final ClassVisitor classVisitor,
+ final Context context, int u,
+ final String mainClass, int packages) {
+
+ char[] buffer = context.buffer;
+
+ // reads module name, flags and version
+ String name = readModule(u, buffer);
+ int flags = readUnsignedShort(u + 2);
+ String version = readUTF8(u + 4, buffer);
+ u += 6;
+
+ ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
+ if (mv == null) {
+ return;
+ }
+
+ // module attributes (main class, packages)
+ if (mainClass != null) {
+ mv.visitMainClass(mainClass);
+ }
+
+ if (packages != 0) {
+ for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
+ String packaze = readPackage(packages, buffer);
+ mv.visitPackage(packaze);
+ packages += 2;
+ }
+ }
+
+ // reads requires
+ u += 2;
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ String module = readModule(u, buffer);
+ int access = readUnsignedShort(u + 2);
+ String requireVersion = readUTF8(u + 4, buffer);
+ mv.visitRequire(module, access, requireVersion);
+ u += 6;
+ }
+
+ // reads exports
+ u += 2;
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ String export = readPackage(u, buffer);
+ int access = readUnsignedShort(u + 2);
+ int exportToCount = readUnsignedShort(u + 4);
+ u += 6;
+ String[] tos = null;
+ if (exportToCount != 0) {
+ tos = new String[exportToCount];
+ for (int j = 0; j < tos.length; ++j) {
+ tos[j] = readModule(u, buffer);
+ u += 2;
+ }
+ }
+ mv.visitExport(export, access, tos);
+ }
+
+ // reads opens
+ u += 2;
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ String open = readPackage(u, buffer);
+ int access = readUnsignedShort(u + 2);
+ int openToCount = readUnsignedShort(u + 4);
+ u += 6;
+ String[] tos = null;
+ if (openToCount != 0) {
+ tos = new String[openToCount];
+ for (int j = 0; j < tos.length; ++j) {
+ tos[j] = readModule(u, buffer);
+ u += 2;
+ }
+ }
+ mv.visitOpen(open, access, tos);
+ }
+
+ // read uses
+ u += 2;
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ mv.visitUse(readClass(u, buffer));
+ u += 2;
+ }
+
+ // read provides
+ u += 2;
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ String service = readClass(u, buffer);
+ int provideWithCount = readUnsignedShort(u + 2);
+ u += 4;
+ String[] withs = new String[provideWithCount];
+ for (int j = 0; j < withs.length; ++j) {
+ withs[j] = readClass(u, buffer);
+ u += 2;
+ }
+ mv.visitProvide(service, withs);
+ }
+
+ mv.visitEnd();
+ }
+
+ /**
* Reads a field and makes the given visitor visit it.
*
* @param classVisitor
@@ -1088,7 +1236,12 @@
readLabel(offset + readShort(u + 1), labels);
u += 3;
break;
+ case ClassWriter.ASM_LABEL_INSN:
+ readLabel(offset + readUnsignedShort(u + 1), labels);
+ u += 3;
+ break;
case ClassWriter.LABELW_INSN:
+ case ClassWriter.ASM_LABELW_INSN:
readLabel(offset + readInt(u + 1), labels);
u += 5;
break;
@@ -1312,8 +1465,25 @@
}
}
}
+ if ((context.flags & EXPAND_ASM_INSNS) != 0
+ && (context.flags & EXPAND_FRAMES) != 0) {
+ // Expanding the ASM pseudo instructions can introduce F_INSERT
+ // frames, even if the method does not currently have any frame.
+ // Also these inserted frames must be computed by simulating the
+ // effect of the bytecode instructions one by one, starting from the
+ // first one and the last existing frame (or the implicit first
+ // one). Finally, due to the way MethodWriter computes this (with
+ // the compute = INSERTED_FRAMES option), MethodWriter needs to know
+ // maxLocals before the first instruction is visited. For all these
+ // reasons we always visit the implicit first frame in this case
+ // (passing only maxLocals - the rest can be and is computed in
+ // MethodWriter).
+ mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
+ }
// visits the instructions
+ int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
+ boolean insertFrame = false;
u = codeStart;
while (u < codeEnd) {
int offset = u - codeStart;
@@ -1346,6 +1516,9 @@
mv.visitFrame(frame.mode, frame.localDiff, frame.local,
frame.stackCount, frame.stack);
}
+ // if there is already a frame for this offset, there is no
+ // need to insert a new one.
+ insertFrame = false;
}
if (frameCount > 0) {
stackMap = readFrame(stackMap, zip, unzip, frame);
@@ -1354,6 +1527,13 @@
frame = null;
}
}
+ // inserts a frame for this offset, if requested by setting
+ // insertFrame to true during the previous iteration. The actual
+ // frame content will be computed in MethodWriter.
+ if (FRAMES && insertFrame) {
+ mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
+ insertFrame = false;
+ }
// visits the instruction at this offset
int opcode = b[u] & 0xFF;
@@ -1378,9 +1558,47 @@
u += 3;
break;
case ClassWriter.LABELW_INSN:
- mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);
+ mv.visitJumpInsn(opcode + opcodeDelta, labels[offset
+ + readInt(u + 1)]);
u += 5;
break;
+ case ClassWriter.ASM_LABEL_INSN: {
+ // changes temporary opcodes 202 to 217 (inclusive), 218
+ // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // IFNONNULL
+ opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+ Label target = labels[offset + readUnsignedShort(u + 1)];
+ // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
+ // with IFNOTxxx GOTO_W L:..., where IFNOTxxx is
+ // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
+ // and where designates the instruction just after
+ // the GOTO_W.
+ if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
+ mv.visitJumpInsn(opcode + 33, target);
+ } else {
+ opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
+ : opcode ^ 1;
+ Label endif = readLabel(offset + 3, labels);
+ mv.visitJumpInsn(opcode, endif);
+ mv.visitJumpInsn(200, target); // GOTO_W
+ // endif designates the instruction just after GOTO_W,
+ // and is visited as part of the next instruction. Since
+ // it is a jump target, we need to insert a frame here.
+ insertFrame = true;
+ }
+ u += 3;
+ break;
+ }
+ case ClassWriter.ASM_LABELW_INSN: {
+ // replaces the pseudo GOTO_W instruction with a real one.
+ mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
+ // The instruction just after is a jump target (because pseudo
+ // GOTO_W are used in patterns IFNOTxxx GOTO_W L:...,
+ // see MethodWriter), so we need to insert a frame here.
+ insertFrame = true;
+ u += 5;
+ break;
+ }
case ClassWriter.WIDE_INSN:
opcode = b[u + 1] & 0xFF;
if (opcode == Opcodes.IINC) {
@@ -2471,6 +2689,20 @@
}
/**
+ * Read a stringish constant item (CONSTANT_Class, CONSTANT_String,
+ * CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package
+ * @param index
+ * @param buf
+ * @return
+ */
+ private String readStringish(final int index, final char[] buf) {
+ // computes the start index of the item in b
+ // and reads the CONSTANT_Utf8 item designated by
+ // the first two bytes of this item
+ return readUTF8(items[readUnsignedShort(index)], buf);
+ }
+
+ /**
* Reads a class constant pool item in {@link #b b}. This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.
@@ -2484,44 +2716,41 @@
* @return the String corresponding to the specified class item.
*/
public String readClass(final int index, final char[] buf) {
- // computes the start index of the CONSTANT_Class item in b
- // and reads the CONSTANT_Utf8 item designated by
- // the first two bytes of this CONSTANT_Class item
- return readUTF8(items[readUnsignedShort(index)], buf);
+ return readStringish(index, buf);
}
/**
- * Reads a CONSTANT_Module_info item in {@code b}. This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.
+ * Reads a module constant pool item in {@link #b b}. This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.
*
- * @param index
- * the start index of an unsigned short value in {@link #b b},
- * whose value is the index of a module constant pool item.
- * @param buf
- * buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
+ * @param index
+ * the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of a module constant pool item.
+ * @param buf
+ * buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified module item.
*/
- public String readModule(int index, char[] buf) {
- return readUTF8(items[readUnsignedShort(index)], buf);
+ public String readModule(final int index, final char[] buf) {
+ return readStringish(index, buf);
}
/**
- * Reads a CONSTANT_Package_info item in {@code b}. This method is
- * intended for {@link Attribute} sub slasses, and is normally not needed
- * by class generators or adapters.
+ * Reads a module constant pool item in {@link #b b}. This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.
*
- * @param index
- * the start index of an unsigned short value in {@link #b b},
- * whose value is the index of a package constant pool item.
- * @param buf
- * buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the String corresponding to the specified package item.
+ * @param index
+ * the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of a module constant pool item.
+ * @param buf
+ * buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified module item.
*/
- public String readPackage(int index, char[] buf) {
- return readUTF8(items[readUnsignedShort(index)], buf);
+ public String readPackage(final int index, final char[] buf) {
+ return readStringish(index, buf);
}
/**
@@ -2550,8 +2779,6 @@
case ClassWriter.DOUBLE:
return Double.longBitsToDouble(readLong(index));
case ClassWriter.CLASS:
- case ClassWriter.MODULE:
- case ClassWriter.PACKAGE:
return Type.getObjectType(readUTF8(index, buf));
case ClassWriter.STR:
return readUTF8(index, buf);
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java
@@ -61,7 +61,7 @@
/**
* A visitor to visit a Java class. The methods of this class must be called in
* the following order: visit [ visitSource ] [
- * visitOuterClass ] ( visitAnnotation |
+ * visitModule ][ visitOuterClass ] ( visitAnnotation |
* visitTypeAnnotation | visitAttribute )* (
* visitInnerClass | visitField | visitMethod )*
* visitEnd.
@@ -72,7 +72,7 @@
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
@@ -87,7 +87,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public ClassVisitor(final int api) {
this(api, null);
@@ -98,13 +98,13 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param cv
* the class visitor to which this visitor must delegate method
* calls. May be null.
*/
public ClassVisitor(final int api, final ClassVisitor cv) {
- if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
@@ -161,6 +161,28 @@
}
/**
+ * Visit the module corresponding to the class.
+ * @param name
+ * module name
+ * @param access
+ * module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
+ * and {@code ACC_MANDATED}.
+ * @param version
+ * module version or null.
+ * @return a visitor to visit the module values, or null if
+ * this visitor is not interested in visiting this module.
+ */
+ public ModuleVisitor visitModule(String name, int access, String version) {
+ if (api < Opcodes.ASM6) {
+ throw new RuntimeException();
+ }
+ if (cv != null) {
+ return cv.visitModule(name, access, version);
+ }
+ return null;
+ }
+
+ /**
* Visits the enclosing class of the class. This method must be called only
* if the class has an enclosing class.
*
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
@@ -87,8 +87,8 @@
* {@link MethodVisitor#visitFrame} method are ignored, and the stack map
* frames are recomputed from the methods bytecode. The arguments of the
* {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
- * recomputed from the bytecode. In other words, computeFrames implies
- * computeMaxs.
+ * recomputed from the bytecode. In other words, COMPUTE_FRAMES implies
+ * COMPUTE_MAXS.
*
* @see #ClassWriter(int)
*/
@@ -197,6 +197,27 @@
static final int WIDE_INSN = 17;
/**
+ * The type of the ASM pseudo instructions with an unsigned 2 bytes offset
+ * label (see Label#resolve).
+ */
+ static final int ASM_LABEL_INSN = 18;
+
+ /**
+ * The type of the ASM pseudo instructions with a 4 bytes offset label.
+ */
+ static final int ASM_LABELW_INSN = 19;
+
+ /**
+ * Represents a frame inserted between already existing frames. This kind of
+ * frame can only be used if the frame content can be computed from the
+ * previous existing frame and from the instructions between this existing
+ * frame and the inserted one, without any knowledge of the type hierarchy.
+ * This kind of frame is only used when an unconditional jump is inserted in
+ * a method while expanding an ASM pseudo instruction (see ClassReader).
+ */
+ static final int F_INSERT = 256;
+
+ /**
* The instruction types of all JVM opcodes.
*/
static final byte[] TYPE;
@@ -284,7 +305,7 @@
/**
* The base value for all CONSTANT_MethodHandle constant pool items.
* Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
- * different items.
+ * different items (from 21 to 29).
*/
static final int HANDLE_BASE = 20;
@@ -434,6 +455,11 @@
private ByteVector sourceDebug;
/**
+ * The module attribute of this class.
+ */
+ private ModuleWriter moduleWriter;
+
+ /**
* The constant pool item that contains the name of the enclosing class of
* this class.
*/
@@ -523,25 +549,19 @@
MethodWriter lastMethod;
/**
- * true if the maximum stack size and number of local variables
- * must be automatically computed.
+ * Indicates what must be automatically computed.
+ *
+ * @see MethodWriter#compute
*/
- private boolean computeMaxs;
+ private int compute;
/**
- * true if the stack map frames must be recomputed from scratch.
+ * true if some methods have wide forward jumps using ASM pseudo
+ * instructions, which need to be expanded into sequences of standard
+ * bytecode instructions. In this case the class is re-read and re-written
+ * with a ClassReader -> ClassWriter chain to perform this transformation.
*/
- private boolean computeFrames;
-
- /**
- * true if the stack map tables of this class are invalid. The
- * {@link MethodWriter#resizeInstructions} method cannot transform existing
- * stack map tables, and so produces potentially invalid classes when it is
- * executed. In this case the class is reread and rewritten with the
- * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
- * stack map tables when this option is used).
- */
- boolean invalidFrames;
+ boolean hasAsmInsns;
// ------------------------------------------------------------------------
// Static initializer
@@ -552,11 +572,11 @@
*/
static {
int i;
- byte[] b = new byte[220];
+ byte[] b = new byte[221];
String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
+ "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
- + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ";
+ + "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST";
for (i = 0; i < b.length; ++i) {
b[i] = (byte) (s.charAt(i) - 'A');
}
@@ -610,8 +630,9 @@
// // temporary opcodes used internally by ASM - see Label and
// MethodWriter
// for (i = 202; i < 220; ++i) {
- // b[i] = LABEL_INSN;
+ // b[i] = ASM_LABEL_INSN;
// }
+ // b[220] = ASM_LABELW_INSN;
//
// // LDC(_W) instructions
// b[Constants.LDC] = LDC_INSN;
@@ -644,7 +665,7 @@
* {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final int flags) {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM6);
index = 1;
pool = new ByteVector();
items = new Item[256];
@@ -653,8 +674,9 @@
key2 = new Item();
key3 = new Item();
key4 = new Item();
- this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
- this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
+ this.compute = (flags & COMPUTE_FRAMES) != 0 ? MethodWriter.FRAMES
+ : ((flags & COMPUTE_MAXS) != 0 ? MethodWriter.MAXS
+ : MethodWriter.NOTHING);
}
/**
@@ -684,9 +706,9 @@
* @param flags
* option flags that can be used to modify the default behavior
* of this class. These option flags do not affect methods
- * that are copied as is in the new class. This means that the
- * maximum stack size nor the stack frames will be computed for
- * these methods. See {@link #COMPUTE_MAXS},
+ * that are copied as is in the new class. This means that
+ * neither the maximum stack size nor the stack frames will be
+ * computed for these methods. See {@link #COMPUTE_MAXS},
* {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final ClassReader classReader, final int flags) {
@@ -705,7 +727,7 @@
final String[] interfaces) {
this.version = version;
this.access = access;
- this.name = (name == null) ? 0 : newClass(name);
+ this.name = newClass(name);
thisName = name;
if (ClassReader.SIGNATURES && signature != null) {
this.signature = newUTF8(signature);
@@ -732,6 +754,14 @@
}
@Override
+ public final ModuleVisitor visitModule(final String name,
+ final int access, final String version) {
+ return moduleWriter = new ModuleWriter(this,
+ newModule(name), access,
+ version == null ? 0 : newUTF8(version));
+ }
+
+ @Override
public final void visitOuterClass(final String owner, final String name,
final String desc) {
enclosingMethodOwner = newClass(owner);
@@ -805,7 +835,7 @@
// and equality tests). If so we store the index of this inner class
// entry (plus one) in intVal. This hack allows duplicate detection in
// O(1) time.
- Item nameItem = newClassItem(name);
+ Item nameItem = newStringishItem(CLASS, name);
if (nameItem.intVal == 0) {
++innerClassesCount;
innerClasses.putShort(nameItem.index);
@@ -830,7 +860,7 @@
public final MethodVisitor visitMethod(final int access, final String name,
final String desc, final String signature, final String[] exceptions) {
return new MethodWriter(this, access, name, desc, signature,
- exceptions, computeMaxs, computeFrames);
+ exceptions, compute);
}
@Override
@@ -932,6 +962,11 @@
size += 8 + itanns.getSize();
newUTF8("RuntimeInvisibleTypeAnnotations");
}
+ if (moduleWriter != null) {
+ attributeCount += 1 + moduleWriter.attributeCount;
+ size += 6 + moduleWriter.size + moduleWriter.attributesSize;
+ newUTF8("Module");
+ }
if (attrs != null) {
attributeCount += attrs.getCount();
size += attrs.getSize(this, null, 0, -1, -1);
@@ -979,6 +1014,11 @@
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
out.putByteArray(sourceDebug.data, 0, len);
}
+ if (moduleWriter != null) {
+ out.putShort(newUTF8("Module"));
+ moduleWriter.put(out);
+ moduleWriter.putAttributes(out);
+ }
if (enclosingMethodOwner != 0) {
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
@@ -1016,22 +1056,29 @@
if (attrs != null) {
attrs.put(this, null, 0, -1, -1, out);
}
- if (invalidFrames) {
+ if (hasAsmInsns) {
+ boolean hasFrames = false;
+ mb = firstMethod;
+ while (mb != null) {
+ hasFrames |= mb.frameCount > 0;
+ mb = (MethodWriter) mb.mv;
+ }
anns = null;
ianns = null;
attrs = null;
+ moduleWriter = 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);
+ compute =
+ hasFrames ? MethodWriter.INSERTED_FRAMES : MethodWriter.NOTHING;
+ hasAsmInsns = false;
+ new ClassReader(out.data).accept(this,
+ (hasFrames ? ClassReader.EXPAND_FRAMES : 0)
+ | ClassReader.EXPAND_ASM_INSNS);
return toByteArray();
}
return out.data;
@@ -1078,16 +1125,16 @@
double val = ((Double) cst).doubleValue();
return newDouble(val);
} else if (cst instanceof String) {
- return newString((String) cst);
+ return newStringishItem(STR, (String) cst);
} else if (cst instanceof Type) {
Type t = (Type) cst;
int s = t.getSort();
if (s == Type.OBJECT) {
- return newClassItem(t.getInternalName());
+ return newStringishItem(CLASS, t.getInternalName());
} else if (s == Type.METHOD) {
- return newMethodTypeItem(t.getDescriptor());
+ return newStringishItem(MTYPE, t.getDescriptor());
} else { // s == primitive type or array
- return newClassItem(t.getDescriptor());
+ return newStringishItem(CLASS, t.getDescriptor());
}
} else if (cst instanceof Handle) {
Handle h = (Handle) cst;
@@ -1136,20 +1183,21 @@
}
/**
- * Adds a class reference to the constant pool of the class being build.
+ * Adds a string reference, a class reference, a method type, a module
+ * or a package to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
- * This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.
*
+ * @param type
+ * a type among STR, CLASS, MTYPE, MODULE or PACKAGE
* @param value
- * the internal name of the class.
- * @return a new or already existing class reference item.
+ * string value of the reference.
+ * @return a new or already existing reference item.
*/
- Item newClassItem(final String value) {
- key2.set(CLASS, value, null, null);
+ Item newStringishItem(final int type, final String value) {
+ key2.set(type, value, null, null);
Item result = get(key2);
if (result == null) {
- pool.put12(CLASS, newUTF8(value));
+ pool.put12(type, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
@@ -1167,72 +1215,7 @@
* @return the index of a new or already existing class reference item.
*/
public int newClass(final String value) {
- return newClassItem(value).index;
- }
-
- /**
- * Adds a module name to the constant pool.
- *
- * Does nothing if the constant pool already contains a similar item.
- * This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.
- *
- * @param value
- * the module name
- * @return the index of a new or already existing module reference item.
- */
- public int newModule(String value) {
- key2.set(MODULE, value, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(MODULE, newUTF8(value));
- result = new Item(index++, key2);
- put(result);
- }
- return result.index;
- }
-
- /**
- * Adds a package name to the constant pool.
- *
- * Does nothing if the constant pool already contains a similar item.
- * This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.
- *
- * @param value
- * the internal name of the package.
- * @return the index of a new or already existing package reference item.
- */
- public int newPackage(String value) {
- key2.set(PACKAGE, value, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(PACKAGE, newUTF8(value));
- result = new Item(index++, key2);
- put(result);
- }
- return result.index;
- }
-
- /**
- * Adds a method type reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.
- *
- * @param methodDesc
- * method descriptor of the method type.
- * @return a new or already existing method type reference item.
- */
- Item newMethodTypeItem(final String methodDesc) {
- key2.set(MTYPE, methodDesc, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(MTYPE, newUTF8(methodDesc));
- result = new Item(index++, key2);
- put(result);
- }
- return result;
+ return newStringishItem(CLASS, value).index;
}
/**
@@ -1247,7 +1230,37 @@
* item.
*/
public int newMethodType(final String methodDesc) {
- return newMethodTypeItem(methodDesc).index;
+ return newStringishItem(MTYPE, methodDesc).index;
+ }
+
+ /**
+ * Adds a module reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.
+ *
+ * @param moduleName
+ * name of the module.
+ * @return the index of a new or already existing module reference
+ * item.
+ */
+ public int newModule(final String moduleName) {
+ return newStringishItem(MODULE, moduleName).index;
+ }
+
+ /**
+ * Adds a package reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.
+ *
+ * @param packageName
+ * name of the package in its internal form.
+ * @return the index of a new or already existing module reference
+ * item.
+ */
+ public int newPackage(final String packageName) {
+ return newStringishItem(PACKAGE, packageName).index;
}
/**
@@ -1629,25 +1642,6 @@
}
/**
- * Adds a string to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value
- * the String value.
- * @return a new or already existing string item.
- */
- private Item newString(final String value) {
- key2.set(STR, value, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(STR, newUTF8(value));
- result = new Item(index++, key2);
- put(result);
- }
- return result;
- }
-
- /**
* Adds a name and type to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item. This
* method is intended for {@link Attribute} sub classes, and is normally not
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/CurrentFrame.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/CurrentFrame.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/CurrentFrame.java
@@ -0,0 +1,85 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * Information about the input stack map frame at the "current" instruction of a
+ * method. This is implemented as a Frame subclass for a "basic block"
+ * containing only one instruction.
+ *
+ * @author Eric Bruneton
+ */
+class CurrentFrame extends Frame {
+
+ /**
+ * Sets this CurrentFrame to the input stack map frame of the next "current"
+ * instruction, i.e. the instruction just after the given one. It is assumed
+ * that the value of this object when this method is called is the stack map
+ * frame status just before the given instruction is executed.
+ */
+ @Override
+ void execute(int opcode, int arg, ClassWriter cw, Item item) {
+ super.execute(opcode, arg, cw, item);
+ Frame successor = new Frame();
+ merge(cw, successor, 0);
+ set(successor);
+ owner.inputStackTop = 0;
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java
@@ -69,7 +69,7 @@
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
@@ -84,7 +84,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public FieldVisitor(final int api) {
this(api, null);
@@ -95,13 +95,13 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param fv
* the field visitor to which this visitor must delegate method
* calls. May be null.
*/
public FieldVisitor(final int api, final FieldVisitor fv) {
- if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java
@@ -147,7 +147,7 @@
*/
FieldWriter(final ClassWriter cw, final int access, final String name,
final String desc, final String signature, final Object value) {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM6);
if (cw.firstField == null) {
cw.firstField = this;
} else {
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java
@@ -63,7 +63,7 @@
*
* @author Eric Bruneton
*/
-final class Frame {
+class Frame {
/*
* Frames are computed in a two steps process: during the visit of each
@@ -525,7 +525,7 @@
* When the stack map frames are completely computed, this field is the
* actual number of types in {@link #outputStack}.
*/
- private int outputStackTop;
+ int outputStackTop;
/**
* Number of types that are initialized in the basic block.
@@ -550,6 +550,110 @@
private int[] initializations;
/**
+ * Sets this frame to the given value.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param nLocal
+ * the number of local variables.
+ * @param local
+ * the local variable types. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+ * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
+ * represented by a single element). Reference types are
+ * represented by String objects (representing internal names),
+ * and uninitialized types by Label objects (this label
+ * designates the NEW instruction that created this uninitialized
+ * value).
+ * @param nStack
+ * the number of operand stack elements.
+ * @param stack
+ * the operand stack types (same format as the "local" array).
+ */
+ final void set(ClassWriter cw, final int nLocal, final Object[] local,
+ final int nStack, final Object[] stack) {
+ int i = convert(cw, nLocal, local, inputLocals);
+ while (i < local.length) {
+ inputLocals[i++] = TOP;
+ }
+ int nStackTop = 0;
+ for (int j = 0; j < nStack; ++j) {
+ if (stack[j] == Opcodes.LONG || stack[j] == Opcodes.DOUBLE) {
+ ++nStackTop;
+ }
+ }
+ inputStack = new int[nStack + nStackTop];
+ convert(cw, nStack, stack, inputStack);
+ outputStackTop = 0;
+ initializationCount = 0;
+ }
+
+ /**
+ * Converts types from the MethodWriter.visitFrame() format to the Frame
+ * format.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param nInput
+ * the number of types to convert.
+ * @param input
+ * the types to convert. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+ * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
+ * represented by a single element). Reference types are
+ * represented by String objects (representing internal names),
+ * and uninitialized types by Label objects (this label
+ * designates the NEW instruction that created this uninitialized
+ * value).
+ * @param output
+ * where to store the converted types.
+ * @return the number of output elements.
+ */
+ private static int convert(ClassWriter cw, int nInput, Object[] input,
+ int[] output) {
+ int i = 0;
+ for (int j = 0; j < nInput; ++j) {
+ if (input[j] instanceof Integer) {
+ output[i++] = BASE | ((Integer) input[j]).intValue();
+ if (input[j] == Opcodes.LONG || input[j] == Opcodes.DOUBLE) {
+ output[i++] = TOP;
+ }
+ } else if (input[j] instanceof String) {
+ output[i++] = type(cw, Type.getObjectType((String) input[j])
+ .getDescriptor());
+ } else {
+ output[i++] = UNINITIALIZED
+ | cw.addUninitializedType("",
+ ((Label) input[j]).position);
+ }
+ }
+ return i;
+ }
+
+ /**
+ * Sets this frame to the value of the given frame. WARNING: after this
+ * method is called the two frames share the same data structures. It is
+ * recommended to discard the given frame f to avoid unexpected side
+ * effects.
+ *
+ * @param f
+ * The new frame value.
+ */
+ final void set(final Frame f) {
+ inputLocals = f.inputLocals;
+ inputStack = f.inputStack;
+ outputLocals = f.outputLocals;
+ outputStack = f.outputStack;
+ outputStackTop = f.outputStackTop;
+ initializationCount = f.initializationCount;
+ initializations = f.initializations;
+ }
+
+ /**
* Returns the output frame local variable type at the given index.
*
* @param local
@@ -614,7 +718,7 @@
}
// pushes the type on the output stack
outputStack[outputStackTop++] = type;
- // updates the maximun height reached by the output stack, if needed
+ // updates the maximum height reached by the output stack, if needed
int top = owner.inputStackTop + outputStackTop;
if (top > owner.outputStackMax) {
owner.outputStackMax = top;
@@ -650,7 +754,7 @@
* a type descriptor.
* @return the int encoding of the given type.
*/
- private static int type(final ClassWriter cw, final String desc) {
+ static int type(final ClassWriter cw, final String desc) {
String t;
int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
switch (desc.charAt(index)) {
@@ -838,7 +942,7 @@
* @param maxLocals
* the maximum number of local variables of this method.
*/
- void initInputFrame(final ClassWriter cw, final int access,
+ final void initInputFrame(final ClassWriter cw, final int access,
final Type[] args, final int maxLocals) {
inputLocals = new int[maxLocals];
inputStack = new int[0];
@@ -1312,7 +1416,7 @@
* @return true if the input frame of the given label has been
* changed by this operation.
*/
- boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
+ final boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
boolean changed = false;
int i, s, dim, kind, t;
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Item.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Item.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Item.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Item.java
@@ -80,6 +80,7 @@
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
+ * {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE},
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
*
* MethodHandle constant 9 variations are stored using a range of 9 values
@@ -239,12 +240,12 @@
this.strVal3 = strVal3;
switch (type) {
case ClassWriter.CLASS:
- case ClassWriter.MODULE:
- case ClassWriter.PACKAGE:
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.MTYPE:
+ case ClassWriter.MODULE:
+ case ClassWriter.PACKAGE:
case ClassWriter.TYPE_NORMAL:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
return;
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java
@@ -389,13 +389,12 @@
* the position of this label in the bytecode.
* @param data
* the bytecode of the method.
- * @return true if a blank that was left for this label was to
+ * @return true if a blank that was left for this label was too
* small to store the offset. In such a case the corresponding jump
* instruction is replaced with a pseudo instruction (using unused
* opcodes) using an unsigned two bytes offset. These pseudo
- * instructions will need to be replaced with true instructions with
- * wider offsets (4 bytes instead of 2). This is done in
- * {@link MethodWriter#resizeInstructions}.
+ * instructions will be replaced with standard bytecode instructions
+ * with wider offsets (4 bytes instead of 2), in ClassReader.
* @throws IllegalArgumentException
* if this label has already been resolved, or if it has not
* been created by the given code writer.
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java
@@ -86,7 +86,7 @@
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
@@ -101,7 +101,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public MethodVisitor(final int api) {
this(api, null);
@@ -112,13 +112,13 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv
* the method visitor to which this visitor must delegate method
* calls. May be null.
*/
public MethodVisitor(final int api, final MethodVisitor mv) {
- if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java
@@ -128,7 +128,19 @@
*
* @see #compute
*/
- private static final int FRAMES = 0;
+ static final int FRAMES = 0;
+
+ /**
+ * Indicates that the stack map frames of type F_INSERT must be computed.
+ * The other frames are not (re)computed. They should all be of type F_NEW
+ * and should be sufficient to compute the content of the F_INSERT frames,
+ * together with the bytecode instructions between a F_NEW and a F_INSERT
+ * frame - and without any knowledge of the type hierarchy (by definition of
+ * F_INSERT).
+ *
+ * @see #compute
+ */
+ static final int INSERTED_FRAMES = 1;
/**
* Indicates that the maximum stack size and number of local variables must
@@ -136,14 +148,14 @@
*
* @see #compute
*/
- private static final int MAXS = 1;
+ static final int MAXS = 2;
/**
* Indicates that nothing must be automatically computed.
*
* @see #compute
*/
- private static final int NOTHING = 2;
+ static final int NOTHING = 3;
/**
* The class writer to which this method must be added.
@@ -277,7 +289,7 @@
/**
* Number of stack map frames in the StackMapTable attribute.
*/
- private int frameCount;
+ int frameCount;
/**
* The StackMapTable attribute.
@@ -384,11 +396,6 @@
private Attribute cattrs;
/**
- * Indicates if some jump instructions are too small and need to be resized.
- */
- private boolean resize;
-
- /**
* The number of subroutines in this method.
*/
private int subroutines;
@@ -409,6 +416,7 @@
* Indicates what must be automatically computed.
*
* @see #FRAMES
+ * @see #INSERTED_FRAMES
* @see #MAXS
* @see #NOTHING
*/
@@ -471,18 +479,13 @@
* @param exceptions
* the internal names of the method's exceptions. May be
* null.
- * @param computeMaxs
- * true if the maximum stack size and number of local
- * variables must be automatically computed.
- * @param computeFrames
- * true if the stack map tables must be recomputed from
- * scratch.
+ * @param compute
+ * Indicates what must be automatically computed (see #compute).
*/
MethodWriter(final ClassWriter cw, final int access, final String name,
final String desc, final String signature,
- final String[] exceptions, final boolean computeMaxs,
- final boolean computeFrames) {
- super(Opcodes.ASM5);
+ final String[] exceptions, final int compute) {
+ super(Opcodes.ASM6);
if (cw.firstMethod == null) {
cw.firstMethod = this;
} else {
@@ -507,8 +510,8 @@
this.exceptions[i] = cw.newClass(exceptions[i]);
}
}
- this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
- if (computeMaxs || computeFrames) {
+ this.compute = compute;
+ if (compute != NOTHING) {
// updates maxLocals
int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
if ((access & Opcodes.ACC_STATIC) != 0) {
@@ -643,7 +646,29 @@
return;
}
- if (type == Opcodes.F_NEW) {
+ if (compute == INSERTED_FRAMES) {
+ if (currentBlock.frame == null) {
+ // This should happen only once, for the implicit first frame
+ // (which is explicitly visited in ClassReader if the
+ // EXPAND_ASM_INSNS option is used).
+ currentBlock.frame = new CurrentFrame();
+ currentBlock.frame.owner = currentBlock;
+ currentBlock.frame.initInputFrame(cw, access,
+ Type.getArgumentTypes(descriptor), nLocal);
+ visitImplicitFirstFrame();
+ } else {
+ if (type == Opcodes.F_NEW) {
+ currentBlock.frame.set(cw, nLocal, local, nStack, stack);
+ } else {
+ // In this case type is equal to F_INSERT by hypothesis, and
+ // currentBlock.frame contains the stack map frame at the
+ // current instruction, computed from the last F_NEW frame
+ // and the bytecode instructions in between (via calls to
+ // CurrentFrame#execute).
+ }
+ visitFrame(currentBlock.frame);
+ }
+ } else if (type == Opcodes.F_NEW) {
if (previousFrame == null) {
visitImplicitFirstFrame();
}
@@ -651,10 +676,10 @@
int frameIndex = startFrame(code.length, nLocal, nStack);
for (int i = 0; i < nLocal; ++i) {
if (local[i] instanceof String) {
- frame[frameIndex++] = Frame.OBJECT
- | cw.addType((String) local[i]);
+ String desc = Type.getObjectType((String) local[i]).getDescriptor();
+ frame[frameIndex++] = Frame.type(cw, desc);
} else if (local[i] instanceof Integer) {
- frame[frameIndex++] = ((Integer) local[i]).intValue();
+ frame[frameIndex++] = Frame.BASE | ((Integer) local[i]).intValue();
} else {
frame[frameIndex++] = Frame.UNINITIALIZED
| cw.addUninitializedType("",
@@ -663,10 +688,10 @@
}
for (int i = 0; i < nStack; ++i) {
if (stack[i] instanceof String) {
- frame[frameIndex++] = Frame.OBJECT
- | cw.addType((String) stack[i]);
+ String desc = Type.getObjectType((String) stack[i]).getDescriptor();
+ frame[frameIndex++] = Frame.type(cw, desc);
} else if (stack[i] instanceof Integer) {
- frame[frameIndex++] = ((Integer) stack[i]).intValue();
+ frame[frameIndex++] = Frame.BASE | ((Integer) stack[i]).intValue();
} else {
frame[frameIndex++] = Frame.UNINITIALIZED
| cw.addUninitializedType("",
@@ -747,7 +772,7 @@
// update currentBlock
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(opcode, 0, null, null);
} else {
// updates current and max stack sizes
@@ -770,7 +795,7 @@
lastCodeOffset = code.length;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(opcode, operand, null, null);
} else if (opcode != Opcodes.NEWARRAY) {
// updates current and max stack sizes only for NEWARRAY
@@ -795,7 +820,7 @@
lastCodeOffset = code.length;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(opcode, var, null, null);
} else {
// updates current and max stack sizes
@@ -852,10 +877,10 @@
@Override
public void visitTypeInsn(final int opcode, final String type) {
lastCodeOffset = code.length;
- Item i = cw.newClassItem(type);
+ Item i = cw.newStringishItem(ClassWriter.CLASS, type);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(opcode, code.length, cw, i);
} else if (opcode == Opcodes.NEW) {
// updates current and max stack sizes only if opcode == NEW
@@ -878,7 +903,7 @@
Item i = cw.newFieldItem(owner, name, desc);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(opcode, 0, cw, i);
} else {
int size;
@@ -918,7 +943,7 @@
int argSize = i.intVal;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(opcode, 0, cw, i);
} else {
/*
@@ -970,7 +995,7 @@
int argSize = i.intVal;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i);
} else {
/*
@@ -1004,7 +1029,9 @@
}
@Override
- public void visitJumpInsn(final int opcode, final Label label) {
+ public void visitJumpInsn(int opcode, final Label label) {
+ boolean isWide = opcode >= 200; // GOTO_W
+ opcode = isWide ? opcode - 33 : opcode;
lastCodeOffset = code.length;
Label nextInsn = null;
// Label currentBlock = this.currentBlock;
@@ -1019,6 +1046,8 @@
// creates a Label for the next basic block
nextInsn = new Label();
}
+ } else if (compute == INSERTED_FRAMES) {
+ currentBlock.frame.execute(opcode, 0, null, null);
} else {
if (opcode == Opcodes.JSR) {
if ((label.status & Label.SUBROUTINE) == 0) {
@@ -1050,8 +1079,8 @@
/*
* case of a backward jump with an offset < -32768. In this case we
* automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
- * with IFNOTxxx GOTO_W , where IFNOTxxx is the
- * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where
+ * with IFNOTxxx GOTO_W L:..., where IFNOTxxx is the
+ * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where
* designates the instruction just after the GOTO_W.
*/
if (opcode == Opcodes.GOTO) {
@@ -1067,9 +1096,21 @@
code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
: opcode ^ 1);
code.putShort(8); // jump offset
- code.putByte(200); // GOTO_W
+ // ASM pseudo GOTO_W insn, see ClassReader. We don't use a real
+ // GOTO_W because we might need to insert a frame just after (as
+ // the target of the IFNOTxxx jump instruction).
+ code.putByte(220);
+ cw.hasAsmInsns = true;
}
label.put(this, code, code.length - 1, true);
+ } else if (isWide) {
+ /*
+ * case of a GOTO_W or JSR_W specified by the user (normally
+ * ClassReader when used to resize instructions). In this case we
+ * keep the original instruction.
+ */
+ code.putByte(opcode + 33);
+ label.put(this, code, code.length - 1, true);
} else {
/*
* case of a backward jump with an offset >= -32768, or of a forward
@@ -1097,7 +1138,7 @@
@Override
public void visitLabel(final Label label) {
// resolves previous forward references to label, if any
- resize |= label.resolve(this, code.length, code.data);
+ cw.hasAsmInsns |= label.resolve(this, code.length, code.data);
// updates currentBlock
if ((label.status & Label.DEBUG) != 0) {
return;
@@ -1130,6 +1171,18 @@
previousBlock.successor = label;
}
previousBlock = label;
+ } else if (compute == INSERTED_FRAMES) {
+ if (currentBlock == null) {
+ // This case should happen only once, for the visitLabel call in
+ // the constructor. Indeed, if compute is equal to
+ // INSERTED_FRAMES currentBlock can not be set back to null (see
+ // #noSuccessor).
+ currentBlock = label;
+ } else {
+ // Updates the frame owner so that a correct frame offset is
+ // computed in visitFrame(Frame).
+ currentBlock.frame.owner = label;
+ }
} else if (compute == MAXS) {
if (currentBlock != null) {
// ends current block (with one new successor)
@@ -1155,7 +1208,7 @@
Item i = cw.newConstItem(cst);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(Opcodes.LDC, 0, cw, i);
} else {
int size;
@@ -1187,7 +1240,7 @@
public void visitIincInsn(final int var, final int increment) {
lastCodeOffset = code.length;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(Opcodes.IINC, var, null, null);
}
}
@@ -1271,10 +1324,10 @@
@Override
public void visitMultiANewArrayInsn(final String desc, final int dims) {
lastCodeOffset = code.length;
- Item i = cw.newClassItem(desc);
+ Item i = cw.newStringishItem(ClassWriter.CLASS, desc);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
- if (compute == FRAMES) {
+ if (compute == FRAMES || compute == INSERTED_FRAMES) {
currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i);
} else {
// updates current stack size (max stack size unchanged because
@@ -1430,14 +1483,6 @@
@Override
public void visitMaxs(final int maxStack, final int maxLocals) {
- if (resize) {
- // replaces the temporary jump opcodes introduced by Label.resolve.
- if (ClassReader.RESIZE) {
- resizeInstructions();
- } else {
- throw new RuntimeException("Method code too large!");
- }
- }
if (ClassReader.FRAMES && compute == FRAMES) {
// completes the control flow graph with exception handler blocks
Handler handler = firstHandler;
@@ -1468,8 +1513,8 @@
// creates and visits the first (implicit) frame
Frame f = labels.frame;
- Type[] args = Type.getArgumentTypes(descriptor);
- f.initInputFrame(cw, access, args, this.maxLocals);
+ f.initInputFrame(cw, access, Type.getArgumentTypes(descriptor),
+ this.maxLocals);
visitFrame(f);
/*
@@ -1717,7 +1762,9 @@
} else {
currentBlock.outputStackMax = maxStackSize;
}
- currentBlock = null;
+ if (compute != INSERTED_FRAMES) {
+ currentBlock = null;
+ }
}
// ------------------------------------------------------------------------
@@ -1789,7 +1836,7 @@
if ((access & ACC_CONSTRUCTOR) == 0) {
frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName);
} else {
- frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS;
+ frame[frameIndex++] = Frame.UNINITIALIZED_THIS;
}
}
int i = 1;
@@ -1801,16 +1848,16 @@
case 'B':
case 'S':
case 'I':
- frame[frameIndex++] = 1; // Opcodes.INTEGER;
+ frame[frameIndex++] = Frame.INTEGER;
break;
case 'F':
- frame[frameIndex++] = 2; // Opcodes.FLOAT;
+ frame[frameIndex++] = Frame.FLOAT;
break;
case 'J':
- frame[frameIndex++] = 4; // Opcodes.LONG;
+ frame[frameIndex++] = Frame.LONG;
break;
case 'D':
- frame[frameIndex++] = 3; // Opcodes.DOUBLE;
+ frame[frameIndex++] = Frame.DOUBLE;
break;
case '[':
while (descriptor.charAt(i) == '[') {
@@ -1822,8 +1869,7 @@
++i;
}
}
- frame[frameIndex++] = Frame.OBJECT
- | cw.addType(descriptor.substring(j, ++i));
+ frame[frameIndex++] = Frame.type(cw, descriptor.substring(j, ++i));
break;
case 'L':
while (descriptor.charAt(i) != ';') {
@@ -2376,569 +2422,4 @@
attrs.put(cw, null, 0, -1, -1, out);
}
}
-
- // ------------------------------------------------------------------------
- // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
- // ------------------------------------------------------------------------
-
- /**
- * Resizes and replaces the temporary instructions inserted by
- * {@link Label#resolve} for wide forward jumps, while keeping jump offsets
- * and instruction addresses consistent. This may require to resize other
- * existing instructions, or even to introduce new instructions: for
- * example, increasing the size of an instruction by 2 at the middle of a
- * method can increases the offset of an IFEQ instruction from 32766 to
- * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
- * 32765. This, in turn, may require to increase the size of another jump
- * instruction, and so on... All these operations are handled automatically
- * by this method.
- *
- * This method must be called after all the method that is being built
- * has been visited. In particular, the {@link Label Label} objects used
- * to construct the method are no longer valid after this method has been
- * called.
- */
- private void resizeInstructions() {
- byte[] b = code.data; // bytecode of the method
- int u, v, label; // indexes in b
- int i, j; // loop indexes
- /*
- * 1st step: As explained above, resizing an instruction may require to
- * resize another one, which may require to resize yet another one, and
- * so on. The first step of the algorithm consists in finding all the
- * instructions that need to be resized, without modifying the code.
- * This is done by the following "fix point" algorithm:
- *
- * Parse the code to find the jump instructions whose offset will need
- * more than 2 bytes to be stored (the future offset is computed from
- * the current offset and from the number of bytes that will be inserted
- * or removed between the source and target instructions). For each such
- * instruction, adds an entry in (a copy of) the indexes and sizes
- * arrays (if this has not already been done in a previous iteration!).
- *
- * If at least one entry has been added during the previous step, go
- * back to the beginning, otherwise stop.
- *
- * In fact the real algorithm is complicated by the fact that the size
- * of TABLESWITCH and LOOKUPSWITCH instructions depends on their
- * position in the bytecode (because of padding). In order to ensure the
- * convergence of the algorithm, the number of bytes to be added or
- * removed from these instructions is over estimated during the previous
- * loop, and computed exactly only after the loop is finished (this
- * requires another pass to parse the bytecode of the method).
- */
- int[] allIndexes = new int[0]; // copy of indexes
- int[] allSizes = new int[0]; // copy of sizes
- boolean[] resize; // instructions to be resized
- int newOffset; // future offset of a jump instruction
-
- resize = new boolean[code.length];
-
- // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
- int state = 3;
- do {
- if (state == 3) {
- state = 2;
- }
- u = 0;
- while (u < b.length) {
- int opcode = b[u] & 0xFF; // opcode of current instruction
- int insert = 0; // bytes to be added after this instruction
-
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- if (opcode > 201) {
- // converts temporary opcodes 202 to 217, 218 and
- // 219 to IFEQ ... JSR (inclusive), IFNULL and
- // IFNONNULL
- opcode = opcode < 218 ? opcode - 49 : opcode - 20;
- label = u + readUnsignedShort(b, u + 1);
- } else {
- label = u + readShort(b, u + 1);
- }
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (newOffset < Short.MIN_VALUE
- || newOffset > Short.MAX_VALUE) {
- if (!resize[u]) {
- if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
- // two additional bytes will be required to
- // replace this GOTO or JSR instruction with
- // a GOTO_W or a JSR_W
- insert = 2;
- } else {
- // five additional bytes will be required to
- // replace this IFxxx instruction with
- // IFNOTxxx GOTO_W , where IFNOTxxx
- // is the "opposite" opcode of IFxxx (i.e.,
- // IFNE for IFEQ) and where designates
- // the instruction just after the GOTO_W.
- insert = 5;
- }
- resize[u] = true;
- }
- }
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- u += 5;
- break;
- case ClassWriter.TABL_INSN:
- if (state == 1) {
- // true number of bytes to be added (or removed)
- // from this instruction = (future number of padding
- // bytes - current number of padding byte) -
- // previously over estimated variation =
- // = ((3 - newOffset%4) - (3 - u%4)) - u%4
- // = (-newOffset%4 + u%4) - u%4
- // = -(newOffset & 3)
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // over estimation of the number of bytes to be
- // added to this instruction = 3 - current number
- // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
- break;
- case ClassWriter.LOOK_INSN:
- if (state == 1) {
- // like TABL_INSN
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // like TABL_INSN
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 8 * readInt(b, u + 4) + 8;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- u += 6;
- } else {
- u += 4;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- u += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- case ClassWriter.INDYMETH_INSN:
- u += 5;
- break;
- // case ClassWriter.MANA_INSN:
- default:
- u += 4;
- break;
- }
- if (insert != 0) {
- // adds a new (u, insert) entry in the allIndexes and
- // allSizes arrays
- int[] newIndexes = new int[allIndexes.length + 1];
- int[] newSizes = new int[allSizes.length + 1];
- System.arraycopy(allIndexes, 0, newIndexes, 0,
- allIndexes.length);
- System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
- newIndexes[allIndexes.length] = u;
- newSizes[allSizes.length] = insert;
- allIndexes = newIndexes;
- allSizes = newSizes;
- if (insert > 0) {
- state = 3;
- }
- }
- }
- if (state < 3) {
- --state;
- }
- } while (state != 0);
-
- // 2nd step:
- // copies the bytecode of the method into a new bytevector, updates the
- // offsets, and inserts (or removes) bytes as requested.
-
- ByteVector newCode = new ByteVector(code.length);
-
- u = 0;
- while (u < code.length) {
- int opcode = b[u] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- newCode.putByte(opcode);
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- if (opcode > 201) {
- // changes temporary opcodes 202 to 217 (inclusive), 218
- // and 219 to IFEQ ... JSR (inclusive), IFNULL and
- // IFNONNULL
- opcode = opcode < 218 ? opcode - 49 : opcode - 20;
- label = u + readUnsignedShort(b, u + 1);
- } else {
- label = u + readShort(b, u + 1);
- }
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (resize[u]) {
- // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
- // with IFNOTxxx GOTO_W , where IFNOTxxx is
- // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
- // and where designates the instruction just after
- // the GOTO_W.
- if (opcode == Opcodes.GOTO) {
- newCode.putByte(200); // GOTO_W
- } else if (opcode == Opcodes.JSR) {
- newCode.putByte(201); // JSR_W
- } else {
- newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
- : opcode ^ 1);
- newCode.putShort(8); // jump offset
- newCode.putByte(200); // GOTO_W
- // newOffset now computed from start of GOTO_W
- newOffset -= 3;
- }
- newCode.putInt(newOffset);
- } else {
- newCode.putByte(opcode);
- newCode.putShort(newOffset);
- }
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- label = u + readInt(b, u + 1);
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- newCode.putByte(opcode);
- newCode.putInt(newOffset);
- u += 5;
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- newCode.putByte(Opcodes.TABLESWITCH);
- newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u);
- u += 4;
- newCode.putInt(j);
- j = readInt(b, u) - j + 1;
- u += 4;
- newCode.putInt(readInt(b, u - 4));
- for (; j > 0; --j) {
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- }
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- newCode.putByte(Opcodes.LOOKUPSWITCH);
- newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u);
- u += 4;
- newCode.putInt(j);
- for (; j > 0; --j) {
- newCode.putInt(readInt(b, u));
- u += 4;
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- }
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- newCode.putByteArray(b, u, 6);
- u += 6;
- } else {
- newCode.putByteArray(b, u, 4);
- u += 4;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- newCode.putByteArray(b, u, 2);
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- newCode.putByteArray(b, u, 3);
- u += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- case ClassWriter.INDYMETH_INSN:
- newCode.putByteArray(b, u, 5);
- u += 5;
- break;
- // case MANA_INSN:
- default:
- newCode.putByteArray(b, u, 4);
- u += 4;
- break;
- }
- }
-
- // updates the stack map frame labels
- if (compute == FRAMES) {
- Label l = labels;
- while (l != null) {
- /*
- * Detects the labels that are just after an IF instruction that
- * has been resized with the IFNOT GOTO_W pattern. These labels
- * are now the target of a jump instruction (the IFNOT
- * instruction). Note that we need the original label position
- * here. getNewOffset must therefore never have been called for
- * this label.
- */
- u = l.position - 3;
- if (u >= 0 && resize[u]) {
- l.status |= Label.TARGET;
- }
- getNewOffset(allIndexes, allSizes, l);
- l = l.successor;
- }
- // Update the offsets in the uninitialized types
- if (cw.typeTable != null) {
- for (i = 0; i < cw.typeTable.length; ++i) {
- Item item = cw.typeTable[i];
- if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
- item.intVal = getNewOffset(allIndexes, allSizes, 0,
- item.intVal);
- }
- }
- }
- // The stack map frames are not serialized yet, so we don't need
- // to update them. They will be serialized in visitMaxs.
- } else if (frameCount > 0) {
- /*
- * Resizing an existing stack map frame table is really hard. Not
- * only the table must be parsed to update the offets, but new
- * frames may be needed for jump instructions that were inserted by
- * this method. And updating the offsets or inserting frames can
- * change the format of the following frames, in case of packed
- * frames. In practice the whole table must be recomputed. For this
- * the frames are marked as potentially invalid. This will cause the
- * whole class to be reread and rewritten with the COMPUTE_FRAMES
- * option (see the ClassWriter.toByteArray method). This is not very
- * efficient but is much easier and requires much less code than any
- * other method I can think of.
- */
- cw.invalidFrames = true;
- }
- // updates the exception handler block labels
- Handler h = firstHandler;
- while (h != null) {
- getNewOffset(allIndexes, allSizes, h.start);
- getNewOffset(allIndexes, allSizes, h.end);
- getNewOffset(allIndexes, allSizes, h.handler);
- h = h.next;
- }
- // updates the instructions addresses in the
- // local var and line number tables
- for (i = 0; i < 2; ++i) {
- ByteVector bv = i == 0 ? localVar : localVarType;
- if (bv != null) {
- b = bv.data;
- u = 0;
- while (u < bv.length) {
- label = readUnsignedShort(b, u);
- newOffset = getNewOffset(allIndexes, allSizes, 0, label);
- writeShort(b, u, newOffset);
- label += readUnsignedShort(b, u + 2);
- newOffset = getNewOffset(allIndexes, allSizes, 0, label)
- - newOffset;
- writeShort(b, u + 2, newOffset);
- u += 10;
- }
- }
- }
- if (lineNumber != null) {
- b = lineNumber.data;
- u = 0;
- while (u < lineNumber.length) {
- writeShort(
- b,
- u,
- getNewOffset(allIndexes, allSizes, 0,
- readUnsignedShort(b, u)));
- u += 4;
- }
- }
- // updates the labels of the other attributes
- Attribute attr = cattrs;
- while (attr != null) {
- Label[] labels = attr.getLabels();
- if (labels != null) {
- for (i = labels.length - 1; i >= 0; --i) {
- getNewOffset(allIndexes, allSizes, labels[i]);
- }
- }
- attr = attr.next;
- }
-
- // replaces old bytecodes with new ones
- code = newCode;
- }
-
- /**
- * Reads an unsigned short value in the given byte array.
- *
- * @param b
- * a byte array.
- * @param index
- * the start index of the value to be read.
- * @return the read value.
- */
- static int readUnsignedShort(final byte[] b, final int index) {
- return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
- }
-
- /**
- * Reads a signed short value in the given byte array.
- *
- * @param b
- * a byte array.
- * @param index
- * the start index of the value to be read.
- * @return the read value.
- */
- static short readShort(final byte[] b, final int index) {
- return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
- }
-
- /**
- * Reads a signed int value in the given byte array.
- *
- * @param b
- * a byte array.
- * @param index
- * the start index of the value to be read.
- * @return the read value.
- */
- static int readInt(final byte[] b, final int index) {
- return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
- | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
- }
-
- /**
- * Writes a short value in the given byte array.
- *
- * @param b
- * a byte array.
- * @param index
- * where the first byte of the short value must be written.
- * @param s
- * the value to be written in the given byte array.
- */
- static void writeShort(final byte[] b, final int index, final int s) {
- b[index] = (byte) (s >>> 8);
- b[index + 1] = (byte) s;
- }
-
- /**
- * Computes the future value of a bytecode offset.
- *
- * Note: it is possible to have several entries for the same instruction in
- * the indexes and sizes: two entries (index=a,size=b) and
- * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b').
- *
- * @param indexes
- * current positions of the instructions to be resized. Each
- * instruction must be designated by the index of its last
- * byte, plus one (or, in other words, by the index of the
- * first byte of the next instruction).
- * @param sizes
- * the number of bytes to be added to the above
- * instructions. More precisely, for each i < len,
- * sizes[i] bytes will be added at the end of the
- * instruction designated by indexes[i] or, if
- * sizes[i] is negative, the last |
- * sizes[i]| bytes of the instruction will be removed
- * (the instruction size must not become negative or
- * null).
- * @param begin
- * index of the first byte of the source instruction.
- * @param end
- * index of the first byte of the target instruction.
- * @return the future value of the given bytecode offset.
- */
- static int getNewOffset(final int[] indexes, final int[] sizes,
- final int begin, final int end) {
- int offset = end - begin;
- for (int i = 0; i < indexes.length; ++i) {
- if (begin < indexes[i] && indexes[i] <= end) {
- // forward jump
- offset += sizes[i];
- } else if (end < indexes[i] && indexes[i] <= begin) {
- // backward jump
- offset -= sizes[i];
- }
- }
- return offset;
- }
-
- /**
- * Updates the offset of the given label.
- *
- * @param indexes
- * current positions of the instructions to be resized. Each
- * instruction must be designated by the index of its last
- * byte, plus one (or, in other words, by the index of the
- * first byte of the next instruction).
- * @param sizes
- * the number of bytes to be added to the above
- * instructions. More precisely, for each i < len,
- * sizes[i] bytes will be added at the end of the
- * instruction designated by indexes[i] or, if
- * sizes[i] is negative, the last |
- * sizes[i]| bytes of the instruction will be removed
- * (the instruction size must not become negative or
- * null).
- * @param label
- * the label whose offset must be updated.
- */
- static void getNewOffset(final int[] indexes, final int[] sizes,
- final Label label) {
- if ((label.status & Label.RESIZED) == 0) {
- label.position = getNewOffset(indexes, sizes, 0, label.position);
- label.status |= Label.RESIZED;
- }
- }
}
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleVisitor.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleVisitor.java
@@ -0,0 +1,207 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * A visitor to visit a Java module. The methods of this class must be called in
+ * the following order: visitVersion | visitMainClass |
+ * visitTargetPlatform | ( visitConcealedPackage | visitRequire |
+ * visitExport | visitUse | visitProvide )* visitEnd.
+ *
+ * @author Remi Forax
+ */
+public abstract class ModuleVisitor {
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be {@link Opcodes#ASM6}.
+ */
+ protected final int api;
+
+ /**
+ * The module visitor to which this visitor must delegate method calls. May
+ * be null.
+ */
+ protected ModuleVisitor mv;
+
+
+ public ModuleVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link MethodVisitor}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
+ * @param mv
+ * the method visitor to which this visitor must delegate method
+ * calls. May be null.
+ */
+ public ModuleVisitor(final int api, final ModuleVisitor mv) {
+ if (api != Opcodes.ASM6) {
+ throw new IllegalArgumentException();
+ }
+ this.api = api;
+ this.mv = mv;
+ }
+
+ /**
+ * Visit the main class of the current module.
+ *
+ * @param mainClass the main class of the current module.
+ */
+ public void visitMainClass(String mainClass) {
+ if (mv != null) {
+ mv.visitMainClass(mainClass);
+ }
+ }
+
+ /**
+ * Visit a concealed package of the current module.
+ *
+ * @param packaze name of a concealed package
+ */
+ public void visitPackage(String packaze) {
+ if (mv != null) {
+ mv.visitPackage(packaze);
+ }
+ }
+
+ /**
+ * Visits a dependence of the current module.
+ *
+ * @param module the module name of the dependence
+ * @param access the access flag of the dependence among
+ * ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC
+ * and ACC_MANDATED.
+ * @param version the module version at compile time or null.
+ */
+ public void visitRequire(String module, int access, String version) {
+ if (mv != null) {
+ mv.visitRequire(module, access, version);
+ }
+ }
+
+ /**
+ * Visit an exported package of the current module.
+ *
+ * @param packaze the name of the exported package.
+ * @param access the access flag of the exported package,
+ * valid values are among {@code ACC_SYNTHETIC} and
+ * {@code ACC_MANDATED}.
+ * @param modules names of the modules that can access to
+ * the public classes of the exported package or
+ * null.
+ */
+ public void visitExport(String packaze, int access, String... modules) {
+ if (mv != null) {
+ mv.visitExport(packaze, access, modules);
+ }
+ }
+
+ /**
+ * Visit an open package of the current module.
+ *
+ * @param packaze the name of the opened package.
+ * @param access the access flag of the opened package,
+ * valid values are among {@code ACC_SYNTHETIC} and
+ * {@code ACC_MANDATED}.
+ * @param modules names of the modules that can use deep
+ * reflection to the classes of the open package or
+ * null.
+ */
+ public void visitOpen(String packaze, int access, String... modules) {
+ if (mv != null) {
+ mv.visitOpen(packaze, access, modules);
+ }
+ }
+
+ /**
+ * Visit a service used by the current module.
+ * The name must be the name of an interface or an
+ * abstract class.
+ *
+ * @param service the internal name of the service.
+ */
+ public void visitUse(String service) {
+ if (mv != null) {
+ mv.visitUse(service);
+ }
+ }
+
+ /**
+ * Visit an implementation of a service.
+ *
+ * @param service the internal name of the service
+ * @param providers the internal names of the implementations
+ * of the service (there is at least one provider).
+ */
+ public void visitProvide(String service, String... providers) {
+ if (mv != null) {
+ mv.visitProvide(service, providers);
+ }
+ }
+
+ public void visitEnd() {
+ if (mv != null) {
+ mv.visitEnd();
+ }
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleWriter.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleWriter.java
@@ -0,0 +1,322 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * @author Remi Forax
+ */
+final class ModuleWriter extends ModuleVisitor {
+ /**
+ * The class writer to which this Module attribute must be added.
+ */
+ private final ClassWriter cw;
+
+ /**
+ * size in byte of the Module attribute.
+ */
+ int size;
+
+ /**
+ * Number of attributes associated with the current module
+ * (Version, ConcealPackages, etc)
+ */
+ int attributeCount;
+
+ /**
+ * Size in bytes of the attributes associated with the current module
+ */
+ int attributesSize;
+
+ /**
+ * module name index in the constant pool
+ */
+ private final int name;
+
+ /**
+ * module access flags
+ */
+ private final int access;
+
+ /**
+ * module version index in the constant pool or 0
+ */
+ private final int version;
+
+ /**
+ * module main class index in the constant pool or 0
+ */
+ private int mainClass;
+
+ /**
+ * number of packages
+ */
+ private int packageCount;
+
+ /**
+ * The packages in bytecode form. This byte vector only contains
+ * the items themselves, the number of items is store in packageCount
+ */
+ private ByteVector packages;
+
+ /**
+ * number of requires items
+ */
+ private int requireCount;
+
+ /**
+ * The requires items in bytecode form. This byte vector only contains
+ * the items themselves, the number of items is store in requireCount
+ */
+ private ByteVector requires;
+
+ /**
+ * number of exports items
+ */
+ private int exportCount;
+
+ /**
+ * The exports items in bytecode form. This byte vector only contains
+ * the items themselves, the number of items is store in exportCount
+ */
+ private ByteVector exports;
+
+ /**
+ * number of opens items
+ */
+ private int openCount;
+
+ /**
+ * The opens items in bytecode form. This byte vector only contains
+ * the items themselves, the number of items is store in openCount
+ */
+ private ByteVector opens;
+
+ /**
+ * number of uses items
+ */
+ private int useCount;
+
+ /**
+ * The uses items in bytecode form. This byte vector only contains
+ * the items themselves, the number of items is store in useCount
+ */
+ private ByteVector uses;
+
+ /**
+ * number of provides items
+ */
+ private int provideCount;
+
+ /**
+ * The uses provides in bytecode form. This byte vector only contains
+ * the items themselves, the number of items is store in provideCount
+ */
+ private ByteVector provides;
+
+ ModuleWriter(final ClassWriter cw, final int name,
+ final int access, final int version) {
+ super(Opcodes.ASM6);
+ this.cw = cw;
+ this.size = 16; // name + access + version + 5 counts
+ this.name = name;
+ this.access = access;
+ this.version = version;
+ }
+
+ @Override
+ public void visitMainClass(String mainClass) {
+ if (this.mainClass == 0) { // protect against several calls to visitMainClass
+ cw.newUTF8("ModuleMainClass");
+ attributeCount++;
+ attributesSize += 8;
+ }
+ this.mainClass = cw.newClass(mainClass);
+ }
+
+ @Override
+ public void visitPackage(String packaze) {
+ if (packages == null) {
+ // protect against several calls to visitPackage
+ cw.newUTF8("ModulePackages");
+ packages = new ByteVector();
+ attributeCount++;
+ attributesSize += 8;
+ }
+ packages.putShort(cw.newPackage(packaze));
+ packageCount++;
+ attributesSize += 2;
+ }
+
+ @Override
+ public void visitRequire(String module, int access, String version) {
+ if (requires == null) {
+ requires = new ByteVector();
+ }
+ requires.putShort(cw.newModule(module))
+ .putShort(access)
+ .putShort(version == null? 0: cw.newUTF8(version));
+ requireCount++;
+ size += 6;
+ }
+
+ @Override
+ public void visitExport(String packaze, int access, String... modules) {
+ if (exports == null) {
+ exports = new ByteVector();
+ }
+ exports.putShort(cw.newPackage(packaze)).putShort(access);
+ if (modules == null) {
+ exports.putShort(0);
+ size += 6;
+ } else {
+ exports.putShort(modules.length);
+ for(String module: modules) {
+ exports.putShort(cw.newModule(module));
+ }
+ size += 6 + 2 * modules.length;
+ }
+ exportCount++;
+ }
+
+ @Override
+ public void visitOpen(String packaze, int access, String... modules) {
+ if (opens == null) {
+ opens = new ByteVector();
+ }
+ opens.putShort(cw.newPackage(packaze)).putShort(access);
+ if (modules == null) {
+ opens.putShort(0);
+ size += 6;
+ } else {
+ opens.putShort(modules.length);
+ for(String module: modules) {
+ opens.putShort(cw.newModule(module));
+ }
+ size += 6 + 2 * modules.length;
+ }
+ openCount++;
+ }
+
+ @Override
+ public void visitUse(String service) {
+ if (uses == null) {
+ uses = new ByteVector();
+ }
+ uses.putShort(cw.newClass(service));
+ useCount++;
+ size += 2;
+ }
+
+ @Override
+ public void visitProvide(String service, String... providers) {
+ if (provides == null) {
+ provides = new ByteVector();
+ }
+ provides.putShort(cw.newClass(service));
+ provides.putShort(providers.length);
+ for(String provider: providers) {
+ provides.putShort(cw.newClass(provider));
+ }
+ provideCount++;
+ size += 4 + 2 * providers.length;
+ }
+
+ @Override
+ public void visitEnd() {
+ // empty
+ }
+
+ void putAttributes(ByteVector out) {
+ if (mainClass != 0) {
+ out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
+ }
+ if (packages != null) {
+ out.putShort(cw.newUTF8("ModulePackages"))
+ .putInt(2 + 2 * packageCount)
+ .putShort(packageCount)
+ .putByteArray(packages.data, 0, packages.length);
+ }
+ }
+
+ void put(ByteVector out) {
+ out.putInt(size);
+ out.putShort(name).putShort(access).putShort(version);
+ out.putShort(requireCount);
+ if (requires != null) {
+ out.putByteArray(requires.data, 0, requires.length);
+ }
+ out.putShort(exportCount);
+ if (exports != null) {
+ out.putByteArray(exports.data, 0, exports.length);
+ }
+ out.putShort(openCount);
+ if (opens != null) {
+ out.putByteArray(opens.data, 0, opens.length);
+ }
+ out.putShort(useCount);
+ if (uses != null) {
+ out.putByteArray(uses.data, 0, uses.length);
+ }
+ out.putShort(provideCount);
+ if (provides != null) {
+ out.putByteArray(provides.data, 0, provides.length);
+ }
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java
@@ -70,13 +70,13 @@
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
-@SuppressWarnings("deprecation") // for Integer(int) constructor
public interface Opcodes {
// ASM API versions
int ASM4 = 4 << 16 | 0 << 8 | 0;
int ASM5 = 5 << 16 | 0 << 8 | 0;
+ int ASM6 = 6 << 16 | 0 << 8 | 0;
// versions
@@ -99,18 +99,23 @@
int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method
+ int ACC_OPEN = 0x0020; // module
+ int ACC_TRANSITIVE = 0x0020; // module requires
int ACC_VOLATILE = 0x0040; // field
int ACC_BRIDGE = 0x0040; // method
+ int ACC_STATIC_PHASE = 0x0040; // module requires
int ACC_VARARGS = 0x0080; // method
int ACC_TRANSIENT = 0x0080; // field
int ACC_NATIVE = 0x0100; // method
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
- int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
+ int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
- int ACC_MANDATED = 0x8000; // parameter
+ int ACC_MANDATED = 0x8000; // parameter, module, module *
+ int ACC_MODULE = 0x8000; // class
+
// ASM specific pseudo access flags
@@ -177,15 +182,17 @@
*/
int F_SAME1 = 4;
- // For reference comparison purposes, construct new instances
- // instead of using valueOf() or autoboxing.
- Integer TOP = new Integer(0);
- Integer INTEGER = new Integer(1);
- Integer FLOAT = new Integer(2);
- Integer DOUBLE = new Integer(3);
- Integer LONG = new Integer(4);
- Integer NULL = new Integer(5);
- Integer UNINITIALIZED_THIS = new Integer(6);
+ // Do not try to change the following code to use auto-boxing,
+ // these values are compared by reference and not by value
+ // The constructor of Integer was deprecated in 9
+ // but we are stuck with it by backward compatibility
+ @SuppressWarnings("deprecation") Integer TOP = new Integer(0);
+ @SuppressWarnings("deprecation") Integer INTEGER = new Integer(1);
+ @SuppressWarnings("deprecation") Integer FLOAT = new Integer(2);
+ @SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3);
+ @SuppressWarnings("deprecation") Integer LONG = new Integer(4);
+ @SuppressWarnings("deprecation") Integer NULL = new Integer(5);
+ @SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6);
// opcodes // visit method (- = idem)
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java
@@ -406,7 +406,16 @@
*/
public static Type getReturnType(final String methodDescriptor) {
char[] buf = methodDescriptor.toCharArray();
- return getType(buf, methodDescriptor.indexOf(')') + 1);
+ int off = 1;
+ while (true) {
+ char car = buf[off++];
+ if (car == ')') {
+ return getType(buf, off);
+ } else if (car == 'L') {
+ while (buf[off++] != ';') {
+ }
+ }
+ }
}
/**
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java
@@ -112,7 +112,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv
* the method visitor to which this adapter delegates calls.
* @param access
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java
@@ -170,7 +170,7 @@
*/
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);
+ this(Opcodes.ASM6, owner, access, name, desc, mv);
if (getClass() != AnalyzerAdapter.class) {
throw new IllegalStateException();
}
@@ -181,7 +181,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param owner
* the owner's class name.
* @param access
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java
@@ -73,7 +73,7 @@
public AnnotationRemapper(final AnnotationVisitor av,
final Remapper remapper) {
- this(Opcodes.ASM5, av, remapper);
+ this(Opcodes.ASM6, av, remapper);
}
protected AnnotationRemapper(final int api, final AnnotationVisitor av,
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java
@@ -59,10 +59,14 @@
package jdk.internal.org.objectweb.asm.commons;
+import java.util.List;
+
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
+import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath;
@@ -78,7 +82,7 @@
protected String className;
public ClassRemapper(final ClassVisitor cv, final Remapper remapper) {
- this(Opcodes.ASM5, cv, remapper);
+ this(Opcodes.ASM6, cv, remapper);
}
protected ClassRemapper(final int api, final ClassVisitor cv,
@@ -97,6 +101,12 @@
}
@Override
+ public ModuleVisitor visitModule(String name, int flags, String version) {
+ ModuleVisitor mv = super.visitModule(remapper.mapModuleName(name), flags, version);
+ return mv == null ? null : createModuleRemapper(mv);
+ }
+
+ @Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
visible);
@@ -112,6 +122,18 @@
}
@Override
+ public void visitAttribute(Attribute attr) {
+ if (attr instanceof ModuleHashesAttribute) {
+ ModuleHashesAttribute hashesAttr = new ModuleHashesAttribute();
+ List modules = hashesAttr.modules;
+ for(int i = 0; i < modules.size(); i++) {
+ modules.set(i, remapper.mapModuleName(modules.get(i)));
+ }
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
public FieldVisitor visitField(int access, String name, String desc,
String signature, Object value) {
FieldVisitor fv = super.visitField(access,
@@ -158,4 +180,8 @@
protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) {
return new AnnotationRemapper(av, remapper);
}
+
+ protected ModuleVisitor createModuleRemapper(ModuleVisitor mv) {
+ return new ModuleRemapper(mv, remapper);
+ }
}
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java
@@ -75,7 +75,7 @@
private int maxSize;
public CodeSizeEvaluator(final MethodVisitor mv) {
- this(Opcodes.ASM5, mv);
+ this(Opcodes.ASM6, mv);
}
protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java
@@ -74,7 +74,7 @@
private final Remapper remapper;
public FieldRemapper(final FieldVisitor fv, final Remapper remapper) {
- this(Opcodes.ASM5, fv, remapper);
+ this(Opcodes.ASM6, fv, remapper);
}
protected FieldRemapper(final int api, final FieldVisitor fv,
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java
@@ -289,7 +289,7 @@
*/
public GeneratorAdapter(final MethodVisitor mv, final int access,
final String name, final String desc) {
- this(Opcodes.ASM5, mv, access, name, desc);
+ this(Opcodes.ASM6, mv, access, name, desc);
if (getClass() != GeneratorAdapter.class) {
throw new IllegalStateException();
}
@@ -300,7 +300,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv
* the method visitor to which this adapter delegates calls.
* @param access
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java
@@ -86,7 +86,7 @@
* If a subclass calls this constructor.
*/
public InstructionAdapter(final MethodVisitor mv) {
- this(Opcodes.ASM5, mv);
+ this(Opcodes.ASM6, mv);
if (getClass() != InstructionAdapter.class) {
throw new IllegalStateException();
}
@@ -97,7 +97,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv
* the method visitor to which this adapter delegates calls.
*/
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java
@@ -142,7 +142,7 @@
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);
+ this(Opcodes.ASM6, mv, access, name, desc, signature, exceptions);
if (getClass() != JSRInlinerAdapter.class) {
throw new IllegalStateException();
}
@@ -153,7 +153,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv
* the MethodVisitor to send the resulting inlined
* method code to (use null for none).
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java
@@ -120,7 +120,7 @@
*/
public LocalVariablesSorter(final int access, final String desc,
final MethodVisitor mv) {
- this(Opcodes.ASM5, access, desc, mv);
+ this(Opcodes.ASM6, access, desc, mv);
if (getClass() != LocalVariablesSorter.class) {
throw new IllegalStateException();
}
@@ -131,7 +131,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param access
* access flags of the adapted method.
* @param desc
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java
@@ -76,7 +76,7 @@
protected final Remapper remapper;
public MethodRemapper(final MethodVisitor mv, final Remapper remapper) {
- this(Opcodes.ASM5, mv, remapper);
+ this(Opcodes.ASM6, mv, remapper);
}
protected MethodRemapper(final int api, final MethodVisitor mv,
@@ -122,18 +122,20 @@
}
private Object[] remapEntries(int n, Object[] entries) {
- for (int i = 0; i < n; i++) {
- if (entries[i] instanceof String) {
- Object[] newEntries = new Object[n];
- if (i > 0) {
- System.arraycopy(entries, 0, newEntries, 0, i);
+ if (entries != null) {
+ for (int i = 0; i < n; i++) {
+ if (entries[i] instanceof String) {
+ Object[] newEntries = new Object[n];
+ if (i > 0) {
+ System.arraycopy(entries, 0, newEntries, 0, i);
+ }
+ do {
+ Object t = entries[i];
+ newEntries[i++] = t instanceof String ? remapper
+ .mapType((String) t) : t;
+ } while (i < n);
+ return newEntries;
}
- do {
- Object t = entries[i];
- newEntries[i++] = t instanceof String ? remapper
- .mapType((String) t) : t;
- } while (i < n);
- return newEntries;
}
}
return entries;
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleHashesAttribute.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleHashesAttribute.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleHashesAttribute.java
@@ -0,0 +1,155 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package jdk.internal.org.objectweb.asm.commons;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.ByteVector;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+
+/**
+ * ModuleHashes attribute.
+ * This attribute is specific to the OpenJDK and may change in the future.
+ *
+ * @author Remi Forax
+ */
+public final class ModuleHashesAttribute extends Attribute {
+ public String algorithm;
+ public List modules;
+ public List hashes;
+
+ /**
+ * Creates an attribute with a hashing algorithm, a list of module names,
+ * and a list of the same length of hashes.
+ * @param algorithm the hashing algorithm name.
+ * @param modules a list of module name
+ * @param hashes a list of hash, one for each module name.
+ */
+ public ModuleHashesAttribute(final String algorithm,
+ final List modules, final List hashes) {
+ super("ModuleHashes");
+ this.algorithm = algorithm;
+ this.modules = modules;
+ this.hashes = hashes;
+ }
+
+ /**
+ * Creates an empty attribute that can be used as prototype
+ * to be passed as argument of the method
+ * {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
+ */
+ public ModuleHashesAttribute() {
+ this(null, null, null);
+ }
+
+ @Override
+ protected Attribute read(ClassReader cr, int off, int len, char[] buf,
+ int codeOff, Label[] labels) {
+ String hashAlgorithm = cr.readUTF8(off, buf);
+
+ int count = cr.readUnsignedShort(off + 2);
+ ArrayList modules = new ArrayList(count);
+ ArrayList hashes = new ArrayList(count);
+ off += 4;
+
+ for (int i = 0; i < count; i++) {
+ String module = cr.readModule(off, buf);
+ int hashLength = cr.readUnsignedShort(off + 2);
+ off += 4;
+
+ byte[] hash = new byte[hashLength];
+ for (int j = 0; j < hashLength; j++) {
+ hash[j] = (byte) (cr.readByte(off + j) & 0xff);
+ }
+ off += hashLength;
+
+ modules.add(module);
+ hashes.add(hash);
+ }
+ return new ModuleHashesAttribute(hashAlgorithm, modules, hashes);
+ }
+
+ @Override
+ protected ByteVector write(ClassWriter cw, byte[] code, int len,
+ int maxStack, int maxLocals) {
+ ByteVector v = new ByteVector();
+ int index = cw.newUTF8(algorithm);
+ v.putShort(index);
+
+ int count = (modules == null)? 0: modules.size();
+ v.putShort(count);
+
+ for(int i = 0; i < count; i++) {
+ String module = modules.get(i);
+ v.putShort(cw.newModule(module));
+
+ byte[] hash = hashes.get(i);
+ v.putShort(hash.length);
+ for(byte b: hash) {
+ v.putByte(b);
+ }
+ }
+ return v;
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleRemapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleRemapper.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleRemapper.java
@@ -0,0 +1,135 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package jdk.internal.org.objectweb.asm.commons;
+
+import jdk.internal.org.objectweb.asm.ModuleVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+/**
+ * A {@link ModuleVisitor} adapter for type remapping.
+ *
+ * @author Remi Forax
+ */
+public class ModuleRemapper extends ModuleVisitor {
+ private final Remapper remapper;
+
+ public ModuleRemapper(final ModuleVisitor mv, final Remapper remapper) {
+ this(Opcodes.ASM6, mv, remapper);
+ }
+
+ protected ModuleRemapper(final int api, final ModuleVisitor mv,
+ final Remapper remapper) {
+ super(api, mv);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visitMainClass(String mainClass) {
+ super.visitMainClass(remapper.mapType(mainClass));
+ }
+
+ @Override
+ public void visitPackage(String packaze) {
+ super.visitPackage(remapper.mapPackageName(packaze));
+ }
+
+ @Override
+ public void visitRequire(String module, int access, String version) {
+ super.visitRequire(remapper.mapModuleName(module), access, version);
+ }
+
+ @Override
+ public void visitExport(String packaze, int access, String... modules) {
+ String[] newModules = null;
+ if (modules != null) {
+ newModules = new String[modules.length];
+ for (int i = 0 ; i < modules.length; i++) {
+ newModules[i] = remapper.mapModuleName(modules[i]);
+ }
+ }
+ super.visitExport(remapper.mapPackageName(packaze), access, newModules);
+ }
+
+ @Override
+ public void visitOpen(String packaze, int access, String... modules) {
+ String[] newModules = null;
+ if (modules != null) {
+ newModules = new String[modules.length];
+ for (int i = 0 ; i < modules.length; i++) {
+ newModules[i] = remapper.mapModuleName(modules[i]);
+ }
+ }
+ super.visitOpen(remapper.mapPackageName(packaze), access, newModules);
+ }
+
+ @Override
+ public void visitUse(String service) {
+ super.visitUse(remapper.mapType(service));
+ }
+
+ @Override
+ public void visitProvide(String service, String... providers) {
+ String[] newProviders = new String[providers.length];
+ for (int i = 0 ; i < providers.length; i++) {
+ newProviders[i] = remapper.mapType(providers[i]);
+ }
+ super.visitProvide(remapper.mapType(service), newProviders);
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleResolutionAttribute.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleResolutionAttribute.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleResolutionAttribute.java
@@ -0,0 +1,135 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package jdk.internal.org.objectweb.asm.commons;
+
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.ByteVector;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+
+/**
+ * ModuleResolution_attribute.
+ * This attribute is specific to the OpenJDK and may change in the future.
+ *
+ * @author Remi Forax
+ */
+public final class ModuleResolutionAttribute extends Attribute {
+ /**
+ * Resolution state of a module meaning that the module is not available
+ * from the class-path by default.
+ */
+ public static final int RESOLUTION_DO_NOT_RESOLVE_BY_DEFAULT = 1;
+
+ /**
+ * Resolution state of a module meaning the module is marked as deprecated.
+ */
+ public static final int RESOLUTION_WARN_DEPRECATED = 2;
+
+ /**
+ * Resolution state of a module meaning the module is marked as deprecated
+ * and will be removed in a future release.
+ */
+ public static final int RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL = 4;
+
+ /**
+ * Resolution state of a module meaning the module is not yet standardized,
+ * so in incubating mode.
+ */
+ public static final int RESOLUTION_WARN_INCUBATING = 8;
+
+ public int resolution;
+
+ /**
+ * Creates an attribute with a resolution state value.
+ * @param resolution the resolution state among
+ * {@link #RESOLUTION_WARN_DEPRECATED},
+ * {@link #RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL}, and
+ * {@link #RESOLUTION_WARN_INCUBATING}.
+ */
+ public ModuleResolutionAttribute(final int resolution) {
+ super("ModuleResolution");
+ this.resolution = resolution;
+ }
+
+ /**
+ * Creates an empty attribute that can be used as prototype
+ * to be passed as argument of the method
+ * {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
+ */
+ public ModuleResolutionAttribute() {
+ this(0);
+ }
+
+ @Override
+ protected Attribute read(ClassReader cr, int off, int len, char[] buf,
+ int codeOff, Label[] labels) {
+ int resolution = cr.readUnsignedShort(off);
+ return new ModuleResolutionAttribute(resolution);
+ }
+
+ @Override
+ protected ByteVector write(ClassWriter cw, byte[] code, int len,
+ int maxStack, int maxLocals) {
+ ByteVector v = new ByteVector();
+ v.putShort(resolution);
+ return v;
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleTargetAttribute.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleTargetAttribute.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleTargetAttribute.java
@@ -0,0 +1,110 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package jdk.internal.org.objectweb.asm.commons;
+
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.ByteVector;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+
+/**
+ * ModuleTarget attribute.
+ * This attribute is specific to the OpenJDK and may change in the future.
+ *
+ * @author Remi Forax
+ */
+public final class ModuleTargetAttribute extends Attribute {
+ public String platform;
+
+ /**
+ * Creates an attribute with a platform name.
+ * @param platform the platform name on which the module can run.
+ */
+ public ModuleTargetAttribute(final String platform) {
+ super("ModuleTarget");
+ this.platform = platform;
+ }
+
+ /**
+ * Creates an empty attribute that can be used as prototype
+ * to be passed as argument of the method
+ * {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
+ */
+ public ModuleTargetAttribute() {
+ this(null);
+ }
+
+ @Override
+ protected Attribute read(ClassReader cr, int off, int len, char[] buf,
+ int codeOff, Label[] labels) {
+ String platform = cr.readUTF8(off, buf);
+ return new ModuleTargetAttribute(platform);
+ }
+
+ @Override
+ protected ByteVector write(ClassWriter cw, byte[] code, int len,
+ int maxStack, int maxLocals) {
+ ByteVector v = new ByteVector();
+ int index = (platform == null)? 0: cw.newUTF8(platform);
+ v.putShort(index);
+ return v;
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java
@@ -255,6 +255,28 @@
}
/**
+ * Map package name to the new name. Subclasses can override.
+ *
+ * @param name name of the package
+ * @return new name of the package
+ */
+ public String mapPackageName(String name) {
+ String fakeName = map(name + ".FakeClassName");
+ int index;
+ return fakeName == null || (index = fakeName.lastIndexOf('.')) == -1 ? name: fakeName.substring(0, index);
+ }
+
+ /**
+ * Map module name to the new name. Subclasses can override.
+ *
+ * @param name name of the module
+ * @return new name of the module
+ */
+ public String mapModuleName(String name) {
+ return name;
+ }
+
+ /**
* Map type name to the new name. Subclasses can override.
*
* @param typeName
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java
@@ -75,7 +75,7 @@
public RemappingAnnotationAdapter(final AnnotationVisitor av,
final Remapper remapper) {
- this(Opcodes.ASM5, av, remapper);
+ this(Opcodes.ASM6, av, remapper);
}
protected RemappingAnnotationAdapter(final int api,
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java
@@ -63,6 +63,7 @@
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath;
@@ -80,7 +81,7 @@
protected String className;
public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
- this(Opcodes.ASM5, cv, remapper);
+ this(Opcodes.ASM6, cv, remapper);
}
protected RemappingClassAdapter(final int api, final ClassVisitor cv,
@@ -99,6 +100,11 @@
}
@Override
+ public ModuleVisitor visitModule(String name, int flags, String version) {
+ throw new RuntimeException("RemappingClassAdapter is deprecated, use ClassRemapper instead");
+ }
+
+ @Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
visible);
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java
@@ -76,7 +76,7 @@
private final Remapper remapper;
public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
- this(Opcodes.ASM5, fv, remapper);
+ this(Opcodes.ASM6, fv, remapper);
}
protected RemappingFieldAdapter(final int api, final FieldVisitor fv,
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java
@@ -79,7 +79,7 @@
public RemappingMethodAdapter(final int access, final String desc,
final MethodVisitor mv, final Remapper remapper) {
- this(Opcodes.ASM5, access, desc, mv, remapper);
+ this(Opcodes.ASM6, access, desc, mv, remapper);
}
protected RemappingMethodAdapter(final int api, final int access,
@@ -125,18 +125,20 @@
}
private Object[] remapEntries(int n, Object[] entries) {
- for (int i = 0; i < n; i++) {
- if (entries[i] instanceof String) {
- Object[] newEntries = new Object[n];
- if (i > 0) {
- System.arraycopy(entries, 0, newEntries, 0, i);
+ if (entries != null) {
+ for (int i = 0; i < n; i++) {
+ if (entries[i] instanceof String) {
+ Object[] newEntries = new Object[n];
+ if (i > 0) {
+ System.arraycopy(entries, 0, newEntries, 0, i);
+ }
+ do {
+ Object t = entries[i];
+ newEntries[i++] = t instanceof String ? remapper
+ .mapType((String) t) : t;
+ } while (i < n);
+ return newEntries;
}
- do {
- Object t = entries[i];
- newEntries[i++] = t instanceof String ? remapper
- .mapType((String) t) : t;
- } while (i < n);
- return newEntries;
}
}
return entries;
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java
@@ -79,7 +79,7 @@
public RemappingSignatureAdapter(final SignatureVisitor v,
final Remapper remapper) {
- this(Opcodes.ASM5, v, remapper);
+ this(Opcodes.ASM6, v, remapper);
}
protected RemappingSignatureAdapter(final int api,
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java
@@ -80,7 +80,7 @@
* ClassWriter cw = new ClassWriter(...);
* ClassVisitor sv = new SerialVersionUIDAdder(cw);
* ClassVisitor ca = new MyClassAdapter(sv);
- * new ClassReader(originalClass).accept(ca, false);
+ * new ClassReader(orginalClass).accept(ca, false);
*
*
* The SVUID algorithm can be found classNames = new Stack();
public SignatureRemapper(final SignatureVisitor v, final Remapper remapper) {
- this(Opcodes.ASM5, v, remapper);
+ this(Opcodes.ASM6, v, remapper);
}
protected SignatureRemapper(final int api, final SignatureVisitor v,
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java
@@ -78,7 +78,7 @@
private int counter;
public StaticInitMerger(final String prefix, final ClassVisitor cv) {
- this(Opcodes.ASM5, prefix, cv);
+ this(Opcodes.ASM6, prefix, cv);
}
protected StaticInitMerger(final int api, final String prefix,
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java
@@ -86,7 +86,7 @@
public TryCatchBlockSorter(final MethodVisitor mv, final int access,
final String name, final String desc, final String signature,
final String[] exceptions) {
- this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions);
+ this(Opcodes.ASM6, mv, access, name, desc, signature, exceptions);
}
protected TryCatchBlockSorter(final int api, final MethodVisitor mv,
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java
@@ -102,7 +102,7 @@
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
@@ -111,10 +111,10 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public SignatureVisitor(final int api) {
- if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java
@@ -95,7 +95,7 @@
* Constructs a new {@link SignatureWriter} object.
*/
public SignatureWriter() {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM6);
}
// ------------------------------------------------------------------------
diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java
@@ -65,7 +65,7 @@
import jdk.internal.org.objectweb.asm.Opcodes;
/**
- * A node that represents an annotationn.
+ * A node that represents an annotation.
*
* @author Eric Bruneton
*/
@@ -81,8 +81,8 @@
* as two consecutive elements in the list. The name is a {@link String},
* and the value may be a {@link Byte}, {@link Boolean}, {@link Character},
* {@link Short}, {@link Integer}, {@link Long}, {@link Float},
- * {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.asm.Type}, or an
- * two elements String array (for enumeration values), a
+ * {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.asm.Type}, or a
+ * two elements String array (for enumeration values), an
* {@link AnnotationNode}, or a {@link List} of values of one of the
* preceding types. The list may be null if there is no name value
* pair.
@@ -100,7 +100,7 @@
* If a subclass calls this constructor.
*/
public AnnotationNode(final String desc) {
- this(Opcodes.ASM5, desc);
+ this(Opcodes.ASM6, desc);
if (getClass() != AnnotationNode.class) {
throw new IllegalStateException();
}
@@ -111,7 +111,7 @@
*
* @param api
* the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param desc
* the class descriptor of the annotation class.
*/
@@ -127,7 +127,7 @@
* where the visited values must be stored.
*/
AnnotationNode(final List