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 index 0841a6c97c629cc97ee6e4211c5e1f67c758de8f..9383c235b01116f1d46e1cff4c1ec673f3ff3a9a 100644 --- 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 @@ public abstract class AnnotationVisitor { /** * 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 @@ public abstract class AnnotationVisitor { * * @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 @@ public abstract class AnnotationVisitor { * * @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 @@ public abstract class AnnotationVisitor { * 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 index 5419615e86c6c0e4ee37c123b64435e536b5159f..fad0396553a0b998ebdee04e1c1d9d516bfa5c78 100644 --- 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 @@ final class AnnotationWriter extends AnnotationVisitor { */ 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 index a3c58f2990c58df2aafc3f4daec477b8fe95963e..3854a3eddb8f4ce4132a52d56135aa61d2df6943 100644 --- 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 @@ -72,31 +72,6 @@ import java.io.InputStream; */ public class ClassReader { - /** - * True to enable signatures support. - */ - static final boolean SIGNATURES = true; - - /** - * True to enable annotations support. - */ - static final boolean ANNOTATIONS = true; - - /** - * True to enable stack map frames support. - */ - static final boolean FRAMES = true; - - /** - * True to enable bytecode writing support. - */ - static final boolean WRITER = true; - - /** - * True to enable JSR_W and GOTO_W support. - */ - static final boolean RESIZE = true; - /** * Flag to skip method code. If this class is set CODE * attribute won't be visited. This can be used, for example, to retrieve @@ -133,6 +108,21 @@ public class ClassReader { */ 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 @@ -195,7 +185,7 @@ public class ClassReader { public ClassReader(final byte[] b, final int off, final int len) { this.b = b; // checks the class version - if (readShort(off + 6) > Opcodes.V1_9) { + if (readShort(off + 6) > Opcodes.V9) { throw new IllegalArgumentException(); } // parses the constant pool @@ -234,6 +224,8 @@ public class ClassReader { // case ClassWriter.CLASS: // case ClassWriter.STR: // case ClassWriter.MTYPE + // case ClassWriter.PACKAGE: + // case ClassWriter.MODULE: default: size = 3; break; @@ -377,7 +369,9 @@ public class ClassReader { 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 +578,14 @@ public class ClassReader { 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(); @@ -607,13 +604,11 @@ public class ClassReader { enclosingName = readUTF8(items[item], c); enclosingDesc = readUTF8(items[item] + 2, c); } - } else if (SIGNATURES && "Signature".equals(attrName)) { + } else if ("Signature".equals(attrName)) { signature = readUTF8(u + 8, c); - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleAnnotations".equals(attrName)) { anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = u + 8; } else if ("Deprecated".equals(attrName)) { access |= Opcodes.ACC_DEPRECATED; @@ -623,12 +618,16 @@ public class ClassReader { } else if ("SourceDebugExtension".equals(attrName)) { int len = readInt(u + 4); sourceDebug = readUTF(u + 8, len, new char[len]); - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + } else if ("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 +656,12 @@ public class ClassReader { 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, @@ -664,19 +669,19 @@ public class ClassReader { } // visits the class annotations and type annotations - if (ANNOTATIONS && anns != 0) { + if (anns != 0) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), true)); } } - if (ANNOTATIONS && ianns != 0) { + if (ianns != 0) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), false)); } } - if (ANNOTATIONS && tanns != 0) { + if (tanns != 0) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -684,7 +689,7 @@ public class ClassReader { context.typePath, readUTF8(v, c), true)); } } - if (ANNOTATIONS && itanns != 0) { + if (itanns != 0) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -726,6 +731,120 @@ public class ClassReader { classVisitor.visitEnd(); } + /** + * 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. * @@ -762,24 +881,20 @@ public class ClassReader { if ("ConstantValue".equals(attrName)) { int item = readUnsignedShort(u + 8); value = item == 0 ? null : readConst(item, c); - } else if (SIGNATURES && "Signature".equals(attrName)) { + } else if ("Signature".equals(attrName)) { signature = readUTF8(u + 8, c); } else if ("Deprecated".equals(attrName)) { access |= Opcodes.ACC_DEPRECATED; } else if ("Synthetic".equals(attrName)) { access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleAnnotations".equals(attrName)) { anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { itanns = u + 8; } else { Attribute attr = readAttribute(context.attrs, attrName, u + 8, @@ -801,19 +916,19 @@ public class ClassReader { } // visits the field annotations and type annotations - if (ANNOTATIONS && anns != 0) { + if (anns != 0) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, fv.visitAnnotation(readUTF8(v, c), true)); } } - if (ANNOTATIONS && ianns != 0) { + if (ianns != 0) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, fv.visitAnnotation(readUTF8(v, c), false)); } } - if (ANNOTATIONS && tanns != 0) { + if (tanns != 0) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -821,7 +936,7 @@ public class ClassReader { context.typePath, readUTF8(v, c), true)); } } - if (ANNOTATIONS && itanns != 0) { + if (itanns != 0) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -895,32 +1010,26 @@ public class ClassReader { exceptions[j] = readClass(exception, c); exception += 2; } - } else if (SIGNATURES && "Signature".equals(attrName)) { + } else if ("Signature".equals(attrName)) { signature = readUTF8(u + 8, c); } else if ("Deprecated".equals(attrName)) { context.access |= Opcodes.ACC_DEPRECATED; - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleAnnotations".equals(attrName)) { anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = u + 8; - } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { + } else if ("AnnotationDefault".equals(attrName)) { dann = u + 8; } else if ("Synthetic".equals(attrName)) { context.access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { itanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleParameterAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) { mpanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleParameterAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) { impanns = u + 8; } else if ("MethodParameters".equals(attrName)) { methodParameters = u + 8; @@ -953,7 +1062,7 @@ public class ClassReader { * access, name and descriptor can have been changed, this is not * important since they are not copied as is from the reader). */ - if (WRITER && mv instanceof MethodWriter) { + if (mv instanceof MethodWriter) { MethodWriter mw = (MethodWriter) mv; if (mw.cw.cr == this && signature == mw.signature) { boolean sameExceptions = false; @@ -990,26 +1099,26 @@ public class ClassReader { } // visits the method annotations - if (ANNOTATIONS && dann != 0) { + if (dann != 0) { AnnotationVisitor dv = mv.visitAnnotationDefault(); readAnnotationValue(dann, c, null, dv); if (dv != null) { dv.visitEnd(); } } - if (ANNOTATIONS && anns != 0) { + if (anns != 0) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, mv.visitAnnotation(readUTF8(v, c), true)); } } - if (ANNOTATIONS && ianns != 0) { + if (ianns != 0) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, mv.visitAnnotation(readUTF8(v, c), false)); } } - if (ANNOTATIONS && tanns != 0) { + if (tanns != 0) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -1017,7 +1126,7 @@ public class ClassReader { context.typePath, readUTF8(v, c), true)); } } - if (ANNOTATIONS && itanns != 0) { + if (itanns != 0) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -1025,10 +1134,10 @@ public class ClassReader { context.typePath, readUTF8(v, c), false)); } } - if (ANNOTATIONS && mpanns != 0) { + if (mpanns != 0) { readParameterAnnotations(mv, context, mpanns, true); } - if (ANNOTATIONS && impanns != 0) { + if (impanns != 0) { readParameterAnnotations(mv, context, impanns, false); } @@ -1075,7 +1184,7 @@ public class ClassReader { int codeStart = u; int codeEnd = u + codeLength; Label[] labels = context.labels = new Label[codeLength + 2]; - readLabel(codeLength + 1, labels); + createLabel(codeLength + 1, labels); while (u < codeEnd) { int offset = u - codeStart; int opcode = b[u] & 0xFF; @@ -1085,11 +1194,16 @@ public class ClassReader { u += 1; break; case ClassWriter.LABEL_INSN: - readLabel(offset + readShort(u + 1), labels); + createLabel(offset + readShort(u + 1), labels); + u += 3; + break; + case ClassWriter.ASM_LABEL_INSN: + createLabel(offset + readUnsignedShort(u + 1), labels); u += 3; break; case ClassWriter.LABELW_INSN: - readLabel(offset + readInt(u + 1), labels); + case ClassWriter.ASM_LABELW_INSN: + createLabel(offset + readInt(u + 1), labels); u += 5; break; case ClassWriter.WIDE_INSN: @@ -1104,9 +1218,9 @@ public class ClassReader { // skips 0 to 3 padding bytes u = u + 4 - (offset & 3); // reads instruction - readLabel(offset + readInt(u), labels); + createLabel(offset + readInt(u), labels); for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { - readLabel(offset + readInt(u + 12), labels); + createLabel(offset + readInt(u + 12), labels); u += 4; } u += 12; @@ -1115,9 +1229,9 @@ public class ClassReader { // skips 0 to 3 padding bytes u = u + 4 - (offset & 3); // reads instruction - readLabel(offset + readInt(u), labels); + createLabel(offset + readInt(u), labels); for (int i = readInt(u + 4); i > 0; --i) { - readLabel(offset + readInt(u + 12), labels); + createLabel(offset + readInt(u + 12), labels); u += 8; } u += 8; @@ -1147,9 +1261,9 @@ public class ClassReader { // reads the try catch entries to find the labels, and also visits them for (int i = readUnsignedShort(u); i > 0; --i) { - Label start = readLabel(readUnsignedShort(u + 2), labels); - Label end = readLabel(readUnsignedShort(u + 4), labels); - Label handler = readLabel(readUnsignedShort(u + 6), labels); + Label start = createLabel(readUnsignedShort(u + 2), labels); + Label end = createLabel(readUnsignedShort(u + 4), labels); + Label handler = createLabel(readUnsignedShort(u + 6), labels); String type = readUTF8(items[readUnsignedShort(u + 8)], c); mv.visitTryCatchBlock(start, end, handler, type); u += 8; @@ -1180,13 +1294,9 @@ public class ClassReader { varTable = u + 8; for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { int label = readUnsignedShort(v + 10); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } + createDebugLabel(label, labels); label += readUnsignedShort(v + 12); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } + createDebugLabel(label, labels); v += 10; } } @@ -1196,9 +1306,7 @@ public class ClassReader { if ((context.flags & SKIP_DEBUG) == 0) { for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { int label = readUnsignedShort(v + 10); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } + createDebugLabel(label, labels); Label l = labels[label]; while (l.line > 0) { if (l.next == null) { @@ -1210,17 +1318,15 @@ public class ClassReader { v += 4; } } - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = readTypeAnnotations(mv, context, u + 8, true); ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 : readUnsignedShort(tanns[0] + 1); - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { itanns = readTypeAnnotations(mv, context, u + 8, false); nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 : readUnsignedShort(itanns[0] + 1); - } else if (FRAMES && "StackMapTable".equals(attrName)) { + } else if ("StackMapTable".equals(attrName)) { if ((context.flags & SKIP_FRAMES) == 0) { stackMap = u + 10; stackMapSize = readInt(u + 4); @@ -1244,7 +1350,7 @@ public class ClassReader { * this by parsing the stack map table without a full decoding * (see below). */ - } else if (FRAMES && "StackMap".equals(attrName)) { + } else if ("StackMap".equals(attrName)) { if ((context.flags & SKIP_FRAMES) == 0) { zip = false; stackMap = u + 10; @@ -1273,7 +1379,7 @@ public class ClassReader { u += 2; // generates the first (implicit) stack map frame - if (FRAMES && stackMap != 0) { + if (stackMap != 0) { /* * for the first explicit frame the offset is not offset_delta + 1 * but only offset_delta; setting the implicit frame offset to -1 @@ -1306,14 +1412,31 @@ public class ClassReader { int v = readUnsignedShort(i + 1); if (v >= 0 && v < codeLength) { if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { - readLabel(v, labels); + createLabel(v, labels); } } } } } + 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; @@ -1334,7 +1457,7 @@ public class ClassReader { } // visits the frame for this offset, if any - while (FRAMES && frame != null + while (frame != null && (frame.offset == offset || frame.offset == -1)) { // if there is a frame for this offset, makes the visitor visit // it, and reads the next frame if there is one. @@ -1346,6 +1469,9 @@ public class ClassReader { 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 +1480,13 @@ public class ClassReader { 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 (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 +1511,47 @@ public class ClassReader { 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 = createLabel(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) { @@ -1636,8 +1807,8 @@ public class ClassReader { for (int j = readUnsignedShort(u + 1); j > 0; --j) { int start = readUnsignedShort(u + 3); int length = readUnsignedShort(u + 5); - readLabel(start, context.labels); - readLabel(start + length, context.labels); + createLabel(start, context.labels); + createLabel(start + length, context.labels); u += 6; } u += 3; @@ -1716,8 +1887,8 @@ public class ClassReader { for (int i = 0; i < n; ++i) { int start = readUnsignedShort(u); int length = readUnsignedShort(u + 2); - context.start[i] = readLabel(start, context.labels); - context.end[i] = readLabel(start + length, context.labels); + context.start[i] = createLabel(start, context.labels); + context.end[i] = createLabel(start + length, context.labels); context.index[i] = readUnsignedShort(u + 4); u += 6; } @@ -2137,7 +2308,7 @@ public class ClassReader { } } frame.offset += delta + 1; - readLabel(frame.offset, labels); + createLabel(frame.offset, labels); return stackMap; } @@ -2190,7 +2361,7 @@ public class ClassReader { v += 2; break; default: // Uninitialized - frame[index] = readLabel(readUnsignedShort(v), labels); + frame[index] = createLabel(readUnsignedShort(v), labels); v += 2; } return v; @@ -2216,6 +2387,39 @@ public class ClassReader { return labels[offset]; } + /** + * Creates a label without the Label.DEBUG flag set, for the given offset. + * The label is created with a call to {@link #readLabel} and its + * Label.DEBUG flag is cleared. + * + * @param offset + * a bytecode offset in a method. + * @param labels + * the already created labels, indexed by their offset. + * @return a Label without the Label.DEBUG flag set. + */ + private Label createLabel(int offset, Label[] labels) { + Label label = readLabel(offset, labels); + label.status &= ~Label.DEBUG; + return label; + } + + /** + * Creates a label with the Label.DEBUG flag set, if there is no already + * existing label for the given offset (otherwise does nothing). The label + * is created with a call to {@link #readLabel}. + * + * @param offset + * a bytecode offset in a method. + * @param labels + * the already created labels, indexed by their offset. + */ + private void createDebugLabel(int offset, Label[] labels) { + if (labels[offset] == null) { + readLabel(offset, labels).status |= Label.DEBUG; + } + } + /** * Returns the start index of the attribute_info structure of this class. * @@ -2470,6 +2674,20 @@ public class ClassReader { return new String(buf, 0, strLen); } + /** + * 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 @@ -2484,44 +2702,41 @@ public class ClassReader { * @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 +2765,6 @@ public class ClassReader { 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 index f95597e2317b5b0815eb8cd92cb932ed3cb5e4ce..5a9e5bb3f8c58e9815b339b9e3b43b1b6e637df9 100644 --- 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 @@ package jdk.internal.org.objectweb.asm; /** * A visitor to visit a Java class. The methods of this class must be called in * the following order: visit [ visitSource ] [ - * visitOuterClass ] ( visitAnnotation | + * visitModule ][ visitOuterClass ] ( visitAnnotation | * visitTypeAnnotation | visitAttribute )* ( * visitInnerClass | visitField | visitMethod )* * visitEnd. @@ -72,7 +72,7 @@ public abstract class ClassVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} 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 @@ public abstract class ClassVisitor { * * @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 @@ public abstract class ClassVisitor { * * @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; @@ -160,6 +160,28 @@ public abstract class ClassVisitor { } } + /** + * 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 index bd0978c0c097063e1622f4669c2bb31bed470545..9d974b2f8efa8ef9183be3292582a0f6b24d3745 100644 --- 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 @@ public class ClassWriter extends ClassVisitor { * {@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) */ @@ -196,6 +196,27 @@ public class ClassWriter extends ClassVisitor { */ 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. */ @@ -284,7 +305,7 @@ public class ClassWriter extends ClassVisitor { /** * The base value for all CONSTANT_MethodHandle constant pool items. * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9 - * different items. + * different items (from 21 to 29). */ static final int HANDLE_BASE = 20; @@ -433,6 +454,11 @@ public class ClassWriter extends ClassVisitor { */ 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 @@ public class ClassWriter extends ClassVisitor { MethodWriter lastMethod; /** - * true if the maximum stack size and number of local variables - * must be automatically computed. - */ - private boolean computeMaxs; - - /** - * true if the stack map frames must be recomputed from scratch. + * Indicates what must be automatically computed. + * + * @see MethodWriter#compute */ - private boolean computeFrames; + private int compute; /** - * 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). + * 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. */ - boolean invalidFrames; + boolean hasAsmInsns; // ------------------------------------------------------------------------ // Static initializer @@ -552,11 +572,11 @@ public class ClassWriter extends ClassVisitor { */ 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 @@ public class ClassWriter extends ClassVisitor { // // 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 @@ public class ClassWriter extends ClassVisitor { * {@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 @@ public class ClassWriter extends ClassVisitor { 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 @@ public class ClassWriter extends ClassVisitor { * @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,9 +727,9 @@ public class ClassWriter extends ClassVisitor { 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) { + if (signature != null) { this.signature = newUTF8(signature); } this.superName = superName == null ? 0 : newClass(superName); @@ -731,6 +753,14 @@ public class ClassWriter extends ClassVisitor { } } + @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) { @@ -743,9 +773,6 @@ public class ClassWriter extends ClassVisitor { @Override public final AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(newUTF8(desc)).putShort(0); @@ -763,9 +790,6 @@ public class ClassWriter extends ClassVisitor { @Override public final AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info AnnotationWriter.putTarget(typeRef, typePath, bv); @@ -805,7 +829,7 @@ public class ClassWriter extends ClassVisitor { // 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 +854,7 @@ public class ClassWriter extends ClassVisitor { 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 @@ -874,7 +898,7 @@ public class ClassWriter extends ClassVisitor { size += 8 + bootstrapMethods.length; newUTF8("BootstrapMethods"); } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { ++attributeCount; size += 8; newUTF8("Signature"); @@ -912,26 +936,31 @@ public class ClassWriter extends ClassVisitor { size += 8 + innerClasses.length; newUTF8("InnerClasses"); } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { ++attributeCount; size += 8 + anns.getSize(); newUTF8("RuntimeVisibleAnnotations"); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { ++attributeCount; size += 8 + ianns.getSize(); newUTF8("RuntimeInvisibleAnnotations"); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { ++attributeCount; size += 8 + tanns.getSize(); newUTF8("RuntimeVisibleTypeAnnotations"); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { ++attributeCount; 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); @@ -968,7 +997,7 @@ public class ClassWriter extends ClassVisitor { bootstrapMethodsCount); out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); } if (sourceFile != 0) { @@ -979,6 +1008,11 @@ public class ClassWriter extends ClassVisitor { 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); @@ -997,41 +1031,46 @@ public class ClassWriter extends ClassVisitor { out.putInt(innerClasses.length + 2).putShort(innerClassesCount); out.putByteArray(innerClasses.data, 0, innerClasses.length); } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { out.putShort(newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { out.putShort(newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { out.putShort(newUTF8("RuntimeVisibleTypeAnnotations")); tanns.put(out); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations")); itanns.put(out); } 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; - innerClassesCount = 0; - innerClasses = null; - bootstrapMethodsCount = 0; - bootstrapMethods = null; + moduleWriter = 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 +1117,16 @@ public class ClassWriter extends ClassVisitor { 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 +1175,21 @@ public class ClassWriter extends ClassVisitor { } /** - * 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,87 +1207,52 @@ public class ClassWriter extends ClassVisitor { * @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; + return newStringishItem(CLASS, value).index; } /** - * Adds a package name to the constant pool. - * - * Does nothing if the constant pool already contains a similar item. + * 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 value - * the internal name of the package. - * @return the index of a new or already existing package reference item. + * @param methodDesc + * method descriptor of the method type. + * @return the index of a new or already existing method type 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; + public int newMethodType(final String methodDesc) { + return newStringishItem(MTYPE, methodDesc).index; } /** - * Adds a method type reference to the constant pool of the class being + * 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 methodDesc - * method descriptor of the method type. - * @return a new or already existing method type reference item. + * @param moduleName + * name of the module. + * @return the index of a new or already existing module 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; + public int newModule(final String moduleName) { + return newStringishItem(MODULE, moduleName).index; } /** - * Adds a method type reference to the constant pool of the class being + * 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 methodDesc - * method descriptor of the method type. - * @return the index of a new or already existing method type reference + * @param packageName + * name of the package in its internal form. + * @return the index of a new or already existing module reference * item. */ - public int newMethodType(final String methodDesc) { - return newMethodTypeItem(methodDesc).index; + public int newPackage(final String packageName) { + return newStringishItem(PACKAGE, packageName).index; } /** @@ -1628,25 +1633,6 @@ public class ClassWriter extends ClassVisitor { return result; } - /** - * 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 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 index 0000000000000000000000000000000000000000..7429fac2a6e41e88ed051e5abd584c7dd86b143a --- /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 index 7f16c4e70b3de823c7e5c8080a16fbd57ee85e52..127c22c1709330beaa19a2366605b0cd72b4fef2 100644 --- 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 @@ public abstract class FieldVisitor { /** * 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 @@ public abstract class FieldVisitor { * * @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 @@ public abstract class FieldVisitor { * * @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 index b30eeacb25244250969e604b3ebd204af5779757..09a0f24db2c28b8cf4ba8c70e7f9735fd0396a9a 100644 --- 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 @@ final class FieldWriter extends FieldVisitor { */ 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 { @@ -158,7 +158,7 @@ final class FieldWriter extends FieldVisitor { this.access = access; this.name = cw.newUTF8(name); this.desc = cw.newUTF8(desc); - if (ClassReader.SIGNATURES && signature != null) { + if (signature != null) { this.signature = cw.newUTF8(signature); } if (value != null) { @@ -173,9 +173,6 @@ final class FieldWriter extends FieldVisitor { @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(cw.newUTF8(desc)).putShort(0); @@ -193,9 +190,6 @@ final class FieldWriter extends FieldVisitor { @Override public AnnotationVisitor visitTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info AnnotationWriter.putTarget(typeRef, typePath, bv); @@ -249,23 +243,23 @@ final class FieldWriter extends FieldVisitor { cw.newUTF8("Deprecated"); size += 6; } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { cw.newUTF8("Signature"); size += 8; } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { cw.newUTF8("RuntimeVisibleAnnotations"); size += 8 + anns.getSize(); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { cw.newUTF8("RuntimeInvisibleAnnotations"); size += 8 + ianns.getSize(); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { cw.newUTF8("RuntimeVisibleTypeAnnotations"); size += 8 + tanns.getSize(); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { cw.newUTF8("RuntimeInvisibleTypeAnnotations"); size += 8 + itanns.getSize(); } @@ -299,19 +293,19 @@ final class FieldWriter extends FieldVisitor { if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { ++attributeCount; } if (attrs != null) { @@ -331,23 +325,23 @@ final class FieldWriter extends FieldVisitor { if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { out.putShort(cw.newUTF8("Signature")); out.putInt(2).putShort(signature); } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); tanns.put(out); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); itanns.put(out); } 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 index bb7ff8f514775d2e7f565437448ad5c8e8481e89..d34bfa84a0d04f403d01f4dcbc8c9e44d8ecb174 100644 --- 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 @@ package jdk.internal.org.objectweb.asm; * * @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 @@ final class Frame { * 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. @@ -549,6 +549,110 @@ final class Frame { */ 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. * @@ -614,7 +718,7 @@ final class Frame { } // 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 @@ final class Frame { * 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 @@ final class Frame { * @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]; @@ -981,7 +1085,7 @@ final class Frame { case Opcodes.AALOAD: pop(1); t1 = pop(); - push(ELEMENT_OF + t1); + push(t1 == NULL ? t1 : ELEMENT_OF + t1); break; case Opcodes.ISTORE: case Opcodes.FSTORE: @@ -1312,7 +1416,7 @@ final class Frame { * @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 index b0b80907d9d81b7440cd6aa7c25197819c26ef32..08e7acd2050d412ca57118d41390f81eb5ec490b 100644 --- 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 @@ final class Item { * {@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 @@ final class Item { 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 index 63e42a020bcdbdadd372c5742c9c51f8ca6900f0..df380a9953de616d9f8ed174798a1b323e1c5a9a 100644 --- 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 @@ public class Label { * 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. @@ -454,7 +453,7 @@ public class Label { * @return the first label of the series to which this label belongs. */ Label getFirst() { - return !ClassReader.FRAMES || frame == null ? this : frame.owner; + return frame == null ? this : frame.owner; } // ------------------------------------------------------------------------ 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 index 1448067a4676ae82f6d5fbe19f72b37e23834bba..35c3c0f574953ee645faf270f4f300e0fec51b37 100644 --- 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 @@ public abstract class MethodVisitor { /** * 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 @@ public abstract class MethodVisitor { * * @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 @@ public abstract class MethodVisitor { * * @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 index c2e4031e304f37095be148b6413d1fa34a01eb59..92f252363c69a7a816bdcc95e2f331abd6accdfc 100644 --- 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 @@ class MethodWriter extends MethodVisitor { * * @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 @@ class MethodWriter extends MethodVisitor { * * @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 @@ class MethodWriter extends MethodVisitor { /** * Number of stack map frames in the StackMapTable attribute. */ - private int frameCount; + int frameCount; /** * The StackMapTable attribute. @@ -383,11 +395,6 @@ class MethodWriter extends MethodVisitor { */ 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. */ @@ -409,6 +416,7 @@ class MethodWriter extends MethodVisitor { * Indicates what must be automatically computed. * * @see #FRAMES + * @see #INSERTED_FRAMES * @see #MAXS * @see #NOTHING */ @@ -471,18 +479,13 @@ class MethodWriter extends MethodVisitor { * @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 { @@ -497,9 +500,7 @@ class MethodWriter extends MethodVisitor { this.name = cw.newUTF8(name); this.desc = cw.newUTF8(desc); this.descriptor = desc; - if (ClassReader.SIGNATURES) { - this.signature = signature; - } + this.signature = signature; if (exceptions != null && exceptions.length > 0) { exceptionCount = exceptions.length; this.exceptions = new int[exceptionCount]; @@ -507,8 +508,8 @@ class MethodWriter extends MethodVisitor { 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) { @@ -539,9 +540,6 @@ class MethodWriter extends MethodVisitor { @Override public AnnotationVisitor visitAnnotationDefault() { - if (!ClassReader.ANNOTATIONS) { - return null; - } annd = new ByteVector(); return new AnnotationWriter(cw, false, annd, null, 0); } @@ -549,9 +547,6 @@ class MethodWriter extends MethodVisitor { @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(cw.newUTF8(desc)).putShort(0); @@ -569,9 +564,6 @@ class MethodWriter extends MethodVisitor { @Override public AnnotationVisitor visitTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info AnnotationWriter.putTarget(typeRef, typePath, bv); @@ -592,9 +584,6 @@ class MethodWriter extends MethodVisitor { @Override public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); if ("Ljava/lang/Synthetic;".equals(desc)) { // workaround for a bug in javac with synthetic parameters @@ -639,11 +628,33 @@ class MethodWriter extends MethodVisitor { @Override public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) { - if (!ClassReader.FRAMES || compute == FRAMES) { + if (compute == FRAMES) { 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 +662,10 @@ class MethodWriter extends MethodVisitor { 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 +674,10 @@ class MethodWriter extends MethodVisitor { } 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 +758,7 @@ class MethodWriter extends MethodVisitor { // 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 +781,7 @@ class MethodWriter extends MethodVisitor { 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 +806,7 @@ class MethodWriter extends MethodVisitor { 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 +863,10 @@ class MethodWriter extends MethodVisitor { @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 +889,7 @@ class MethodWriter extends MethodVisitor { 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 +929,7 @@ class MethodWriter extends MethodVisitor { 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 +981,7 @@ class MethodWriter extends MethodVisitor { 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 +1015,9 @@ class MethodWriter extends MethodVisitor { } @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 +1032,8 @@ class MethodWriter extends MethodVisitor { // 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 +1065,8 @@ class MethodWriter extends MethodVisitor { /* * 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 +1082,21 @@ class MethodWriter extends MethodVisitor { 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 +1124,7 @@ class MethodWriter extends MethodVisitor { @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 +1157,18 @@ class MethodWriter extends MethodVisitor { 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 +1194,7 @@ class MethodWriter extends MethodVisitor { 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 +1226,7 @@ class MethodWriter extends MethodVisitor { 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 +1310,10 @@ class MethodWriter extends MethodVisitor { @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 @@ -1289,9 +1328,6 @@ class MethodWriter extends MethodVisitor { @Override public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8); @@ -1331,9 +1367,6 @@ class MethodWriter extends MethodVisitor { @Override public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info AnnotationWriter.putTarget(typeRef, typePath, bv); @@ -1387,9 +1420,6 @@ class MethodWriter extends MethodVisitor { public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info bv.putByte(typeRef >>> 24).putShort(start.length); @@ -1430,15 +1460,7 @@ class MethodWriter extends MethodVisitor { @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) { + if (compute == FRAMES) { // completes the control flow graph with exception handler blocks Handler handler = firstHandler; while (handler != null) { @@ -1468,8 +1490,8 @@ class MethodWriter extends MethodVisitor { // 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 +1739,9 @@ class MethodWriter extends MethodVisitor { } else { currentBlock.outputStackMax = maxStackSize; } - currentBlock = null; + if (compute != INSERTED_FRAMES) { + currentBlock = null; + } } // ------------------------------------------------------------------------ @@ -1789,7 +1813,7 @@ class MethodWriter extends MethodVisitor { 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 +1825,16 @@ class MethodWriter extends MethodVisitor { 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 +1846,7 @@ class MethodWriter extends MethodVisitor { ++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) != ';') { @@ -2083,11 +2106,11 @@ class MethodWriter extends MethodVisitor { cw.newUTF8(zip ? "StackMapTable" : "StackMap"); size += 8 + stackMap.length; } - if (ClassReader.ANNOTATIONS && ctanns != null) { + if (ctanns != null) { cw.newUTF8("RuntimeVisibleTypeAnnotations"); size += 8 + ctanns.getSize(); } - if (ClassReader.ANNOTATIONS && ictanns != null) { + if (ictanns != null) { cw.newUTF8("RuntimeInvisibleTypeAnnotations"); size += 8 + ictanns.getSize(); } @@ -2111,7 +2134,7 @@ class MethodWriter extends MethodVisitor { cw.newUTF8("Deprecated"); size += 6; } - if (ClassReader.SIGNATURES && signature != null) { + if (signature != null) { cw.newUTF8("Signature"); cw.newUTF8(signature); size += 8; @@ -2120,34 +2143,34 @@ class MethodWriter extends MethodVisitor { cw.newUTF8("MethodParameters"); size += 7 + methodParameters.length; } - if (ClassReader.ANNOTATIONS && annd != null) { + if (annd != null) { cw.newUTF8("AnnotationDefault"); size += 6 + annd.length; } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { cw.newUTF8("RuntimeVisibleAnnotations"); size += 8 + anns.getSize(); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { cw.newUTF8("RuntimeInvisibleAnnotations"); size += 8 + ianns.getSize(); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { cw.newUTF8("RuntimeVisibleTypeAnnotations"); size += 8 + tanns.getSize(); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { cw.newUTF8("RuntimeInvisibleTypeAnnotations"); size += 8 + itanns.getSize(); } - if (ClassReader.ANNOTATIONS && panns != null) { + if (panns != null) { cw.newUTF8("RuntimeVisibleParameterAnnotations"); size += 7 + 2 * (panns.length - synthetics); for (int i = panns.length - 1; i >= synthetics; --i) { size += panns[i] == null ? 0 : panns[i].getSize(); } } - if (ClassReader.ANNOTATIONS && ipanns != null) { + if (ipanns != null) { cw.newUTF8("RuntimeInvisibleParameterAnnotations"); size += 7 + 2 * (ipanns.length - synthetics); for (int i = ipanns.length - 1; i >= synthetics; --i) { @@ -2193,31 +2216,31 @@ class MethodWriter extends MethodVisitor { if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; } - if (ClassReader.SIGNATURES && signature != null) { + if (signature != null) { ++attributeCount; } if (methodParameters != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && annd != null) { + if (annd != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && panns != null) { + if (panns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ipanns != null) { + if (ipanns != null) { ++attributeCount; } if (attrs != null) { @@ -2238,10 +2261,10 @@ class MethodWriter extends MethodVisitor { if (stackMap != null) { size += 8 + stackMap.length; } - if (ClassReader.ANNOTATIONS && ctanns != null) { + if (ctanns != null) { size += 8 + ctanns.getSize(); } - if (ClassReader.ANNOTATIONS && ictanns != null) { + if (ictanns != null) { size += 8 + ictanns.getSize(); } if (cattrs != null) { @@ -2273,10 +2296,10 @@ class MethodWriter extends MethodVisitor { if (stackMap != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ctanns != null) { + if (ctanns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ictanns != null) { + if (ictanns != null) { ++attributeCount; } if (cattrs != null) { @@ -2304,11 +2327,11 @@ class MethodWriter extends MethodVisitor { out.putInt(stackMap.length + 2).putShort(frameCount); out.putByteArray(stackMap.data, 0, stackMap.length); } - if (ClassReader.ANNOTATIONS && ctanns != null) { + if (ctanns != null) { out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); ctanns.put(out); } - if (ClassReader.ANNOTATIONS && ictanns != null) { + if (ictanns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); ictanns.put(out); } @@ -2333,7 +2356,7 @@ class MethodWriter extends MethodVisitor { if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); } - if (ClassReader.SIGNATURES && signature != null) { + if (signature != null) { out.putShort(cw.newUTF8("Signature")).putInt(2) .putShort(cw.newUTF8(signature)); } @@ -2343,32 +2366,32 @@ class MethodWriter extends MethodVisitor { methodParametersCount); out.putByteArray(methodParameters.data, 0, methodParameters.length); } - if (ClassReader.ANNOTATIONS && annd != null) { + if (annd != null) { out.putShort(cw.newUTF8("AnnotationDefault")); out.putInt(annd.length); out.putByteArray(annd.data, 0, annd.length); } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); tanns.put(out); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); itanns.put(out); } - if (ClassReader.ANNOTATIONS && panns != null) { + if (panns != null) { out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); AnnotationWriter.put(panns, synthetics, out); } - if (ClassReader.ANNOTATIONS && ipanns != null) { + if (ipanns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); AnnotationWriter.put(ipanns, synthetics, out); } @@ -2376,569 +2399,4 @@ class MethodWriter extends MethodVisitor { 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 index 0000000000000000000000000000000000000000..bf478c15854c4b47345951728621d6ba0c09442a --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleVisitor.java @@ -0,0 +1,219 @@ +/* + * 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: visitMainClass | ( visitPackage | + * visitRequire | visitExport | visitOpen | + * visitUse | visitProvide )* visitEnd. + * + * The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)}, + * {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)} + * take as parameter a package name or a module name. Unlike the other names which are internal names + * (names separated by slash), module and package names are qualified names (names separated by dot). + * + * @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; + + /** + * Constructs a new {@link ModuleVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}. + */ + public ModuleVisitor(final int api) { + this(api, null); + } + + /** + * Constructs a new {@link ModuleVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}. + * @param mv + * the module 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 internal name of the main class of the current module. + */ + public void visitMainClass(String mainClass) { + if (mv != null) { + mv.visitMainClass(mainClass); + } + } + + /** + * Visit a package of the current module. + * + * @param packaze the qualified name of a package. + */ + public void visitPackage(String packaze) { + if (mv != null) { + mv.visitPackage(packaze); + } + } + + /** + * Visits a dependence of the current module. + * + * @param module the qualified 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 qualified 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 the qualified 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 qualified 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 the qualified 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 internal name of an interface or a 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); + } + } + + /** + * Visits the end of the module. This method, which is the last one to be + * called, is used to inform the visitor that everything have been visited. + */ + 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 index 0000000000000000000000000000000000000000..c14432ba858d0a9032cd2c4dcc609e9034f67820 --- /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 index e6a7cded42f37211e0c3a4710532e26a3d6dc3b0..4dc3ff19c5c91ef022efd9192572dbea0f49048c 100644 --- 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 @@ package jdk.internal.org.objectweb.asm; * @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 @@ -88,7 +88,7 @@ public interface Opcodes { int V1_6 = 0 << 16 | 50; int V1_7 = 0 << 16 | 51; int V1_8 = 0 << 16 | 52; - int V1_9 = 0 << 16 | 53; + int V9 = 0 << 16 | 53; // access flags @@ -99,18 +99,23 @@ public interface Opcodes { 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 @@ public interface Opcodes { */ 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 index 056ace15fa8c18c57707cb57a5b8a29fb69cfd68..2bbb94928f93c1b70e89519b9c25f11ed460dc7f 100644 --- 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 class Type { */ 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 index 00dccd549f014a242c1ed2404ef9a0f03bbbfa5e..f24b8604593495b9a9b1405afc737b936285ba2f 100644 --- 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 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes * * @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 index b761babb1386b7e4002ee5e21f8dc6e0bbe09184..3f3acf07be3d42fa041763f99ecfc331ac24fbde 100644 --- 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 class AnalyzerAdapter extends MethodVisitor { */ 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 @@ public class AnalyzerAdapter extends MethodVisitor { * * @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 @@ -690,6 +690,8 @@ public class AnalyzerAdapter extends MethodVisitor { t1 = pop(); if (t1 instanceof String) { pushDesc(((String) t1).substring(1)); + } else if (t1 == Opcodes.NULL) { + push(t1); } else { push("java/lang/Object"); } 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 index 3482ac95f6c933dc8fcaba3a9b04740d150643ec..8411f3407f00d167bf9ffecedf13386380c37445 100644 --- 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 class AnnotationRemapper extends AnnotationVisitor { 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 index 8a8ea738ae98317cfcc14283aaec7fb621da02c5..f60833561fc45c4b9151604a8b60c441a6f0edc4 100644 --- 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 @@ public class ClassRemapper extends ClassVisitor { 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, @@ -96,6 +100,12 @@ public class ClassRemapper extends ClassVisitor { interfaces == null ? null : remapper.mapTypes(interfaces)); } + @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), @@ -111,6 +121,18 @@ public class ClassRemapper extends ClassVisitor { return av == null ? null : createAnnotationRemapper(av); } + @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) { @@ -158,4 +180,8 @@ public class ClassRemapper extends ClassVisitor { 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 index 0a41b2b8af695024b8653d7aee143e9c2dbab293..5826b563a8e537b516889dfa244b76d998becd63 100644 --- 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 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { 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 index 13f8b7fd15451ce2e9b9655b1df0adb4da7412d3..c334066bd8722c2f9e0b1b85e460b52b38c63787 100644 --- 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 @@ public class FieldRemapper extends FieldVisitor { 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 index e198de78ce33f583de574e901c80a1950aa89128..7b19f55e8712075fa97b46945b77e8abe7168afa 100644 --- 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 class GeneratorAdapter extends LocalVariablesSorter { */ 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 @@ public class GeneratorAdapter extends LocalVariablesSorter { * * @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 index 2df144ef70c2ad65fa5bb0c757dd8eca56560625..c303362f4e93b91da1b66cbc7552080b810951b1 100644 --- 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 @@ public class InstructionAdapter extends MethodVisitor { * 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 @@ public class InstructionAdapter extends MethodVisitor { * * @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 index e0514114e517792b4342fce8191b172d9ec790fb..905e035ef0b54407a32501d40fb0de2047460d0e 100644 --- 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 class JSRInlinerAdapter extends MethodNode implements Opcodes { 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 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { * * @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 index 7aad39658e81b0c93538bc1a39d65dcbd796aadb..d96de75e733823d2269f08a307c393a63b31f6e3 100644 --- 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 class LocalVariablesSorter extends MethodVisitor { */ 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 @@ public class LocalVariablesSorter extends MethodVisitor { * * @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 index 486cc6b7c57d5e6c2ba1a279bb8168c9014a4a1f..3a3dc9e2d06f26a7ec3b52f8f013a39f15770891 100644 --- 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 @@ public class MethodRemapper extends MethodVisitor { 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 @@ public class MethodRemapper extends MethodVisitor { } 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 index 0000000000000000000000000000000000000000..fda1c686c79b4c593ea7d3fa32ddf23ad9eb6774 --- /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 index 0000000000000000000000000000000000000000..0da0469588395f0de2e7c7c17075824347d2a67f --- /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 index 0000000000000000000000000000000000000000..b561a526b6b30c407af1c14139b62e8e4a04146a --- /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 index 0000000000000000000000000000000000000000..ec8a553e9a4f00f84830296ecba6a7c19abff521 --- /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 index b90aee055906e9d5b270812293b598da8a9c4512..f5dabc5cb08e9680f1fd0e5f2a7e472897b6df42 100644 --- 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 @@ -254,6 +254,28 @@ public abstract class Remapper { return name; } + /** + * 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. * 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 index f16da4bdd0935c74ca5867332b30061d1c015e03..bdd88bf2db25fcdc93a3d2c0a9c4a1d190f2270e 100644 --- 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 class RemappingAnnotationAdapter extends AnnotationVisitor { 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 index e36d79e931db7cc51bbd1c6fd402664c3269074c..0d1df6731858bb5448d2c3d8a6abf04a17cdcad9 100644 --- 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.AnnotationVisitor; 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 @@ public class RemappingClassAdapter extends ClassVisitor { 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, @@ -98,6 +99,11 @@ public class RemappingClassAdapter extends ClassVisitor { interfaces == null ? null : remapper.mapTypes(interfaces)); } + @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), 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 index 8bafee1bf4a93d6b3d0b88e606c0f915a7649ae9..f0e86850aba20d8ef68203bb1c83aba3b3c30589 100644 --- 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 @@ public class RemappingFieldAdapter extends FieldVisitor { 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 index 7bd76903eb4d8c169cb958148b467ff35092d424..4df3e30e1b8256e1546f18376e1fefc54208e650 100644 --- 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 class RemappingMethodAdapter extends LocalVariablesSorter { 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 @@ public class RemappingMethodAdapter extends LocalVariablesSorter { } 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 index 4aa8428f344dd82ba2a447613c44ff821e7f9880..1571b7a24f5e911bc7e794b77ce8bdda297b5e27 100644 --- 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 class RemappingSignatureAdapter extends SignatureVisitor { 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 index e70bb1de5d525b7cc6f8f084febe813f7a2f8fe3..57cf619939d3bbc96855d2e94fa1d0c2b5fa2d8f 100644 --- 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 @@ import jdk.internal.org.objectweb.asm.Opcodes; * 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 index 2f2f3b6ddcb579c947087e591639e81cfb231fd6..e7a02edb8542d3a45c4f4ccae9756c4eb9636343 100644 --- 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 @@ public class StaticInitMerger extends ClassVisitor { 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 index 39c2bf37904ad74cbff3050a43c9f3800e051a2f..fcf1eb8e914b9bba85004bb8ef2b851b5b365c3b 100644 --- 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 class TryCatchBlockSorter extends MethodNode { public TryCatchBlockSorter(final MethodVisitor mv, final int access, final String name, final String desc, final String signature, final String[] exceptions) { - this(Opcodes.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 index 8ad2de612301ca8d269613a2c68c9d42bf4fe346..a4597e1b254561e4cc6892d6a5e92dd1855e5c55 100644 --- 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 @@ public abstract class SignatureVisitor { /** * 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 @@ public abstract class SignatureVisitor { * * @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 index a1eceb8d5c94720c85783dab3cd59219990ee9eb..18cce485a9b1f151efacfffad4dac7179f18274c 100644 --- 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 @@ public class SignatureWriter extends SignatureVisitor { * 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 index 1bb9925df04b2f26aaa3a1d8b332fc4eb16cfff5..f35dc7700afcc0813d2117446a944b205124ea54 100644 --- 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.AnnotationVisitor; 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 @@ public class AnnotationNode extends AnnotationVisitor { * as two consecutive elements in the list. The name is a {@link String}, * and the value may be a {@link Byte}, {@link Boolean}, {@link Character}, * {@link Short}, {@link Integer}, {@link Long}, {@link Float}, - * {@link Double}, {@link String} or {@link 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 @@ public class AnnotationNode extends AnnotationVisitor { * 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 @@ public class AnnotationNode extends AnnotationVisitor { * * @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 @@ public class AnnotationNode extends AnnotationVisitor { * where the visited values must be stored. */ AnnotationNode(final List values) { - super(Opcodes.ASM5); + super(Opcodes.ASM6); this.values = values; } @@ -143,7 +143,65 @@ public class AnnotationNode extends AnnotationVisitor { if (this.desc != null) { values.add(name); } - values.add(value); + if (value instanceof byte[]) { + byte[] v = (byte[]) value; + ArrayList l = new ArrayList(v.length); + for (byte b : v) { + l.add(b); + } + values.add(l); + } else if (value instanceof boolean[]) { + boolean[] v = (boolean[]) value; + ArrayList l = new ArrayList(v.length); + for (boolean b : v) { + l.add(b); + } + values.add(l); + } else if (value instanceof short[]) { + short[] v = (short[]) value; + ArrayList l = new ArrayList(v.length); + for (short s : v) { + l.add(s); + } + values.add(l); + } else if (value instanceof char[]) { + char[] v = (char[]) value; + ArrayList l = new ArrayList(v.length); + for (char c : v) { + l.add(c); + } + values.add(l); + } else if (value instanceof int[]) { + int[] v = (int[]) value; + ArrayList l = new ArrayList(v.length); + for (int i : v) { + l.add(i); + } + values.add(l); + } else if (value instanceof long[]) { + long[] v = (long[]) value; + ArrayList l = new ArrayList(v.length); + for (long lng : v) { + l.add(lng); + } + values.add(l); + } else if (value instanceof float[]) { + float[] v = (float[]) value; + ArrayList l = new ArrayList(v.length); + for (float f : v) { + l.add(f); + } + values.add(l); + } else if (value instanceof double[]) { + double[] v = (double[]) value; + ArrayList l = new ArrayList(v.length); + for (double d : v) { + l.add(d); + } + values.add(l); + } else { + values.add(value); + } } @Override @@ -200,8 +258,8 @@ public class AnnotationNode extends AnnotationVisitor { * versions of the ASM API than the given version. * * @param api - * an ASM API version. Must be one of {@link Opcodes#ASM4} or - * {@link Opcodes#ASM5}. + * an ASM API version. Must be one of {@link Opcodes#ASM4}, + * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ public void check(final int api) { // nothing to do diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java index 39334641754cfe3fbc25416ff5ef78e97868ed63..295ac6486c9f84d16fa4421bbf5768f3b9c033dd 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java @@ -67,6 +67,7 @@ import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.ModuleVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.TypePath; @@ -126,6 +127,11 @@ public class ClassNode extends ClassVisitor { */ public String sourceDebug; + /** + * Module information. May be null. + */ + public ModuleNode module; + /** * The internal name of the enclosing class of the class. May be * null. @@ -221,7 +227,7 @@ public class ClassNode extends ClassVisitor { * If a subclass calls this constructor. */ public ClassNode() { - this(Opcodes.ASM5); + this(Opcodes.ASM6); if (getClass() != ClassNode.class) { throw new IllegalStateException(); } @@ -232,7 +238,7 @@ public class ClassNode extends ClassVisitor { * * @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 ClassNode(final int api) { super(api); @@ -266,6 +272,12 @@ public class ClassNode extends ClassVisitor { sourceDebug = debug; } + @Override + public ModuleVisitor visitModule(final String name, final int access, + final String version) { + return module = new ModuleNode(name, access, version); + } + @Override public void visitOuterClass(final String owner, final String name, final String desc) { @@ -358,11 +370,16 @@ public class ClassNode extends ClassVisitor { * API than the given version. * * @param api - * an ASM API version. Must be one of {@link Opcodes#ASM4} or - * {@link Opcodes#ASM5}. + * an ASM API version. Must be one of {@link Opcodes#ASM4}, + * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ public void check(final int api) { - if (api == Opcodes.ASM4) { + if (api < Opcodes.ASM6) { + if (module != null) { + throw new RuntimeException(); + } + } + if (api < Opcodes.ASM5) { if (visibleTypeAnnotations != null && visibleTypeAnnotations.size() > 0) { throw new RuntimeException(); @@ -371,12 +388,31 @@ public class ClassNode extends ClassVisitor { && invisibleTypeAnnotations.size() > 0) { throw new RuntimeException(); } - for (FieldNode f : fields) { - f.check(api); - } - for (MethodNode m : methods) { - m.check(api); - } + } + // checks attributes + int i, n; + n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); + for (i = 0; i < n; ++i) { + visibleAnnotations.get(i).check(api); + } + n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); + for (i = 0; i < n; ++i) { + invisibleAnnotations.get(i).check(api); + } + n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); + for (i = 0; i < n; ++i) { + visibleTypeAnnotations.get(i).check(api); + } + n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations + .size(); + for (i = 0; i < n; ++i) { + invisibleTypeAnnotations.get(i).check(api); + } + for (FieldNode f : fields) { + f.check(api); + } + for (MethodNode m : methods) { + m.check(api); } } @@ -395,6 +431,10 @@ public class ClassNode extends ClassVisitor { if (sourceFile != null || sourceDebug != null) { cv.visitSource(sourceFile, sourceDebug); } + // visits module + if (module != null) { + module.accept(cv); + } // visits outer class if (outerClass != null) { cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc); diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java index cc79a5815cbc8689389aa0dbc49c873ac5201d2b..0cf0500ad9ea384eef479916a9e783406e831a7e 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java @@ -173,7 +173,7 @@ public class FieldNode extends FieldVisitor { */ public FieldNode(final int access, final String name, final String desc, final String signature, final Object value) { - this(Opcodes.ASM5, access, name, desc, signature, value); + this(Opcodes.ASM6, access, name, desc, signature, value); if (getClass() != FieldNode.class) { throw new IllegalStateException(); } @@ -276,8 +276,8 @@ public class FieldNode extends FieldVisitor { * API than the given version. * * @param api - * an ASM API version. Must be one of {@link Opcodes#ASM4} or - * {@link Opcodes#ASM5}. + * an ASM API version. Must be one of {@link Opcodes#ASM4}, + * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ public void check(final int api) { if (api == Opcodes.ASM4) { diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java index 768130c94c171d0698ff33c1444b2ae5d783706b..f05ba2f21a61ca00d06a1f8d6aa0c3758c1d0faf 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java @@ -634,14 +634,28 @@ public class InsnList { } public void add(Object o) { - InsnList.this.insertBefore(next, (AbstractInsnNode) o); + if (next != null) { + InsnList.this.insertBefore(next, (AbstractInsnNode) o); + } else if (prev != null) { + InsnList.this.insert(prev, (AbstractInsnNode) o); + } else { + InsnList.this.add((AbstractInsnNode) o); + } prev = (AbstractInsnNode) o; remove = null; } public void set(Object o) { - InsnList.this.set(next.prev, (AbstractInsnNode) o); - prev = (AbstractInsnNode) o; + if (remove != null) { + InsnList.this.set(remove, (AbstractInsnNode) o); + if (remove == prev) { + prev = (AbstractInsnNode) o; + } else { + next = (AbstractInsnNode) o; + } + } else { + throw new IllegalStateException(); + } } } } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java index 6bb549b5abbb39e06f23e00e30f1a1cfb04dce12..faab44e7215e606bf07a0c737a91c7ffc7fee8aa 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java @@ -122,7 +122,7 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode { */ public LocalVariableAnnotationNode(int typeRef, TypePath typePath, LabelNode[] start, LabelNode[] end, int[] index, String desc) { - this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc); + this(Opcodes.ASM6, typeRef, typePath, start, end, index, desc); } /** @@ -130,7 +130,7 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode { * * @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 typeRef * a reference to the annotated type. See {@link TypeReference}. * @param start @@ -181,6 +181,6 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode { index[i] = this.index.get(i); } accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end, - index, desc, true)); + index, desc, visible)); } } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java index 1561442761a1be51d9119a043c9407bba69c4c6d..a6868e6e78082481b1e902e517223035491b51a1 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java @@ -249,7 +249,7 @@ public class MethodNode extends MethodVisitor { * If a subclass calls this constructor. */ public MethodNode() { - this(Opcodes.ASM5); + this(Opcodes.ASM6); if (getClass() != MethodNode.class) { throw new IllegalStateException(); } @@ -260,7 +260,7 @@ public class MethodNode extends MethodVisitor { * * @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 MethodNode(final int api) { super(api); @@ -291,7 +291,7 @@ public class MethodNode extends MethodVisitor { */ public MethodNode(final int access, final String name, final String desc, final String signature, final String[] exceptions) { - this(Opcodes.ASM5, access, name, desc, signature, exceptions); + this(Opcodes.ASM6, access, name, desc, signature, exceptions); if (getClass() != MethodNode.class) { throw new IllegalStateException(); } @@ -302,7 +302,7 @@ public class MethodNode extends MethodVisitor { * * @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 * the method's access flags (see {@link Opcodes}). This * parameter also indicates if the method is synthetic and/or @@ -688,8 +688,8 @@ public class MethodNode extends MethodVisitor { * versions of the ASM API than the given version. * * @param api - * an ASM API version. Must be one of {@link Opcodes#ASM4} or - * {@link Opcodes#ASM5}. + * an ASM API version. Must be one of {@link Opcodes#ASM4}, + * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ public void check(final int api) { if (api == Opcodes.ASM4) { diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleExportNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleExportNode.java new file mode 100644 index 0000000000000000000000000000000000000000..35871dca4dd3b8dcd0ae4950e0b00d640fd8b335 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleExportNode.java @@ -0,0 +1,111 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package jdk.internal.org.objectweb.asm.tree; + +import java.util.List; + +import jdk.internal.org.objectweb.asm.ModuleVisitor; + +/** + * A node that represents an exported package with its name and the module that can access to it. + * + * @author Remi Forax + */ +public class ModuleExportNode { + /** + * The package name. + */ + public String packaze; + + /** + * The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). + * Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}. + */ + public int access; + + /** + * A list of modules that can access to this exported package. + * May be null. + */ + public List modules; + + /** + * Constructs a new {@link ModuleExportNode}. + * + * @param packaze + * the parameter's name. + * @param modules + * a list of modules that can access to this exported package. + */ + public ModuleExportNode(final String packaze, final int access, final List modules) { + this.packaze = packaze; + this.access = access; + this.modules = modules; + } + + /** + * Makes the given module visitor visit this export declaration. + * + * @param mv + * a module visitor. + */ + public void accept(final ModuleVisitor mv) { + mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0])); + } +} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleNode.java new file mode 100644 index 0000000000000000000000000000000000000000..3f5747db1d72260e5848ee4f03f65d0496628937 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleNode.java @@ -0,0 +1,280 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package jdk.internal.org.objectweb.asm.tree; + +import java.util.ArrayList; +import java.util.List; + +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.ModuleVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +/** + * A node that represents a module declaration. + * + * @author Remi Forax + */ +public class ModuleNode extends ModuleVisitor { + /** + * Module name + */ + public String name; + + /** + * Module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} + * and {@code ACC_MANDATED}. + */ + public int access; + + /** + * Version of the module. + * May be null. + */ + public String version; + + /** + * Name of the main class in internal form + * May be null. + */ + public String mainClass; + + /** + * A list of packages that are declared by the current module. + * May be null. + */ + public List packages; + + /** + * A list of modules can are required by the current module. + * May be null. + */ + public List requires; + + /** + * A list of packages that are exported by the current module. + * May be null. + */ + public List exports; + + /** + * A list of packages that are opened by the current module. + * May be null. + */ + public List opens; + + /** + * A list of classes in their internal forms that are used + * as a service by the current module. May be null. + */ + public List uses; + + /** + * A list of services along with their implementations provided + * by the current module. May be null. + */ + public List provides; + + public ModuleNode(final String name, final int access, + final String version) { + super(Opcodes.ASM6); + this.name = name; + this.access = access; + this.version = version; + } + + public ModuleNode(final int api, + final String name, + final int access, + final String version, + final List requires, + final List exports, + final List opens, + final List uses, + final List provides) { + super(api); + this.name = name; + this.access = access; + this.version = version; + this.requires = requires; + this.exports = exports; + this.opens = opens; + this.uses = uses; + this.provides = provides; + if (getClass() != ModuleNode.class) { + throw new IllegalStateException(); + } + } + + @Override + public void visitMainClass(String mainClass) { + this.mainClass = mainClass; + } + + @Override + public void visitPackage(String packaze) { + if (packages == null) { + packages = new ArrayList(5); + } + packages.add(packaze); + } + + @Override + public void visitRequire(String module, int access, String version) { + if (requires == null) { + requires = new ArrayList(5); + } + requires.add(new ModuleRequireNode(module, access, version)); + } + + @Override + public void visitExport(String packaze, int access, String... modules) { + if (exports == null) { + exports = new ArrayList(5); + } + List moduleList = null; + if (modules != null) { + moduleList = new ArrayList(modules.length); + for (int i = 0; i < modules.length; i++) { + moduleList.add(modules[i]); + } + } + exports.add(new ModuleExportNode(packaze, access, moduleList)); + } + + @Override + public void visitOpen(String packaze, int access, String... modules) { + if (opens == null) { + opens = new ArrayList(5); + } + List moduleList = null; + if (modules != null) { + moduleList = new ArrayList(modules.length); + for (int i = 0; i < modules.length; i++) { + moduleList.add(modules[i]); + } + } + opens.add(new ModuleOpenNode(packaze, access, moduleList)); + } + + @Override + public void visitUse(String service) { + if (uses == null) { + uses = new ArrayList(5); + } + uses.add(service); + } + + @Override + public void visitProvide(String service, String... providers) { + if (provides == null) { + provides = new ArrayList(5); + } + ArrayList providerList = + new ArrayList(providers.length); + for (int i = 0; i < providers.length; i++) { + providerList.add(providers[i]); + } + provides.add(new ModuleProvideNode(service, providerList)); + } + + @Override + public void visitEnd() { + } + + public void accept(final ClassVisitor cv) { + ModuleVisitor mv = cv.visitModule(name, access, version); + if (mv == null) { + return; + } + if (mainClass != null) { + mv.visitMainClass(mainClass); + } + if (packages != null) { + for (int i = 0; i < packages.size(); i++) { + mv.visitPackage(packages.get(i)); + } + } + + if (requires != null) { + for (int i = 0; i < requires.size(); i++) { + requires.get(i).accept(mv); + } + } + if (exports != null) { + for (int i = 0; i < exports.size(); i++) { + exports.get(i).accept(mv); + } + } + if (opens != null) { + for (int i = 0; i < opens.size(); i++) { + opens.get(i).accept(mv); + } + } + if (uses != null) { + for (int i = 0; i < uses.size(); i++) { + mv.visitUse(uses.get(i)); + } + } + if (provides != null) { + for (int i = 0; i < provides.size(); i++) { + provides.get(i).accept(mv); + } + } + } +} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleOpenNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleOpenNode.java new file mode 100644 index 0000000000000000000000000000000000000000..2c6ed05a9bcf31545f5f919a17713faccb454608 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleOpenNode.java @@ -0,0 +1,111 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package jdk.internal.org.objectweb.asm.tree; + +import java.util.List; + +import jdk.internal.org.objectweb.asm.ModuleVisitor; + +/** + * A node that represents an opened package with its name and the module that can access to it. + * + * @author Remi Forax + */ +public class ModuleOpenNode { + /** + * The package name. + */ + public String packaze; + + /** + * The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). + * Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}. + */ + public int access; + + /** + * A list of modules that can access to this exported package. + * May be null. + */ + public List modules; + + /** + * Constructs a new {@link ModuleOpenNode}. + * + * @param packaze + * the parameter's name. + * @param modules + * a list of modules that can access to this open package. + */ + public ModuleOpenNode(final String packaze, final int access, final List modules) { + this.packaze = packaze; + this.access = access; + this.modules = modules; + } + + /** + * Makes the given module visitor visit this open declaration. + * + * @param mv + * a module visitor. + */ + public void accept(final ModuleVisitor mv) { + mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0])); + } +} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleProvideNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleProvideNode.java new file mode 100644 index 0000000000000000000000000000000000000000..ed1a28b0df1166dbddde9ef37b6a4aa1b5a8c26b --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleProvideNode.java @@ -0,0 +1,103 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package jdk.internal.org.objectweb.asm.tree; + +import java.util.List; + +import jdk.internal.org.objectweb.asm.ModuleVisitor; + +/** + * A node that represents a service and its implementation provided by the current module. + * + * @author Remi Forax + */ +public class ModuleProvideNode { + /** + * The service name (in its internal form). + */ + public String service; + + /** + * The service provider names (in their internal form). + */ + public List providers; + + /** + * Constructs a new {@link ModuleProvideNode}. + * + * @param service + * the service name (in its internal form). + * @param providers + * the service provider names (in their internal form). + */ + public ModuleProvideNode(final String service, final List providers) { + this.service = service; + this.providers = providers; + } + + /** + * Makes the given module visitor visit this require declaration. + * + * @param mv + * a module visitor. + */ + public void accept(final ModuleVisitor mv) { + mv.visitProvide(service, providers.toArray(new String[0])); + } +} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleRequireNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleRequireNode.java new file mode 100644 index 0000000000000000000000000000000000000000..3a5379b391224b7934a0eb2ecd74c74941f52d94 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleRequireNode.java @@ -0,0 +1,116 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package jdk.internal.org.objectweb.asm.tree; + +import jdk.internal.org.objectweb.asm.ModuleVisitor; + +/** + * A node that represents a required module with its name and access of a module descriptor. + * + * @author Remi Forax + */ +public class ModuleRequireNode { + /** + * The name of the required module. + */ + public String module; + + /** + * The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). + * Valid values are ACC_TRANSITIVE, ACC_STATIC_PHASE, + * ACC_SYNTHETIC and ACC_MANDATED. + */ + public int access; + + /** + * Version at compile time of the required module or null. + */ + public String version; + + /** + * Constructs a new {@link ModuleRequireNode}. + * + * @param module + * the name of the required module. + * @param access + * The access flags. Valid values are + * ACC_TRANSITIVE, ACC_STATIC_PHASE, + * ACC_SYNTHETIC and ACC_MANDATED + * (see {@link jdk.internal.org.objectweb.asm.Opcodes}). + * @param version + * Version of the required module at compile time, + * null if not defined. + */ + public ModuleRequireNode(final String module, final int access, + final String version) { + this.module = module; + this.access = access; + this.version = version; + } + + /** + * Makes the given module visitor visit this require directive. + * + * @param mv + * a module visitor. + */ + public void accept(final ModuleVisitor mv) { + mv.visitRequire(module, access, version); + } +} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java index 641dca1c17d8be2377f336de70b48047a5c2ddbf..d61320183390ae30f84f2fa73cb912d3d1d5adc0 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java @@ -99,7 +99,7 @@ public class TypeAnnotationNode extends AnnotationNode { */ public TypeAnnotationNode(final int typeRef, final TypePath typePath, final String desc) { - this(Opcodes.ASM5, typeRef, typePath, desc); + this(Opcodes.ASM6, typeRef, typePath, desc); if (getClass() != TypeAnnotationNode.class) { throw new IllegalStateException(); } @@ -110,7 +110,7 @@ public class TypeAnnotationNode extends AnnotationNode { * * @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 typeRef * a reference to the annotated type. See {@link TypeReference}. * @param typePath diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java index e450166ba6592824b77e39422cbde72cef4ebdcb..e42f529e97a5f84f44f87933cb946e994992e339 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java @@ -82,7 +82,7 @@ public class BasicInterpreter extends Interpreter implements Opcodes { public BasicInterpreter() { - super(ASM5); + super(ASM6); } protected BasicInterpreter(final int api) { diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java index 2ccf67d4cb474eb502f053c7569eb14e4e63030a..9aae77d5f801ae37dcf7f52b3b0c006054964c0e 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java @@ -76,7 +76,7 @@ import jdk.internal.org.objectweb.asm.tree.MethodInsnNode; public class BasicVerifier extends BasicInterpreter { public BasicVerifier() { - super(ASM5); + super(ASM6); } protected BasicVerifier(final int api) { diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java index a93c5f2a1215db6ed504a2b4e3ae22815cc84718..e0fba8f98cff955e61d5397cc979fe9fd68823ea 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java @@ -136,7 +136,7 @@ public class SimpleVerifier extends BasicVerifier { public SimpleVerifier(final Type currentClass, final Type currentSuperClass, final List currentClassInterfaces, final boolean isInterface) { - this(ASM5, currentClass, currentSuperClass, currentClassInterfaces, + this(ASM6, currentClass, currentSuperClass, currentClassInterfaces, isInterface); } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java index e37cecc9ec6e5d3cda49283e642ee50f2565d422..ba69f35e22da6556b88a5c4f42cf0fee3983fdf7 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java @@ -79,7 +79,7 @@ public class SourceInterpreter extends Interpreter implements Opcodes { public SourceInterpreter() { - super(ASM5); + super(ASM6); } protected SourceInterpreter(final int api) { diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java index d7c1becfe461184f5798fe650f0ce3351c276729..d6af294de5c13a0d51bff61a3ddb971f584f5a4c 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java @@ -109,6 +109,11 @@ public class ASMifier extends Printer { */ private static final int ACCESS_INNER = 1048576; + /** + * Pseudo access flag used to distinguish module requires/exports flags. + */ + private static final int ACCESS_MODULE = 2097152; + /** * Constructs a new {@link ASMifier}. Subclasses must not use this * constructor. Instead, they must use the @@ -118,7 +123,7 @@ public class ASMifier extends Printer { * If a subclass calls this constructor. */ public ASMifier() { - this(Opcodes.ASM5, "cw", 0); + this(Opcodes.ASM6, "cw", 0); if (getClass() != ASMifier.class) { throw new IllegalStateException(); } @@ -129,7 +134,7 @@ public class ASMifier extends Printer { * * @param api * the ASM API version implemented by this class. Must be one of - * {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * @param name * the name of the visitor variable in the produced code. * @param id @@ -196,13 +201,17 @@ public class ASMifier extends Printer { final String signature, final String superName, final String[] interfaces) { String simpleName; - int n = name.lastIndexOf('/'); - if (n == -1) { - simpleName = name; + if (name == null) { + simpleName = "module-info"; } else { - text.add("package asm." + name.substring(0, n).replace('/', '.') - + ";\n"); - simpleName = name.substring(n + 1); + int n = name.lastIndexOf('/'); + if (n == -1) { + simpleName = name; + } else { + text.add("package asm." + name.substring(0, n).replace('/', '.') + + ";\n"); + simpleName = name.substring(n + 1).replace('-', '_'); + } } text.add("import java.util.*;\n"); text.add("import jdk.internal.org.objectweb.asm.*;\n"); @@ -237,6 +246,12 @@ public class ASMifier extends Printer { case Opcodes.V1_7: buf.append("V1_7"); break; + case Opcodes.V1_8: + buf.append("V1_8"); + break; + case Opcodes.V9: + buf.append("V9"); + break; default: buf.append(version); break; @@ -275,6 +290,24 @@ public class ASMifier extends Printer { text.add(buf.toString()); } + @Override + public Printer visitModule(final String name, final int flags, + final String version) { + buf.setLength(0); + buf.append("ModuleVisitor mdv = cw.visitModule("); + appendConstant(name); + buf.append(", "); + appendAccess(flags | ACCESS_MODULE); + buf.append(", "); + appendConstant(version); + buf.append(");\n\n"); + text.add(buf.toString()); + ASMifier a = createASMifier("mdv", 0); + text.add(a.getText()); + text.add("}\n"); + return a; + } + @Override public void visitOuterClass(final String owner, final String name, final String desc) { @@ -385,6 +418,108 @@ public class ASMifier extends Printer { text.add("}\n"); } + // ------------------------------------------------------------------------ + // Module + // ------------------------------------------------------------------------ + + @Override + public void visitMainClass(String mainClass) { + buf.setLength(0); + buf.append("mdv.visitMainClass("); + appendConstant(buf, mainClass); + buf.append(");\n"); + text.add(buf.toString()); + } + + @Override + public void visitPackage(String packaze) { + buf.setLength(0); + buf.append("mdv.visitPackage("); + appendConstant(buf, packaze); + buf.append(");\n"); + text.add(buf.toString()); + } + + @Override + public void visitRequire(String module, int access, String version) { + buf.setLength(0); + buf.append("mdv.visitRequire("); + appendConstant(buf, module); + buf.append(", "); + appendAccess(access | ACCESS_MODULE); + buf.append(", "); + appendConstant(buf, version); + buf.append(");\n"); + text.add(buf.toString()); + } + + @Override + public void visitExport(String packaze, int access, String... modules) { + buf.setLength(0); + buf.append("mdv.visitExport("); + appendConstant(buf, packaze); + buf.append(", "); + appendAccess(access | ACCESS_MODULE); + if (modules != null && modules.length > 0) { + buf.append(", new String[] {"); + for (int i = 0; i < modules.length; ++i) { + buf.append(i == 0 ? " " : ", "); + appendConstant(modules[i]); + } + buf.append(" }"); + } + buf.append(");\n"); + text.add(buf.toString()); + } + + @Override + public void visitOpen(String packaze, int access, String... modules) { + buf.setLength(0); + buf.append("mdv.visitOpen("); + appendConstant(buf, packaze); + buf.append(", "); + appendAccess(access | ACCESS_MODULE); + if (modules != null && modules.length > 0) { + buf.append(", new String[] {"); + for (int i = 0; i < modules.length; ++i) { + buf.append(i == 0 ? " " : ", "); + appendConstant(modules[i]); + } + buf.append(" }"); + } + buf.append(");\n"); + text.add(buf.toString()); + } + + @Override + public void visitUse(String service) { + buf.setLength(0); + buf.append("mdv.visitUse("); + appendConstant(buf, service); + buf.append(");\n"); + text.add(buf.toString()); + } + + @Override + public void visitProvide(String service, String... providers) { + buf.setLength(0); + buf.append("mdv.visitProvide("); + appendConstant(buf, service); + buf.append(", new String[] {"); + for (int i = 0; i < providers.length; ++i) { + buf.append(i == 0 ? " " : ", "); + appendConstant(providers[i]); + } + buf.append(" });\n"); + text.add(buf.toString()); + } + + @Override + public void visitModuleEnd() { + text.add("mdv.visitEnd();\n"); + } + + // ------------------------------------------------------------------------ // Annotations // ------------------------------------------------------------------------ @@ -972,7 +1107,7 @@ public class ASMifier extends Printer { // ------------------------------------------------------------------------ protected ASMifier createASMifier(final String name, final int id) { - return new ASMifier(Opcodes.ASM5, name, id); + return new ASMifier(Opcodes.ASM6, name, id); } /** @@ -1000,7 +1135,11 @@ public class ASMifier extends Printer { if (!first) { buf.append(" + "); } - buf.append("ACC_FINAL"); + if ((access & ACCESS_MODULE) == 0) { + buf.append("ACC_FINAL"); + } else { + buf.append("ACC_TRANSITIVE"); + } first = false; } if ((access & Opcodes.ACC_STATIC) != 0) { @@ -1010,31 +1149,35 @@ public class ASMifier extends Printer { buf.append("ACC_STATIC"); first = false; } - if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { + if ((access & (Opcodes.ACC_SYNCHRONIZED | Opcodes.ACC_SUPER | Opcodes.ACC_TRANSITIVE)) != 0) { if (!first) { buf.append(" + "); } if ((access & ACCESS_CLASS) == 0) { - buf.append("ACC_SYNCHRONIZED"); + if ((access & ACCESS_MODULE) == 0) { + buf.append("ACC_SYNCHRONIZED"); + } else { + buf.append("ACC_TRANSITIVE"); + } } else { buf.append("ACC_SUPER"); } first = false; } - if ((access & Opcodes.ACC_VOLATILE) != 0 - && (access & ACCESS_FIELD) != 0) { + if ((access & (Opcodes.ACC_VOLATILE | Opcodes.ACC_BRIDGE | Opcodes.ACC_STATIC_PHASE)) != 0) { if (!first) { buf.append(" + "); } - buf.append("ACC_VOLATILE"); - first = false; - } - if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0 - && (access & ACCESS_FIELD) == 0) { - if (!first) { - buf.append(" + "); + if ((access & ACCESS_FIELD) == 0) { + if ((access & ACCESS_MODULE) == 0) { + buf.append("ACC_BRIDGE"); + } else { + buf.append("ACC_STATIC_PHASE"); + } + } else { + buf.append("ACC_VOLATILE"); } - buf.append("ACC_BRIDGE"); + first = false; } if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0 @@ -1113,11 +1256,15 @@ public class ASMifier extends Printer { buf.append("ACC_DEPRECATED"); first = false; } - if ((access & Opcodes.ACC_MANDATED) != 0) { + if ((access & (Opcodes.ACC_MANDATED | Opcodes.ACC_MODULE)) != 0) { if (!first) { buf.append(" + "); } - buf.append("ACC_MANDATED"); + if ((access & ACCESS_CLASS) == 0) { + buf.append("ACC_MANDATED"); + } else { + buf.append("ACC_MODULE"); + } first = false; } if (first) { @@ -1163,7 +1310,8 @@ public class ASMifier extends Printer { .append(", \""); buf.append(h.getOwner()).append("\", \""); buf.append(h.getName()).append("\", \""); - buf.append(h.getDesc()).append("\")"); + buf.append(h.getDesc()).append("\", "); + buf.append(h.isInterface()).append(")"); } else if (cst instanceof Byte) { buf.append("new Byte((byte)").append(cst).append(')'); } else if (cst instanceof Boolean) { diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java index 4b68882676448a6e36dc31aff515eca5fab0bb0f..afa969b9f8fd768991a365c0e6ddcce8e65acb03 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java @@ -78,7 +78,7 @@ public class CheckAnnotationAdapter extends AnnotationVisitor { } CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) { - super(Opcodes.ASM5, av); + super(Opcodes.ASM6, av); this.named = named; } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java index 22dddf2d5e1e359da35705ef371f0b7688f9483d..6e695cc46aa3429819b5e74fafad5fc21948a455 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java @@ -73,6 +73,7 @@ import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.Label; 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.Type; import jdk.internal.org.objectweb.asm.TypePath; @@ -180,6 +181,11 @@ public class CheckClassAdapter extends ClassVisitor { */ private boolean end; + /** + * true if the visitModule method has been called. + */ + private boolean module; + /** * The already visited labels. This map associate Integer values to Label * keys. @@ -363,7 +369,7 @@ public class CheckClassAdapter extends ClassVisitor { * If a subclass calls this constructor. */ public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) { - this(Opcodes.ASM5, cv, checkDataFlow); + this(Opcodes.ASM6, cv, checkDataFlow); if (getClass() != CheckClassAdapter.class) { throw new IllegalStateException(); } @@ -374,7 +380,7 @@ public class CheckClassAdapter extends ClassVisitor { * * @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 adapter must delegate calls. * @param checkDataFlow @@ -407,8 +413,12 @@ public class CheckClassAdapter extends ClassVisitor { + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM - + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - if (name == null || !name.endsWith("package-info")) { + + Opcodes.ACC_DEPRECATED + Opcodes.ACC_MODULE + + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + if (name == null) { + throw new IllegalArgumentException("Illegal class name (null)"); + } + if (!name.endsWith("package-info")) { CheckMethodAdapter.checkInternalName(name, "class name"); } if ("java/lang/Object".equals(name)) { @@ -449,6 +459,22 @@ public class CheckClassAdapter extends ClassVisitor { super.visitSource(file, debug); } + @Override + public ModuleVisitor visitModule(String name, int access, String version) { + checkState(); + if (module) { + throw new IllegalStateException( + "visitModule can be called only once."); + } + module = true; + if (name == null) { + throw new IllegalArgumentException("Illegal module name (null)"); + } + checkAccess(access, Opcodes.ACC_OPEN | Opcodes.ACC_SYNTHETIC); + return new CheckModuleAdapter(super.visitModule(name, access, version), + (access & Opcodes.ACC_OPEN) != 0); + } + @Override public void visitOuterClass(final String owner, final String name, final String desc) { diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java index e0857bf06b3f6160ccd4b16d947ceb48de95c56f..dd7c7d5ce9af55a9c98a1e5445fbd3461c180815 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java @@ -83,7 +83,7 @@ public class CheckFieldAdapter extends FieldVisitor { * If a subclass calls this constructor. */ public CheckFieldAdapter(final FieldVisitor fv) { - this(Opcodes.ASM5, fv); + this(Opcodes.ASM6, fv); if (getClass() != CheckFieldAdapter.class) { throw new IllegalStateException(); } @@ -94,7 +94,7 @@ public class CheckFieldAdapter extends FieldVisitor { * * @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 adapter must delegate calls. */ diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java index a0afdc650a82657f39b55584f3882698a29811b7..d4e50a51f6a4564a213a3972ff70d1dd610eff34 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java @@ -426,7 +426,7 @@ public class CheckMethodAdapter extends MethodVisitor { */ public CheckMethodAdapter(final MethodVisitor mv, final Map labels) { - this(Opcodes.ASM5, mv, labels); + this(Opcodes.ASM6, mv, labels); if (getClass() != CheckMethodAdapter.class) { throw new IllegalStateException(); } @@ -439,7 +439,8 @@ public class CheckMethodAdapter extends MethodVisitor { * * @param api * the ASM API version implemented by this CheckMethodAdapter. - * 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}. * @param mv * the method visitor to which this adapter must delegate calls. * @param labels @@ -756,6 +757,12 @@ public class CheckMethodAdapter extends MethodVisitor { throw new IllegalArgumentException( "INVOKEINTERFACE can't be used with classes"); } + if (opcode == Opcodes.INVOKESPECIAL && itf + && (version & 0xFFFF) < Opcodes.V1_8) { + throw new IllegalArgumentException( + "INVOKESPECIAL can't be used with interfaces prior to Java 8"); + } + // Calling super.visitMethodInsn requires to call the correct version // depending on this.api (otherwise infinite loops can occur). To // simplify and to make it easier to automatically remove the backward diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckModuleAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckModuleAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..9a355360bdd485f50acc851686d738413f2c74c2 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckModuleAdapter.java @@ -0,0 +1,180 @@ +/* + * 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.util; + +import java.util.HashSet; + +import jdk.internal.org.objectweb.asm.ModuleVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +/** + * @author Remi Forax + */ +public final class CheckModuleAdapter extends ModuleVisitor { + private boolean end; + private final boolean isOpen; + + private final HashSet requireNames = new HashSet(); + private final HashSet exportNames = new HashSet(); + private final HashSet openNames = new HashSet(); + private final HashSet useNames = new HashSet(); + private final HashSet provideNames = new HashSet(); + + public CheckModuleAdapter(final ModuleVisitor mv, final boolean isOpen) { + super(Opcodes.ASM6, mv); + this.isOpen = isOpen; + } + + @Override + public void visitRequire(String module, int access, String version) { + checkEnd(); + if (module == null) { + throw new IllegalArgumentException("require cannot be null"); + } + checkDeclared("requires", requireNames, module); + CheckClassAdapter.checkAccess(access, Opcodes.ACC_STATIC_PHASE + + Opcodes.ACC_TRANSITIVE + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_MANDATED); + super.visitRequire(module, access, version); + } + + @Override + public void visitExport(String packaze, int access, String... modules) { + checkEnd(); + if (packaze == null) { + throw new IllegalArgumentException("packaze cannot be null"); + } + CheckMethodAdapter.checkInternalName(packaze, "package name"); + checkDeclared("exports", exportNames, packaze); + CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC + + Opcodes.ACC_MANDATED); + if (modules != null) { + for (int i = 0; i < modules.length; i++) { + if (modules[i] == null) { + throw new IllegalArgumentException("module at index " + i + " cannot be null"); + } + } + } + super.visitExport(packaze, access, modules); + } + + @Override + public void visitOpen(String packaze, int access, String... modules) { + checkEnd(); + if (isOpen) { + throw new IllegalArgumentException("an open module can not use open directive"); + } + if (packaze == null) { + throw new IllegalArgumentException("packaze cannot be null"); + } + CheckMethodAdapter.checkInternalName(packaze, "package name"); + checkDeclared("opens", openNames, packaze); + CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC + + Opcodes.ACC_MANDATED); + if (modules != null) { + for (int i = 0; i < modules.length; i++) { + if (modules[i] == null) { + throw new IllegalArgumentException("module at index " + i + " cannot be null"); + } + } + } + super.visitOpen(packaze, access, modules); + } + + @Override + public void visitUse(String service) { + checkEnd(); + CheckMethodAdapter.checkInternalName(service, "service"); + checkDeclared("uses", useNames, service); + super.visitUse(service); + } + + @Override + public void visitProvide(String service, String... providers) { + checkEnd(); + CheckMethodAdapter.checkInternalName(service, "service"); + checkDeclared("provides", provideNames, service); + if (providers == null || providers.length == 0) { + throw new IllegalArgumentException("providers cannot be null or empty"); + } + for (int i = 0; i < providers.length; i++) { + CheckMethodAdapter.checkInternalName(providers[i], "provider"); + } + super.visitProvide(service, providers); + } + + @Override + public void visitEnd() { + checkEnd(); + end = true; + super.visitEnd(); + } + + private void checkEnd() { + if (end) { + throw new IllegalStateException( + "Cannot call a visit method after visitEnd has been called"); + } + } + + private static void checkDeclared(String directive, HashSet names, String name) { + if (!names.add(name)) { + throw new IllegalArgumentException(directive + " " + name + " already declared"); + } + } +} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java index ad3bca8fb563755272b1bd3c26a621e60ed5569b..cdfcc68a9c880b862de2e853108e5f9a2a630c02 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java @@ -142,7 +142,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { * null. */ public CheckSignatureAdapter(final int type, final SignatureVisitor sv) { - this(Opcodes.ASM5, type, sv); + this(Opcodes.ASM6, type, sv); } /** @@ -150,7 +150,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { * * @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 type * the type of signature to be checked. See * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and @@ -175,7 +175,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { || (state != EMPTY && state != FORMAL && state != BOUND)) { throw new IllegalStateException(); } - CheckMethodAdapter.checkIdentifier(name, "formal type parameter"); + checkIdentifier(name, "formal type parameter"); state = FORMAL; if (sv != null) { sv.visitFormalTypeParameter(name); @@ -284,7 +284,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { if (type != TYPE_SIGNATURE || state != EMPTY) { throw new IllegalStateException(); } - CheckMethodAdapter.checkIdentifier(name, "type variable"); + checkIdentifier(name, "type variable"); state = SIMPLE_TYPE; if (sv != null) { sv.visitTypeVariable(name); @@ -306,7 +306,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { if (type != TYPE_SIGNATURE || state != EMPTY) { throw new IllegalStateException(); } - CheckMethodAdapter.checkInternalName(name, "class name"); + checkClassName(name, "class name"); state = CLASS_TYPE; if (sv != null) { sv.visitClassType(name); @@ -318,7 +318,7 @@ public class CheckSignatureAdapter extends SignatureVisitor { if (state != CLASS_TYPE) { throw new IllegalStateException(); } - CheckMethodAdapter.checkIdentifier(name, "inner class name"); + checkIdentifier(name, "inner class name"); if (sv != null) { sv.visitInnerClassType(name); } @@ -356,4 +356,30 @@ public class CheckSignatureAdapter extends SignatureVisitor { sv.visitEnd(); } } + + private void checkClassName(final String name, final String msg) { + if (name == null || name.length() == 0) { + throw new IllegalArgumentException("Invalid " + msg + + " (must not be null or empty)"); + } + for (int i = 0; i < name.length(); ++i) { + if (".;[<>:".indexOf(name.charAt(i)) != -1) { + throw new IllegalArgumentException("Invalid " + msg + + " (must not contain . ; [ < > or :): " + name); + } + } + } + + private void checkIdentifier(final String name, final String msg) { + if (name == null || name.length() == 0) { + throw new IllegalArgumentException("Invalid " + msg + + " (must not be null or empty)"); + } + for (int i = 0; i < name.length(); ++i) { + if (".;[/<>:".indexOf(name.charAt(i)) != -1) { + throw new IllegalArgumentException("Invalid " + msg + + " (must not contain . ; [ / < > or :): " + name); + } + } + } } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java index 650e1f0b87850b20786bdad8319920da3c192a72..91640e8259e897025c289bec2e961df157157ab7 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java @@ -146,7 +146,7 @@ public abstract class Printer { /** * The ASM API version implemented by this class. 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; @@ -174,7 +174,7 @@ public abstract class Printer { * * @param api * the ASM API version implemented by this printer. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ protected Printer(final int api) { this.api = api; @@ -226,6 +226,24 @@ public abstract class Printer { */ public abstract void visitSource(final String source, final String debug); + + /** + * Module. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitModule(String, int)}. + * + * @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 + */ + public Printer visitModule(String name, int access, String version) { + throw new RuntimeException("Must be overriden"); + } + /** * Class outer class. * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitOuterClass}. @@ -375,6 +393,45 @@ public abstract class Printer { */ public abstract void visitClassEnd(); + // ------------------------------------------------------------------------ + // Module + // ------------------------------------------------------------------------ + + public void visitMainClass(String mainClass) { + throw new RuntimeException("Must be overriden"); + } + + public void visitPackage(String packaze) { + throw new RuntimeException("Must be overriden"); + } + + public void visitRequire(String module, int access, String version) { + throw new RuntimeException("Must be overriden"); + } + + public void visitExport(String packaze, int access, String... modules) { + throw new RuntimeException("Must be overriden"); + } + + public void visitOpen(String packaze, int access, String... modules) { + throw new RuntimeException("Must be overriden"); + } + + public void visitUse(String service) { + throw new RuntimeException("Must be overriden"); + } + + public void visitProvide(String service, String... providers) { + throw new RuntimeException("Must be overriden"); + } + + /** + * Module end. See {@link jdk.internal.org.objectweb.asm.ModuleVisitor#visitEnd}. + */ + public void visitModuleEnd() { + throw new RuntimeException("Must be overriden"); + } + // ------------------------------------------------------------------------ // Annotations // ------------------------------------------------------------------------ diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java index b8e1cd1f12ff8634b85cf76ba0238d907335f6eb..17b38bd952e2181222504339b2c72e8c2503dcc4 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java @@ -182,7 +182,7 @@ public class Textifier extends Printer { * If a subclass calls this constructor. */ public Textifier() { - this(Opcodes.ASM5); + this(Opcodes.ASM6); if (getClass() != Textifier.class) { throw new IllegalStateException(); } @@ -193,7 +193,7 @@ public class Textifier extends Printer { * * @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}. */ protected Textifier(final int api) { super(api); @@ -250,6 +250,10 @@ public class Textifier extends Printer { public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { + if ((access & Opcodes.ACC_MODULE) != 0) { + // visitModule will print the module + return; + } this.access = access; int major = version & 0xFFFF; int minor = version >>> 16; @@ -271,7 +275,7 @@ public class Textifier extends Printer { .append(sv.getDeclaration()).append('\n'); } - appendAccess(access & ~Opcodes.ACC_SUPER); + appendAccess(access & ~(Opcodes.ACC_SUPER | Opcodes.ACC_MODULE)); if ((access & Opcodes.ACC_ANNOTATION) != 0) { buf.append("@interface "); } else if ((access & Opcodes.ACC_INTERFACE) != 0) { @@ -314,6 +318,24 @@ public class Textifier extends Printer { } } + @Override + public Printer visitModule(final String name, final int access, + final String version) { + buf.setLength(0); + if ((access & Opcodes.ACC_OPEN) != 0) { + buf.append("open "); + } + buf.append("module ") + .append(name) + .append(" { ") + .append(version == null ? "" : "// " + version) + .append("\n\n"); + text.add(buf.toString()); + Textifier t = createTextifier(); + text.add(t.getText()); + return t; + } + @Override public void visitOuterClass(final String owner, final String name, final String desc) { @@ -443,7 +465,7 @@ public class Textifier extends Printer { } buf.append(tab); - appendAccess(access & ~Opcodes.ACC_VOLATILE); + appendAccess(access & ~(Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT)); if ((access & Opcodes.ACC_NATIVE) != 0) { buf.append("native "); } @@ -482,6 +504,118 @@ public class Textifier extends Printer { text.add("}\n"); } + // ------------------------------------------------------------------------ + // Module + // ------------------------------------------------------------------------ + + @Override + public void visitMainClass(String mainClass) { + buf.setLength(0); + buf.append(" // main class ").append(mainClass).append('\n'); + text.add(buf.toString()); + } + + @Override + public void visitPackage(String packaze) { + buf.setLength(0); + buf.append(" // package ").append(packaze).append('\n'); + text.add(buf.toString()); + } + + @Override + public void visitRequire(String require, int access, String version) { + buf.setLength(0); + buf.append(tab).append("requires "); + if ((access & Opcodes.ACC_TRANSITIVE) != 0) { + buf.append("transitive "); + } + if ((access & Opcodes.ACC_STATIC_PHASE) != 0) { + buf.append("static "); + } + buf.append(require) + .append("; // access flags 0x") + .append(Integer.toHexString(access).toUpperCase()) + .append('\n'); + if (version != null) { + buf.append(" // version ") + .append(version) + .append('\n'); + } + text.add(buf.toString()); + } + + @Override + public void visitExport(String export, int access, String... modules) { + buf.setLength(0); + buf.append(tab).append("exports "); + buf.append(export); + if (modules != null && modules.length > 0) { + buf.append(" to"); + } else { + buf.append(';'); + } + buf.append(" // access flags 0x") + .append(Integer.toHexString(access).toUpperCase()) + .append('\n'); + if (modules != null && modules.length > 0) { + for (int i = 0; i < modules.length; ++i) { + buf.append(tab2).append(modules[i]); + buf.append(i != modules.length - 1 ? ",\n": ";\n"); + } + } + text.add(buf.toString()); + } + + @Override + public void visitOpen(String export, int access, String... modules) { + buf.setLength(0); + buf.append(tab).append("opens "); + buf.append(export); + if (modules != null && modules.length > 0) { + buf.append(" to"); + } else { + buf.append(';'); + } + buf.append(" // access flags 0x") + .append(Integer.toHexString(access).toUpperCase()) + .append('\n'); + if (modules != null && modules.length > 0) { + for (int i = 0; i < modules.length; ++i) { + buf.append(tab2).append(modules[i]); + buf.append(i != modules.length - 1 ? ",\n": ";\n"); + } + } + text.add(buf.toString()); + } + + @Override + public void visitUse(String use) { + buf.setLength(0); + buf.append(tab).append("uses "); + appendDescriptor(INTERNAL_NAME, use); + buf.append(";\n"); + text.add(buf.toString()); + } + + @Override + public void visitProvide(String provide, String... providers) { + buf.setLength(0); + buf.append(tab).append("provides "); + appendDescriptor(INTERNAL_NAME, provide); + buf.append(" with\n"); + for (int i = 0; i < providers.length; ++i) { + buf.append(tab2); + appendDescriptor(INTERNAL_NAME, providers[i]); + buf.append(i != providers.length - 1 ? ",\n": ";\n"); + } + text.add(buf.toString()); + } + + @Override + public void visitModuleEnd() { + // empty + } + // ------------------------------------------------------------------------ // Annotations // ------------------------------------------------------------------------ @@ -1296,13 +1430,16 @@ public class Textifier extends Printer { appendDescriptor(INTERNAL_NAME, h.getOwner()); buf.append('.'); buf.append(h.getName()); - if(!isMethodHandle){ + if (!isMethodHandle) { buf.append('('); } appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc()); - if(!isMethodHandle){ + if (!isMethodHandle) { buf.append(')'); } + if (h.isInterface()) { + buf.append(" itf"); + } } /** diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java index d521c2cf484ed3b4b53c01aca7c00df6d1958eaf..f7491b20380fe3c081afcd2d6cc0f28550815e6e 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java @@ -76,7 +76,7 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor { } public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) { - super(Opcodes.ASM5, av); + super(Opcodes.ASM6, av); this.p = p; } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java index e927bff9ea5c202825c7e3bcc2c5fdf3f762c7f5..8e30fa605c465a45c248fe84260e9497f242748b 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java @@ -65,6 +65,7 @@ import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.ModuleVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.TypePath; @@ -160,7 +161,7 @@ public final class TraceClassVisitor extends ClassVisitor { */ public TraceClassVisitor(final ClassVisitor cv, final Printer p, final PrintWriter pw) { - super(Opcodes.ASM5, cv); + super(Opcodes.ASM6, cv); this.pw = pw; this.p = p; } @@ -179,6 +180,14 @@ public final class TraceClassVisitor extends ClassVisitor { super.visitSource(file, debug); } + @Override + public ModuleVisitor visitModule(String name, int flags, + String version) { + Printer p = this.p.visitModule(name, flags, version); + ModuleVisitor mv = super.visitModule(name, flags, version); + return new TraceModuleVisitor(mv, p); + } + @Override public void visitOuterClass(final String owner, final String name, final String desc) { diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java index 4c15f996fbfeb766b1a1e1b9997ed4aa8b868a61..1548879dd6dbe20963634836a62f974e56e071bf 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java @@ -79,7 +79,7 @@ public final class TraceFieldVisitor extends FieldVisitor { } public TraceFieldVisitor(final FieldVisitor fv, final Printer p) { - super(Opcodes.ASM5, fv); + super(Opcodes.ASM6, fv); this.p = p; } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java index ea679c6a0b92023eab62a2749e052fd25f7561a6..69343069c4d89d1f803e69eab07ee71ae8cc4020 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java @@ -81,7 +81,7 @@ public final class TraceMethodVisitor extends MethodVisitor { } public TraceMethodVisitor(final MethodVisitor mv, final Printer p) { - super(Opcodes.ASM5, mv); + super(Opcodes.ASM6, mv); this.p = p; } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceModuleVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceModuleVisitor.java new file mode 100644 index 0000000000000000000000000000000000000000..bad027eb423365c9a13bf07183427e9260afdf52 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceModuleVisitor.java @@ -0,0 +1,130 @@ +/* + * 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.util; + +import jdk.internal.org.objectweb.asm.ModuleVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +/** + * A {@link ModuleVisitor} that prints the fields it visits with a + * {@link Printer}. + * + * @author Remi Forax + */ +public final class TraceModuleVisitor extends ModuleVisitor { + + public final Printer p; + + public TraceModuleVisitor(final Printer p) { + this(null, p); + } + + public TraceModuleVisitor(final ModuleVisitor mv, final Printer p) { + super(Opcodes.ASM6, mv); + this.p = p; + } + + @Override + public void visitMainClass(String mainClass) { + p.visitMainClass(mainClass); + super.visitMainClass(mainClass); + } + + @Override + public void visitPackage(String packaze) { + p.visitPackage(packaze); + super.visitPackage(packaze); + } + + @Override + public void visitRequire(String module, int access, String version) { + p.visitRequire(module, access, version); + super.visitRequire(module, access, version); + } + + @Override + public void visitExport(String packaze, int access, String... modules) { + p.visitExport(packaze, access, modules); + super.visitExport(packaze, access, modules); + } + + @Override + public void visitOpen(String packaze, int access, String... modules) { + p.visitOpen(packaze, access, modules); + super.visitOpen(packaze, access, modules); + } + + @Override + public void visitUse(String use) { + p.visitUse(use); + super.visitUse(use); + } + + @Override + public void visitProvide(String service, String... providers) { + p.visitProvide(service, providers); + super.visitProvide(service, providers); + } + + @Override + public void visitEnd() { + p.visitModuleEnd(); + super.visitEnd(); + } +} diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java index ef78b14b8a2402e728be74de2d90e246b0e74b94..02e6b1da371e81ac3a70a3767ae2f3fc2404c1c3 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java @@ -104,13 +104,13 @@ public final class TraceSignatureVisitor extends SignatureVisitor { private String separator = ""; public TraceSignatureVisitor(final int access) { - super(Opcodes.ASM5); + super(Opcodes.ASM6); isInterface = (access & Opcodes.ACC_INTERFACE) != 0; this.declaration = new StringBuilder(); } private TraceSignatureVisitor(final StringBuilder buf) { - super(Opcodes.ASM5); + super(Opcodes.ASM6); this.declaration = buf; } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt index 5c62bb6faf9d5eefb4edd905632fd89a9ee29cf2..05e7371d76f36a1ff9f05018e50eb1822afdd53c 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt @@ -1,12 +1,4 @@ -Path: . -Working Copy Root Path: /hudson/jobs/objectweb-init/workspace/asm-svn-2016-01-25 -URL: file:///svnroot/asm/trunk/asm -Repository Root: file:///svnroot/asm -Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9 -Revision: 1795 -Node Kind: directory -Schedule: normal -Last Changed Author: ebruneton -Last Changed Rev: 1795 -Last Changed Date: 2016-01-24 14:17:10 +0100 (Sun, 24 Jan 2016) +ASM_6_0-11-gac81f5f +origin https://gitlab.ow2.org/asm/asm.git (fetch) +ac81f5f Merge branch 'add-class-dump-tool-for-unit-tests' into 'master' diff --git a/test/hotspot/jtreg/runtime/constantPool/ConstModule.java b/test/hotspot/jtreg/runtime/constantPool/ConstModule.java index 94e577a29ef05317f1ecda6090c6b5fb026fc287..27d9c2008b9cc676984fd8d42fb7de8e14740a6a 100644 --- a/test/hotspot/jtreg/runtime/constantPool/ConstModule.java +++ b/test/hotspot/jtreg/runtime/constantPool/ConstModule.java @@ -47,13 +47,13 @@ public class ConstModule { // Test that the JVM throws CFE for constant pool CONSTANT_Module type, for // class file version 53, when ACC_MODULE is not set in the access_flags. - ConstModule.write_and_load(Opcodes.V1_9, + ConstModule.write_and_load(Opcodes.V9, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC, "jdk.fooMod", "FooMod", MODULE_TEST, CFE_EXCEPTION); // Test that the JVM throws NCDFE for constant pool CONSTANT_Module type, // for class file version 53, when ACC_MODULE is set in the access_flags. - ConstModule.write_and_load(Opcodes.V1_9, + ConstModule.write_and_load(Opcodes.V9, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE, "jdk.fooModACC", "FooModACC", MODULE_TEST, NCDFE_EXCEPTION); @@ -65,13 +65,13 @@ public class ConstModule { // Test that the JVM throws CFE for constant pool CONSTANT_Package type, for // class file version 53, when ACC_MODULE is not set in the access_flags. - ConstModule.write_and_load(Opcodes.V1_9, + ConstModule.write_and_load(Opcodes.V9, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC, "jdk.fooPkg", "FooPkg", PACKAGE_TEST, CFE_EXCEPTION); // Test that the JVM throws NCDFE for constant pool CONSTANT_Package type, // for class file version 53, when ACC_MODULE is set in the access_flags. - ConstModule.write_and_load(Opcodes.V1_9, + ConstModule.write_and_load(Opcodes.V9, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE, "jdk.fooModACC", "FooModACC", PACKAGE_TEST, NCDFE_EXCEPTION); diff --git a/test/jdk/java/lang/ModuleTests/AnnotationsTest.java b/test/jdk/java/lang/ModuleTests/AnnotationsTest.java index de4125b7af8a44500bb70453e1ed3324e3c54bf2..847b6dda95bceeb36ff3750a66372797fec0ad51 100644 --- a/test/jdk/java/lang/ModuleTests/AnnotationsTest.java +++ b/test/jdk/java/lang/ModuleTests/AnnotationsTest.java @@ -34,13 +34,13 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; -import jdk.internal.module.ClassFileAttributes; import jdk.internal.org.objectweb.asm.AnnotationVisitor; import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute; import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -48,6 +48,7 @@ import static org.testng.Assert.*; /** * @test * @modules java.base/jdk.internal.org.objectweb.asm + * java.base/jdk.internal.org.objectweb.asm.commons * java.base/jdk.internal.module * java.xml * @run testng AnnotationsTest @@ -113,14 +114,11 @@ public class AnnotationsTest { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); - ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) { }; + ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) { }; ClassReader cr = new ClassReader(in); - List attrs = new ArrayList<>(); - attrs.add(new ClassFileAttributes.ModuleAttribute()); - attrs.add(new ClassFileAttributes.ModulePackagesAttribute()); - attrs.add(new ClassFileAttributes.ModuleTargetAttribute()); + attrs.add(new ModuleTargetAttribute()); cr.accept(cv, attrs.toArray(new Attribute[0]), 0); AnnotationVisitor annotationVisitor diff --git a/test/jdk/java/lang/invoke/DefineClassTest.java b/test/jdk/java/lang/invoke/DefineClassTest.java index fcad247d217ed00f39ea04dc7acc39fa2d1696b5..e16adb4dfb73c4b58d36c8b45fc913ac78cca6bd 100644 --- a/test/jdk/java/lang/invoke/DefineClassTest.java +++ b/test/jdk/java/lang/invoke/DefineClassTest.java @@ -243,7 +243,7 @@ public class DefineClassTest { byte[] generateClass(String className) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); - cw.visit(V1_9, + cw.visit(V9, ACC_PUBLIC + ACC_SUPER, className.replace(".", "/"), null, @@ -272,7 +272,7 @@ public class DefineClassTest { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); - cw.visit(V1_9, + cw.visit(V9, ACC_PUBLIC + ACC_SUPER, className.replace(".", "/"), null, @@ -309,7 +309,7 @@ public class DefineClassTest { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); - cw.visit(V1_9, + cw.visit(V9, ACC_PUBLIC + ACC_SUPER, className.replace(".", "/"), null, diff --git a/test/jdk/java/util/ServiceLoader/BadProvidersTest.java b/test/jdk/java/util/ServiceLoader/BadProvidersTest.java index 2ce27194bdd484f0f5a766ad8143f5dc6c9bd8d9..58613c7b5e35c8dbd7a24d751f72cb112f18cb08 100644 --- a/test/jdk/java/util/ServiceLoader/BadProvidersTest.java +++ b/test/jdk/java/util/ServiceLoader/BadProvidersTest.java @@ -209,7 +209,7 @@ public class BadProvidersTest { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); - cw.visit(V1_9, + cw.visit(V9, ACC_PUBLIC + ACC_SUPER, "p/ProviderFactory", null, diff --git a/test/jdk/lib/testlibrary/ModuleTargetHelper.java b/test/jdk/lib/testlibrary/ModuleTargetHelper.java index 67ff0c7b2d5ee1d9d7a095b860a77f277ab45484..ebb055f6e5bbe7d64a032f5ef550f576d12e5024 100644 --- a/test/jdk/lib/testlibrary/ModuleTargetHelper.java +++ b/test/jdk/lib/testlibrary/ModuleTargetHelper.java @@ -29,13 +29,9 @@ import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import jdk.internal.module.ClassFileConstants; -import jdk.internal.module.ClassFileAttributes; -import jdk.internal.module.ClassFileAttributes.ModuleTargetAttribute; -import jdk.internal.org.objectweb.asm.Attribute; -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; + +import jdk.internal.module.ModuleInfo; +import jdk.internal.module.ModuleInfo.Attributes; public class ModuleTargetHelper { private ModuleTargetHelper() {} @@ -60,29 +56,12 @@ public class ModuleTargetHelper { } public static ModuleTarget read(InputStream in) throws IOException { - ModuleTargetAttribute[] modTargets = new ModuleTargetAttribute[1]; - ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) { - @Override - public void visitAttribute(Attribute attr) { - if (attr instanceof ModuleTargetAttribute) { - modTargets[0] = (ModuleTargetAttribute)attr; - } - } - }; - - // prototype of attributes that should be parsed - Attribute[] attrs = new Attribute[] { - new ModuleTargetAttribute() - }; - - // parse module-info.class - ClassReader cr = new ClassReader(in); - cr.accept(cv, attrs, 0); - if (modTargets[0] != null) { - return new ModuleTarget(modTargets[0].targetPlatform()); + ModuleInfo.Attributes attrs = ModuleInfo.read(in, null); + if (attrs.target() != null) { + return new ModuleTarget(attrs.target().targetPlatform()); + } else { + return null; } - - return null; } public static ModuleTarget read(ModuleReference modRef) throws IOException { diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java index 59a059bca2e0923c7fda18f351be9d9bf3da1ce6..4b8a479443f9494740d695d57d1a05a4209204e1 100644 --- a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java +++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,35 +34,13 @@ import java.nio.file.Path; import java.util.Collections; import java.util.Set; -import jdk.internal.module.ClassFileAttributes; -import jdk.internal.module.ClassFileAttributes.ModuleTargetAttribute; -import jdk.internal.module.ClassFileConstants; -import jdk.internal.org.objectweb.asm.Attribute; -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.module.ModuleInfo; +import jdk.internal.module.ModuleInfo.Attributes; public class Main { private static boolean hasModuleTarget(InputStream in) throws IOException { - ModuleTargetAttribute[] modTargets = new ModuleTargetAttribute[1]; - ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) { - @Override - public void visitAttribute(Attribute attr) { - if (attr instanceof ModuleTargetAttribute) { - modTargets[0] = (ModuleTargetAttribute)attr; - } - } - }; - - // prototype of attributes that should be parsed - Attribute[] attrs = new Attribute[] { - new ModuleTargetAttribute() - }; - - // parse module-info.class - ClassReader cr = new ClassReader(in); - cr.accept(cv, attrs, 0); - return modTargets[0] != null && modTargets[0].targetPlatform() != null; + ModuleInfo.Attributes attrs = ModuleInfo.read(in, null); + return attrs.target() != null; } public static void main(String... args) throws Exception { diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Main.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Main.java index 396c4fc4da2cd1e5b01fe162cf2059273bfa2a95..c519b19791d2f93bf4ecd9650942d91270417762 100644 --- a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Main.java +++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Main.java @@ -35,35 +35,13 @@ import java.nio.file.Path; import java.util.Map; import java.util.Set; -import jdk.internal.module.ClassFileAttributes; -import jdk.internal.module.ClassFileAttributes.ModuleTargetAttribute; -import jdk.internal.module.ClassFileConstants; -import jdk.internal.org.objectweb.asm.Attribute; -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.module.ModuleInfo; +import jdk.internal.module.ModuleInfo.Attributes; public class Main { private static boolean hasModuleTarget(InputStream in) throws IOException { - ModuleTargetAttribute[] modTargets = new ModuleTargetAttribute[1]; - ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) { - @Override - public void visitAttribute(Attribute attr) { - if (attr instanceof ModuleTargetAttribute) { - modTargets[0] = (ModuleTargetAttribute)attr; - } - } - }; - - // prototype of attributes that should be parsed - Attribute[] attrs = new Attribute[] { - new ModuleTargetAttribute() - }; - - // parse module-info.class - ClassReader cr = new ClassReader(in); - cr.accept(cv, attrs, 0); - return modTargets[0] != null && modTargets[0].targetPlatform() != null; + ModuleInfo.Attributes attrs = ModuleInfo.read(in, null); + return attrs.target() != null; } private static boolean hasModuleTarget(String modName) throws IOException {