diff --git a/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java b/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java index 598c1293c4c..cec786e67df 100644 --- a/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java +++ b/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java @@ -23,121 +23,102 @@ package test.java.lang.invoke.lib; -import jdk.experimental.bytecode.BasicClassBuilder; -import jdk.experimental.bytecode.BasicTypeHelper; -import jdk.experimental.bytecode.Flag; -import jdk.experimental.bytecode.PoolHelper; -import jdk.experimental.bytecode.TypedCodeBuilder; +import jdk.internal.classfile.ClassBuilder; +import jdk.internal.classfile.Classfile; +import jdk.internal.classfile.TypeKind; -import java.io.FileOutputStream; +import java.lang.constant.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; -import java.util.function.Function; import static java.lang.invoke.MethodType.fromMethodDescriptorString; -import static java.lang.invoke.MethodType.methodType; public class InstructionHelper { - static final BasicTypeHelper BTH = new BasicTypeHelper(); - static final AtomicInteger COUNT = new AtomicInteger(); - static BasicClassBuilder classBuilder(MethodHandles.Lookup l) { - String className = l.lookupClass().getCanonicalName().replace('.', '/') + "$Code_" + COUNT.getAndIncrement(); - return new BasicClassBuilder(className, 55, 0) - .withSuperclass("java/lang/Object") - .withMethod("<init>", "()V", M -> - M.withFlags(Flag.ACC_PUBLIC) - .withCode(TypedCodeBuilder::new, C -> - C.aload_0().invokespecial("java/lang/Object", "<init>", "()V", false).return_() - )); + private static void commonBuild(ClassBuilder classBuilder) { + classBuilder + .withVersion(55, 0) + .withSuperclass(ConstantDescs.CD_Object) + .withMethod(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void, Classfile.ACC_PUBLIC, + methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .aload(0) + .invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME, + ConstantDescs.MTD_void, false) + .return_())); } - public static MethodHandle invokedynamic(MethodHandles.Lookup l, - String name, MethodType type, - String bsmMethodName, MethodType bsmType, - Consumer<PoolHelper.StaticArgListBuilder<String, String, byte[]>> staticArgs) throws Exception { - byte[] byteArray = classBuilder(l) - .withMethod("m", type.toMethodDescriptorString(), M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, - C -> { - for (int i = 0; i < type.parameterCount(); i++) { - C.load(BTH.tag(cref(type.parameterType(i))), i); - } - C.invokedynamic(name, type.toMethodDescriptorString(), - csym(l.lookupClass()), bsmMethodName, bsmType.toMethodDescriptorString(), - staticArgs); - C.return_(BTH.tag(cref(type.returnType()))); - } - )) - .build(); + public static MethodHandle invokedynamic(MethodHandles.Lookup l, String name, MethodType type, String bsmMethodName, + MethodType bsmType, ConstantDesc... boostrapArgs) throws Exception { + ClassDesc genClassDesc = classDesc(l.lookupClass(), "$Code_" + COUNT.getAndIncrement()); + byte[] byteArray = Classfile.of().build(genClassDesc, classBuilder -> { + commonBuild(classBuilder); + classBuilder + .withMethod("m", MethodTypeDesc.ofDescriptor(type.toMethodDescriptorString()), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> { + for (int i = 0; i < type.parameterCount(); i++) { + codeBuilder.loadInstruction(TypeKind.from(type.parameterType(i)), i); + } + codeBuilder.invokedynamic(DynamicCallSiteDesc.of( + MethodHandleDesc.ofMethod( + DirectMethodHandleDesc.Kind.STATIC, + classDesc(l.lookupClass()), + bsmMethodName, + MethodTypeDesc.ofDescriptor( + bsmType.toMethodDescriptorString())), + name, + MethodTypeDesc.ofDescriptor(type.toMethodDescriptorString()), + boostrapArgs)); + codeBuilder.returnInstruction(TypeKind.from(type.returnType())); + })); + }); Class<?> gc = l.defineClass(byteArray); return l.findStatic(gc, "m", type); } - public static MethodHandle ldcMethodHandle(MethodHandles.Lookup l, - int refKind, Class<?> owner, String name, MethodType type) throws Exception { - return ldc(l, MethodHandle.class, - P -> P.putHandle(refKind, csym(owner), name, type.toMethodDescriptorString())); + public static MethodHandle ldcDynamicConstant(MethodHandles.Lookup l, String name, Class<?> type, String bsmMethodName, + MethodType bsmType, ConstantDesc... bootstrapArgs) throws Exception { + return ldcDynamicConstant(l, name, type, l.lookupClass(), bsmMethodName, bsmType, bootstrapArgs); } - public static MethodHandle ldcDynamicConstant(MethodHandles.Lookup l, - String name, Class<?> type, - String bsmMethodName, MethodType bsmType, - Consumer<PoolHelper.StaticArgListBuilder<String, String, byte[]>> staticArgs) throws Exception { - return ldcDynamicConstant(l, name, type, l.lookupClass(), bsmMethodName, bsmType, staticArgs); + public static MethodHandle ldcDynamicConstant(MethodHandles.Lookup l, String name, Class<?> type, Class<?> bsmClass, + String bsmMethodName, MethodType bsmType, ConstantDesc... bootstrapArgs) throws Exception { + return ldcDynamicConstant(l, name, type.descriptorString(), bsmClass.descriptorString(), bsmMethodName, + bsmType.descriptorString(), bootstrapArgs); } - public static MethodHandle ldcDynamicConstant(MethodHandles.Lookup l, - String name, Class<?> type, - Class<?> bsmClass, String bsmMethodName, MethodType bsmType, - Consumer<PoolHelper.StaticArgListBuilder<String, String, byte[]>> staticArgs) throws Exception { - return ldcDynamicConstant(l, name, cref(type), csym(bsmClass), bsmMethodName, bsmType.toMethodDescriptorString(), staticArgs); + public static MethodHandle ldcDynamicConstant(MethodHandles.Lookup l, String name, String type, String bsmMethodName, + String bsmType, ConstantDesc... bootstrapArgs) throws Exception { + return ldcDynamicConstant(l, name, type, l.lookupClass().descriptorString(), bsmMethodName, bsmType, bootstrapArgs); } - public static MethodHandle ldcDynamicConstant(MethodHandles.Lookup l, - String name, String type, - String bsmMethodName, String bsmType, - Consumer<PoolHelper.StaticArgListBuilder<String, String, byte[]>> staticArgs) throws Exception { - return ldcDynamicConstant(l, name, type, csym(l.lookupClass()), bsmMethodName, bsmType, staticArgs); - } - - public static MethodHandle ldcDynamicConstant(MethodHandles.Lookup l, - String name, String type, - String bsmClass, String bsmMethodName, String bsmType, - Consumer<PoolHelper.StaticArgListBuilder<String, String, byte[]>> staticArgs) throws Exception { - return ldc(l, type, - P -> P.putDynamicConstant(name, type, - bsmClass, bsmMethodName, bsmType, - staticArgs)); - } - - public static MethodHandle ldc(MethodHandles.Lookup l, - Class<?> type, - Function<PoolHelper<String, String, byte[]>, Integer> poolFunc) throws Exception { - return ldc(l, cref(type), poolFunc); - } - - public static MethodHandle ldc(MethodHandles.Lookup l, - String type, - Function<PoolHelper<String, String, byte[]>, Integer> poolFunc) throws Exception { + public static MethodHandle ldcDynamicConstant(MethodHandles.Lookup l, String name, String type, String bsmClass, + String bsmMethodName, String bsmType, ConstantDesc... bootstrapArgs) + throws IllegalAccessException, NoSuchMethodException { String methodType = "()" + type; - byte[] byteArray = classBuilder(l) - .withMethod("m", "()" + type, M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, - C -> { - C.ldc(null, (P, v) -> poolFunc.apply(P)); - C.return_(BTH.tag(type)); - } - )) - .build(); - Class<?> gc = l.defineClass(byteArray); + ClassDesc genClassDesc = classDesc(l.lookupClass(), "$Code_" + COUNT.getAndIncrement()); + byte[] bytes = Classfile.of().build(genClassDesc, classBuilder -> { + commonBuild(classBuilder); + classBuilder.withMethod("m", MethodTypeDesc.of(ClassDesc.ofDescriptor(type)), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + MethodHandleDesc.ofMethod( + DirectMethodHandleDesc.Kind.STATIC, + ClassDesc.ofDescriptor(bsmClass), + bsmMethodName, + MethodTypeDesc.ofDescriptor(bsmType)), + name, + ClassDesc.ofDescriptor(type), + bootstrapArgs)) + .returnInstruction(TypeKind.fromDescriptor(type)))); + }); + Class<?> gc = l.defineClass(bytes); return l.findStatic(gc, "m", fromMethodDescriptorString(methodType, l.lookupClass().getClassLoader())); } @@ -145,7 +126,13 @@ public class InstructionHelper { return c.getCanonicalName().replace('.', '/'); } - public static String cref(Class<?> c) { - return methodType(c).toMethodDescriptorString().substring(2); + public static ClassDesc classDesc(Class<?> c) { + return ClassDesc.ofDescriptor(c.descriptorString()); + } + + public static ClassDesc classDesc(Class<?> c, String suffix) { + StringBuilder sb = new StringBuilder(c.descriptorString()); + String classDescStr = sb.insert(sb.length() - 1, suffix).toString(); + return ClassDesc.ofDescriptor(classDescStr); } } diff --git a/test/jdk/java/lang/invoke/condy/BootstrapMethodJumboArgsTest.java b/test/jdk/java/lang/invoke/condy/BootstrapMethodJumboArgsTest.java index 4707060c3cd..75b88775338 100644 --- a/test/jdk/java/lang/invoke/condy/BootstrapMethodJumboArgsTest.java +++ b/test/jdk/java/lang/invoke/condy/BootstrapMethodJumboArgsTest.java @@ -25,13 +25,17 @@ * @test * @bug 8186046 * @summary Test bootstrap methods throwing an exception - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng BootstrapMethodJumboArgsTest * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 BootstrapMethodJumboArgsTest */ -import jdk.experimental.bytecode.PoolHelper; import org.testng.Assert; import org.testng.annotations.Test; import test.java.lang.invoke.lib.InstructionHelper; @@ -49,12 +53,11 @@ public class BootstrapMethodJumboArgsTest { static Object bsmZero(MethodHandles.Lookup l, String name, Object type, - Object... args) { + Object... args) { Object[] a = args.clone(); if (type instanceof MethodType) { return new ConstantCallSite(MethodHandles.constant(Object[].class, a)); - } - else { + } else { return a; } } @@ -66,8 +69,7 @@ public class BootstrapMethodJumboArgsTest { System.arraycopy(args, 0, a, 1, args.length); if (type instanceof MethodType) { return new ConstantCallSite(MethodHandles.constant(Object[].class, a)); - } - else { + } else { return a; } } @@ -80,18 +82,11 @@ public class BootstrapMethodJumboArgsTest { System.arraycopy(args, 0, a, 2, args.length); if (type instanceof MethodType) { return new ConstantCallSite(MethodHandles.constant(Object[].class, a)); - } - else { + } else { return a; } } - static void manyStaticStrings(String[] args, PoolHelper.StaticArgListBuilder<String, String, byte[]> staticArgs) { - for (String s : args) { - staticArgs.add(s); - } - } - @Test public void testCondyWithJumboArgs() throws Throwable { String[] expected = IntStream.range(0, 1000).mapToObj(Integer::toString).toArray(String[]::new); @@ -99,8 +94,8 @@ public class BootstrapMethodJumboArgsTest { { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", Object[].class, - "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object[].class), - S -> manyStaticStrings(expected, S)); + "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class, + Object.class, Object[].class), expected); Object[] actual = (Object[]) mh.invoke(); Assert.assertEquals(actual, expected); @@ -109,8 +104,8 @@ public class BootstrapMethodJumboArgsTest { { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", Object[].class, - "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class, Object[].class), - S -> manyStaticStrings(expected, S)); + "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class, + Object.class, Object.class, Object[].class), expected); Object[] actual = (Object[]) mh.invoke(); Assert.assertEquals(actual, expected); @@ -119,8 +114,8 @@ public class BootstrapMethodJumboArgsTest { { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", Object[].class, - "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class, Object.class, Object[].class), - S -> manyStaticStrings(expected, S)); + "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class, + Object.class, Object.class, Object.class, Object[].class), expected); Object[] actual = (Object[]) mh.invoke(); Assert.assertEquals(actual, expected); @@ -134,8 +129,8 @@ public class BootstrapMethodJumboArgsTest { { MethodHandle mh = InstructionHelper.invokedynamic( L, "name", methodType(Object[].class), - "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object[].class), - S -> manyStaticStrings(expected, S)); + "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class, + Object.class, Object[].class), expected); Object[] actual = (Object[]) mh.invoke(); Assert.assertEquals(actual, expected); @@ -144,8 +139,8 @@ public class BootstrapMethodJumboArgsTest { { MethodHandle mh = InstructionHelper.invokedynamic( L, "name", methodType(Object[].class), - "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class, Object[].class), - S -> manyStaticStrings(expected, S)); + "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class, + Object.class, Object.class, Object[].class), expected); Object[] actual = (Object[]) mh.invoke(); Assert.assertEquals(actual, expected); @@ -154,8 +149,8 @@ public class BootstrapMethodJumboArgsTest { { MethodHandle mh = InstructionHelper.invokedynamic( L, "name", methodType(Object[].class), - "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class, Object.class, Object[].class), - S -> manyStaticStrings(expected, S)); + "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class, + Object.class, Object.class, Object.class, Object[].class), expected); Object[] actual = (Object[]) mh.invoke(); Assert.assertEquals(actual, expected); diff --git a/test/jdk/java/lang/invoke/condy/CondyBSMException.java b/test/jdk/java/lang/invoke/condy/CondyBSMException.java index c9d2f9a12f0..4a8b5106c12 100644 --- a/test/jdk/java/lang/invoke/condy/CondyBSMException.java +++ b/test/jdk/java/lang/invoke/condy/CondyBSMException.java @@ -25,8 +25,13 @@ * @test * @bug 8186046 * @summary Test bootstrap methods throwing an exception - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyBSMException * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyBSMException */ @@ -64,7 +69,7 @@ public class CondyBSMException { } @Test - public void testException() throws Throwable { + public void testException() { test("Exception", BootstrapMethodError.class, Exception.class); } @@ -73,8 +78,7 @@ public class CondyBSMException { Throwable caught = null; try { mh.invoke(); - } - catch (Throwable t) { + } catch (Throwable t) { caught = t; } @@ -98,8 +102,7 @@ public class CondyBSMException { try { Constructor<Throwable> c = type.getDeclaredConstructor(String.class); t = c.newInstance(name); - } - catch (Exception e) { + } catch (Exception e) { throw new InternalError(); } throw t; @@ -110,8 +113,9 @@ public class CondyBSMException { return InstructionHelper.ldcDynamicConstant( MethodHandles.lookup(), message, t, - "throwingBsm", methodType(Throwable.class, MethodHandles.Lookup.class, String.class, Class.class), - S -> { }); + "throwingBsm", + methodType(Throwable.class, MethodHandles.Lookup.class, String.class, Class.class) + ); } catch (Exception e) { throw new Error(e); } diff --git a/test/jdk/java/lang/invoke/condy/CondyBSMInvocation.java b/test/jdk/java/lang/invoke/condy/CondyBSMInvocation.java index 86a68049790..0cf51f4819b 100644 --- a/test/jdk/java/lang/invoke/condy/CondyBSMInvocation.java +++ b/test/jdk/java/lang/invoke/condy/CondyBSMInvocation.java @@ -25,8 +25,13 @@ * @test * @bug 8186046 8199875 * @summary Test basic invocation of bootstrap methods - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyBSMInvocation * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyBSMInvocation */ @@ -36,6 +41,7 @@ import org.testng.Assert; import org.testng.annotations.Test; import test.java.lang.invoke.lib.InstructionHelper; +import java.lang.constant.ConstantDesc; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -55,8 +61,8 @@ public class CondyBSMInvocation { public void testNonexistent() throws Throwable { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", Object.class, - "bsm", methodType(Object.class), - S -> {}); + "bsm", methodType(Object.class) + ); try { mh.invoke(); @@ -110,8 +116,7 @@ public class CondyBSMInvocation { for (MethodHandle bsm : bsms("shape_bsm")) { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", Object.class, - "shape_bsm", bsm.type(), - S -> {} + "shape_bsm", bsm.type() ); try { @@ -136,8 +141,7 @@ public class CondyBSMInvocation { for (MethodHandle bsm : bsms("sig_bsm")) { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", Object.class, - "sig_bsm", bsm.type(), - S -> {} + "sig_bsm", bsm.type() ); try { @@ -216,8 +220,8 @@ public class CondyBSMInvocation { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", Object.class, "bsm", mt, - S -> IntStream.range(0, n).forEach(S::add) - ); + IntStream.range(0, n).boxed().toArray(ConstantDesc[]::new) + ); Object r = mh.invoke(); Assert.assertEquals(r, Integer.toString(n)); @@ -228,7 +232,7 @@ public class CondyBSMInvocation { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", Object.class, "bsm", mt, - S -> IntStream.range(0, 9).forEach(S::add) + IntStream.range(0, 9).boxed().toArray(ConstantDesc[]::new) ); Object r = mh.invoke(); @@ -246,7 +250,7 @@ public class CondyBSMInvocation { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", Object.class, "bsm", mt, - S -> IntStream.range(0, n - 1).forEach(S::add) + IntStream.range(0, n - 1).boxed().toArray(ConstantDesc[]::new) ); try { diff --git a/test/jdk/java/lang/invoke/condy/CondyBSMValidationTest.java b/test/jdk/java/lang/invoke/condy/CondyBSMValidationTest.java index c3e14877863..d833ddd279f 100644 --- a/test/jdk/java/lang/invoke/condy/CondyBSMValidationTest.java +++ b/test/jdk/java/lang/invoke/condy/CondyBSMValidationTest.java @@ -25,12 +25,18 @@ * @test * @bug 8186046 * @summary Test invalid name in name and type - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyBSMValidationTest * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyBSMValidationTest */ +import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import test.java.lang.invoke.lib.InstructionHelper; @@ -49,19 +55,22 @@ public class CondyBSMValidationTest { @DataProvider public Object[][] invalidSignaturesProvider() throws Exception { return Stream.of(BSM_TYPE.replace("(", ""), - BSM_TYPE.replace(")", ""), - BSM_TYPE.replace("(", "").replace(")", ""), - BSM_TYPE.replace(";)", ")"), - BSM_TYPE.replace(";", "")) + BSM_TYPE.replace(")", ""), + BSM_TYPE.replace("(", "").replace(")", ""), + BSM_TYPE.replace(";)", ")"), + BSM_TYPE.replace(";", "")) .map(e -> new Object[]{e}).toArray(Object[][]::new); } - @Test(dataProvider = "invalidSignaturesProvider", expectedExceptions = ClassFormatError.class) + @Test(dataProvider = "invalidSignaturesProvider") public void testInvalidBSMSignature(String sig) throws Exception { - MethodHandle mh = InstructionHelper.ldcDynamicConstant( - L, "name", "Ljava/lang/Object;", - "bsm", sig, - S -> { - }); + try { + MethodHandle mh = InstructionHelper.ldcDynamicConstant( + L, "name", "Ljava/lang/Object;", + "bsm", sig + ); + } catch (IllegalArgumentException e) { + Assert.assertTrue(e.getMessage().contains("Bad method descriptor")); + } } } diff --git a/test/jdk/java/lang/invoke/condy/CondyInterfaceWithOverpassMethods.java b/test/jdk/java/lang/invoke/condy/CondyInterfaceWithOverpassMethods.java index fb32bec7834..9ba6e3c28f7 100644 --- a/test/jdk/java/lang/invoke/condy/CondyInterfaceWithOverpassMethods.java +++ b/test/jdk/java/lang/invoke/condy/CondyInterfaceWithOverpassMethods.java @@ -25,18 +25,23 @@ * @test * @bug 8186046 * @summary Test for an interface using condy with default overpass methods - * @library /lib/testlibrary/bytecode - * @build jdk.experimental.bytecode.BasicClassBuilder + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyInterfaceWithOverpassMethods * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyInterfaceWithOverpassMethods */ -import jdk.experimental.bytecode.BasicClassBuilder; -import jdk.experimental.bytecode.Flag; -import jdk.experimental.bytecode.TypedCodeBuilder; +import jdk.internal.classfile.Classfile; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import test.java.lang.invoke.lib.InstructionHelper; +import java.lang.constant.*; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -70,24 +75,32 @@ public class CondyInterfaceWithOverpassMethods { Class<?> thisClass = CondyInterfaceWithOverpassMethods.class; String genClassName = thisClass.getSimpleName() + "$Code"; - String bsmClassName = thisClass.getCanonicalName().replace('.', '/'); + String bsmClassName = thisClass.descriptorString(); String bsmMethodName = "bsm"; String bsmDescriptor = MethodType.methodType(Object.class, MethodHandles.Lookup.class, - String.class, Class.class).toMethodDescriptorString(); - - byte[] byteArray = new BasicClassBuilder(genClassName, 55, 0) - .withFlags(Flag.ACC_INTERFACE, Flag.ACC_ABSTRACT) - .withSuperclass("java/lang/Object") - .withSuperinterface(thisClass.getCanonicalName().replace('.', '/') + "$" + A.class.getSimpleName()) - .withMethod("y", "()Ljava/lang/String;", M -> - M.withFlags(Flag.ACC_PUBLIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("String", "Ljava/lang/String;", bsmClassName, bsmMethodName, bsmDescriptor, - S -> {}) - .areturn() - )) - .build(); + String.class, Class.class).toMethodDescriptorString(); + byte[] byteArray = Classfile.of().build(ClassDesc.of(genClassName), classBuilder -> classBuilder + .withFlags(Classfile.ACC_INTERFACE + Classfile.ACC_ABSTRACT) + .withSuperclass(ConstantDescs.CD_Object) + .withInterfaceSymbols(InstructionHelper.classDesc(A.class)) + .withMethod("y", MethodTypeDesc.of(ConstantDescs.CD_String), Classfile.ACC_PUBLIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + MethodHandleDesc.of( + DirectMethodHandleDesc.Kind.STATIC, + ClassDesc.ofDescriptor(bsmClassName), + bsmMethodName, + bsmDescriptor + ), + "String", + ConstantDescs.CD_String + ) + ) + .areturn() + ) + ) + ); gc = MethodHandles.lookup().defineClass(byteArray); } diff --git a/test/jdk/java/lang/invoke/condy/CondyNameValidationTest.java b/test/jdk/java/lang/invoke/condy/CondyNameValidationTest.java index b7d6999fb4d..24a71a80edb 100644 --- a/test/jdk/java/lang/invoke/condy/CondyNameValidationTest.java +++ b/test/jdk/java/lang/invoke/condy/CondyNameValidationTest.java @@ -25,12 +25,18 @@ * @test * @bug 8186046 * @summary Test invalid name in name and type - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyNameValidationTest * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyNameValidationTest */ +import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import test.java.lang.invoke.lib.InstructionHelper; @@ -47,29 +53,33 @@ public class CondyNameValidationTest { static final MethodType BSM_TYPE = methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class); @DataProvider - public Object[][] invalidNamesProvider() throws Exception { - return Stream.of("", - ".", - ";", - "[", - "/") - .map(e -> new Object[]{e}).toArray(Object[][]::new); + public Object[][] invalidNamesProvider() { + return Stream.of( + new Object[]{"", "zero-length member name"}, + new Object[]{".", "Invalid member name"}, + new Object[]{";", "Invalid member name"}, + new Object[]{"[", "Invalid member name"}, + new Object[]{"/", "Invalid member name"} + ) + .toArray(Object[][]::new); } - @Test(dataProvider = "invalidNamesProvider", expectedExceptions = java.lang.ClassFormatError.class) - public void testInvalidNames(String name) throws Exception { - MethodHandle mh = InstructionHelper.ldcDynamicConstant( - L, name, Object.class, - "bsm", BSM_TYPE, - S -> { - }); + @Test(dataProvider = "invalidNamesProvider") + public void testInvalidNames(String name, String errMessContent) throws Exception { + try { + MethodHandle mh = InstructionHelper.ldcDynamicConstant( + L, name, Object.class, + "bsm", BSM_TYPE + ); + } catch (IllegalArgumentException e) { + Assert.assertTrue(e.getMessage().contains(errMessContent)); + } } @DataProvider public Object[][] validNamesProvider() throws Exception { return Stream.of("<clinit>", - "<init>", - "<foo>") + "<init>") .map(e -> new Object[]{e}).toArray(Object[][]::new); } @@ -77,8 +87,7 @@ public class CondyNameValidationTest { public void testValidNames(String name) throws Exception { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, name, Object.class, - "bsm", BSM_TYPE, - S -> { - }); + "bsm", BSM_TYPE + ); } } diff --git a/test/jdk/java/lang/invoke/condy/CondyNestedTest.java b/test/jdk/java/lang/invoke/condy/CondyNestedTest.java index 7cb3ebd56e6..dc11c7f560a 100644 --- a/test/jdk/java/lang/invoke/condy/CondyNestedTest.java +++ b/test/jdk/java/lang/invoke/condy/CondyNestedTest.java @@ -26,6 +26,11 @@ * @bug 8186046 * @summary Test nested dynamic constant declarations that are recursive * @compile CondyNestedTest_Code.jcod + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyNestedTest * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyNestedTest */ @@ -34,21 +39,17 @@ import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import java.lang.invoke.MethodHandles; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class CondyNestedTest { static final Class[] THROWABLES = {InvocationTargetException.class, StackOverflowError.class}; + private static final MethodHandles.Lookup L = MethodHandles.lookup(); Class<?> c; -// Add the following annotations to the test description if uncommenting the -// following code -// -// * @library /lib/testlibrary/bytecode -// * @build jdk.experimental.bytecode.BasicClassBuilder -// // static final MethodHandles.Lookup L = MethodHandles.lookup(); // // /** @@ -65,97 +66,178 @@ public class CondyNestedTest { // */ // public static byte[] generator() throws Exception { // String genClassName = L.lookupClass().getSimpleName() + "_Code"; -// String bsmDescriptor = MethodType.methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class).toMethodDescriptorString(); -// String bsmIndyDescriptor = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class).toMethodDescriptorString(); +// ClassDesc genClassDesc = ClassDesc.of(genClassName); +// String bsmDescriptor = MethodType.methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, +// Object.class).toMethodDescriptorString(); +// String bsmIndyDescriptor = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, +// Object.class, Object.class).toMethodDescriptorString(); +// DirectMethodHandleDesc bsmMhDesc = MethodHandleDesc.of( +// DirectMethodHandleDesc.Kind.STATIC, +// genClassDesc, +// "bsm", +// bsmDescriptor +// ); +// DirectMethodHandleDesc bsmIndyMhDesc = MethodHandleDesc.of( +// DirectMethodHandleDesc.Kind.STATIC, +// genClassDesc, +// "bsmIndy", +// bsmIndyDescriptor +// ); +// byte[] byteArray = Classfile.of().build(ClassDesc.of(genClassName), classBuilder -> classBuilder +// .withVersion(55, 0) +// .withSuperclass(ConstantDescs.CD_Object) +// .withMethod(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void, Classfile.ACC_PUBLIC, methodBuilder -> methodBuilder +// .withCode(codeBuilder -> codeBuilder +// .aload(0) +// .invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME, ConstantDescs.MTD_void) +// .return_() +// ) +// ) +// .withMethod("main", MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_String.arrayType()), +// Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder +// .withCode(codeBuilder -> { +// codeBuilder +// .aload(0) +// .iconst_0() +// .aaload() +// .invokevirtual(ConstantDescs.CD_String, "intern", +// MethodTypeDesc.of(ConstantDescs.CD_String)) +// .astore(1); +// Label case1 = codeBuilder.newLabel(); +// codeBuilder +// .aload(1) +// .ldc("condy_bsm_condy_bsm") +// .if_acmpne(case1) +// .invokestatic(genClassDesc, "condy_bsm_condy_bsm", +// MethodTypeDesc.of(ConstantDescs.CD_Object)) +// .return_(); +// Label case2 = codeBuilder.newLabel(); +// codeBuilder +// .labelBinding(case1) +// .aload(1) +// .ldc("indy_bsmIndy_condy_bsm") +// .if_acmpne(case2) +// .invokestatic(genClassDesc, "indy_bsmIndy_condy_bsm", +// MethodTypeDesc.of(ConstantDescs.CD_Object)) +// .return_(); +// Label case3 = codeBuilder.newLabel(); +// codeBuilder +// .labelBinding(case2) +// .aload(1) +// .ldc("indy_bsm_condy_bsm") +// .if_acmpne(case3) +// .invokestatic(genClassDesc, "indy_bsm_condy_bsm", +// MethodTypeDesc.of(ConstantDescs.CD_Object)) +// .return_(); +// codeBuilder +// .labelBinding(case3) +// .return_(); +// } +// ) +// ) +// // bsm that when used with indy returns a call site whose target is MethodHandles.constant(String.class, name), and +// // when used with condy returns the name +// .withMethod("bsm", MethodTypeDesc.ofDescriptor(bsmDescriptor), +// Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder +// .withCode(codeBuilder -> { +// codeBuilder +// .aload(2) +// .instanceof_(ConstantDescs.CD_MethodType) +// .iconst_0(); +// Label condy = codeBuilder.newLabel(); +// codeBuilder +// .if_acmpeq(condy) +// .new_(ClassDesc.ofDescriptor(ConstantCallSite.class.descriptorString())) +// .dup() +// .ldc(ConstantDescs.CD_String) +// .aload(1) +// .invokestatic(ConstantDescs.CD_MethodHandles, "constant", +// MethodTypeDesc.of(ConstantDescs.CD_MethodHandle, ConstantDescs.CD_Class, +// ConstantDescs.CD_Object)) +// .invokespecial(ClassDesc.ofDescriptor(ConstantCallSite.class.descriptorString()), +// ConstantDescs.INIT_NAME, +// MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_MethodHandle)) +// .areturn(); +// codeBuilder +// .labelBinding(condy) +// .aload(1) +// .areturn(); +// } // -// byte[] byteArray = new BasicClassBuilder(genClassName, 55, 0) -// .withSuperclass("java/lang/Object") -// .withMethod("<init>", "()V", M -> -// M.withFlags(Flag.ACC_PUBLIC) -// .withCode(TypedCodeBuilder::new, C -> -// C.aload_0().invokespecial("java/lang/Object", "<init>", "()V", false).return_() -// )) -// .withMethod("main", "([Ljava/lang/String;)V", M -> -// M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) -// .withCode(TypedCodeBuilder::new, C -> { -// C.aload_0().iconst_0().aaload(); -// C.invokevirtual("java/lang/String", "intern", "()Ljava/lang/String;", false); -// C.astore_1(); -// -// C.aload_1(); -// C.ldc("condy_bsm_condy_bsm"); -// C.ifcmp(TypeTag.A, MacroCodeBuilder.CondKind.NE, "CASE1"); -// C.invokestatic(genClassName, "condy_bsm_condy_bsm", "()Ljava/lang/Object;", false).return_(); -// -// C.label("CASE1"); -// C.aload_1(); -// C.ldc("indy_bsmIndy_condy_bsm"); -// C.ifcmp(TypeTag.A, MacroCodeBuilder.CondKind.NE, "CASE2"); -// C.invokestatic(genClassName, "indy_bsmIndy_condy_bsm", "()Ljava/lang/Object;", false).return_(); -// -// C.label("CASE2"); -// C.aload_1(); -// C.ldc("indy_bsm_condy_bsm"); -// C.ifcmp(TypeTag.A, MacroCodeBuilder.CondKind.NE, "CASE3"); -// C.invokestatic(genClassName, "indy_bsm_condy_bsm", "()Ljava/lang/Object;", false).return_(); -// -// C.label("CASE3"); -// C.return_(); -// })) -// .withMethod("bsm", bsmDescriptor, M -> -// M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) -// .withCode(TypedCodeBuilder::new, C -> { -// C.aload_2(); -// C.instanceof_("java/lang/invoke/MethodType"); -// C.iconst_0(); -// C.ifcmp(TypeTag.I, MacroCodeBuilder.CondKind.EQ, "CONDY"); -// C.new_("java/lang/invoke/ConstantCallSite").dup(); -// C.ldc("java/lang/String", PoolHelper::putClass); -// C.aload_1(); -// C.invokestatic("java/lang/invoke/MethodHandles", "constant", "(Ljava/lang/Class;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;", false); -// C.invokespecial("java/lang/invoke/ConstantCallSite", "<init>", "(Ljava/lang/invoke/MethodHandle;)V", false); -// C.areturn(); -// C.label("CONDY"); -// C.aload_1().areturn(); -// })) -// .withMethod("bsmIndy", bsmIndyDescriptor, M -> -// M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) -// .withCode(TypedCodeBuilder::new, C -> { -// C.new_("java/lang/invoke/ConstantCallSite").dup(); -// C.ldc("java/lang/String", PoolHelper::putClass); -// C.aload_1(); -// C.invokestatic("java/lang/invoke/MethodHandles", "constant", "(Ljava/lang/Class;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;", false); -// C.invokespecial("java/lang/invoke/ConstantCallSite", "<init>", "(Ljava/lang/invoke/MethodHandle;)V", false); -// C.areturn(); -// })) -// .withMethod("condy_bsm_condy_bsm", "()Ljava/lang/Object;", M -> -// M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) -// .withCode(TypedCodeBuilder::new, C -> -// C.ldc("name", "Ljava/lang/String;", genClassName, "bsm", bsmDescriptor, -// S -> S.add(null, (P, v) -> { -// return P.putDynamicConstant("name", "Ljava/lang/String;", genClassName, "bsm", bsmDescriptor, -// S2 -> S2.add("DUMMY_ARG", PoolHelper::putString)); -// })) -// .areturn())) -// .withMethod("indy_bsmIndy_condy_bsm", "()Ljava/lang/Object;", M -> -// M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) -// .withCode(TypedCodeBuilder::new, C -> -// C.invokedynamic("name", "()Ljava/lang/String;", genClassName, "bsmIndy", bsmIndyDescriptor, -// S -> S.add(null, (P, v) -> { -// return P.putDynamicConstant("name", "Ljava/lang/String;", genClassName, "bsm", bsmDescriptor, -// S2 -> S2.add("DUMMY_ARG", PoolHelper::putString)); -// })) -// .areturn())) -// .withMethod("indy_bsm_condy_bsm", "()Ljava/lang/Object;", M -> -// M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) -// .withCode(TypedCodeBuilder::new, C -> -// C.invokedynamic("name", "()Ljava/lang/String;", genClassName, "bsm", bsmDescriptor, -// S -> S.add(null, (P, v) -> { -// return P.putDynamicConstant("name", "Ljava/lang/String;", genClassName, "bsm", bsmDescriptor, -// S2 -> S2.add("DUMMY_ARG", PoolHelper::putString)); -// })) -// .areturn())) -// .build(); +// ) +// ) +// // an indy bsm, that returns a call site whose target is MethodHandles.constant(String.class, methodName) +// .withMethod("bsmIndy", MethodTypeDesc.ofDescriptor(bsmIndyDescriptor), +// Classfile.ACC_PUBLIC + Classfile.ACC_PUBLIC, methodBuilder -> methodBuilder +// .withCode(codeBuilder -> codeBuilder +// .new_(ClassDesc.ofDescriptor(ConstantCallSite.class.descriptorString())) +// .dup() +// .ldc(ConstantDescs.CD_String) +// .aload(1) +// .invokestatic(ConstantDescs.CD_MethodHandles, "constant", +// MethodTypeDesc.of(ConstantDescs.CD_MethodHandle, ConstantDescs.CD_Class, +// ConstantDescs.CD_Object)) +// .invokespecial(ClassDesc.ofDescriptor(ConstantCallSite.class.descriptorString()), +// ConstantDescs.INIT_NAME, +// MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_MethodHandle)) +// .areturn() +// ) +// ) +// .withMethod("condy_bsm_condy_bsm", MethodTypeDesc.of(ConstantDescs.CD_Object), +// Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder +// .withCode(codeBuilder -> codeBuilder +// .ldc(DynamicConstantDesc.ofNamed( +// bsmMhDesc, +// "name", +// ConstantDescs.CD_String, +// DynamicConstantDesc.ofNamed( +// bsmMhDesc, +// "name", +// ConstantDescs.CD_String, +// "DUMMY_ARG" +// ) +// ) +// ) +// .areturn() +// ) +// ) +// .withMethod("indy_bsmIndy_condy_bsm", MethodTypeDesc.of(ConstantDescs.CD_Object), +// Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder +// .withCode(codeBuilder -> codeBuilder +// .invokedynamic(DynamicCallSiteDesc.of( +// bsmIndyMhDesc, +// "name", +// MethodTypeDesc.of(ConstantDescs.CD_String), +// DynamicConstantDesc.ofNamed( +// bsmMhDesc, +// "name", +// ConstantDescs.CD_String, +// "DUMMY_ARG" +// ) +// ) +// ) +// .areturn() +// ) +// ) +// .withMethod("indy_bsm_condy_bsm", MethodTypeDesc.of(ConstantDescs.CD_Object), +// Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder +// .withCode(codeBuilder -> codeBuilder +// .invokedynamic(DynamicCallSiteDesc.of( +// bsmMhDesc, +// "name", +// MethodTypeDesc.of(ConstantDescs.CD_String), +// DynamicConstantDesc.ofNamed( +// bsmMhDesc, +// "name", +// ConstantDescs.CD_String, +// "DUMMY_ARG" +// ) +// ) +// ) +// .areturn() +// ) +// ) +// ); // // File f = new File(genClassName + ".class"); // if (f.getParentFile() != null) { @@ -163,15 +245,13 @@ public class CondyNestedTest { // } // new FileOutputStream(f).write(byteArray); // return byteArray; -// // } static void test(Method m, Class<? extends Throwable>... ts) { Throwable caught = null; try { m.invoke(null); - } - catch (Throwable t) { + } catch (Throwable t) { caught = t; } diff --git a/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java b/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java index dc25639e058..2f0208171ae 100644 --- a/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java +++ b/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java @@ -25,19 +25,22 @@ * @test * @bug 8186211 * @summary Test basic invocation of multiple ldc's of the same dynamic constant that fail resolution - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder + * @library /java/lang/invoke/common + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyRepeatFailedResolution * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyRepeatFailedResolution */ -import jdk.experimental.bytecode.BasicClassBuilder; -import jdk.experimental.bytecode.Flag; -import jdk.experimental.bytecode.TypedCodeBuilder; +import jdk.internal.classfile.Classfile; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import java.lang.constant.*; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.InvocationTargetException; @@ -95,124 +98,194 @@ public class CondyRepeatFailedResolution { @BeforeClass public void generateClass() throws Exception { String genClassName = CondyRepeatFailedResolution.class.getSimpleName() + "$Code"; - String bsmClassName = CondyRepeatFailedResolution.class.getCanonicalName().replace('.', '/'); + String bsmClassDesc = CondyRepeatFailedResolution.class.descriptorString(); String bsmMethodName = "intConversion"; String bsmDescriptor = MethodType.methodType(Object.class, MethodHandles.Lookup.class, - String.class, Class.class, int.class).toMethodDescriptorString(); - - byte[] byteArray = new BasicClassBuilder(genClassName, 55, 0) - .withSuperclass("java/lang/Object") - .withMethod("<init>", "()V", M -> - M.withFlags(Flag.ACC_PUBLIC) - .withCode(TypedCodeBuilder::new, C -> - C.aload_0().invokespecial("java/lang/Object", "<init>", "()V", false).return_() - )) - .withMethod("B", "()B", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("B", "B", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Byte.MAX_VALUE)) - .ireturn() - )) - .withMethod("C", "()C", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("C", "C", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Character.MAX_VALUE)) - .ireturn() - )) - .withMethod("D", "()D", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("D", "D", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .dreturn() - )) - .withMethod("D_AsType", "()D", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("I", "D", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .dreturn() - )) - .withMethod("F", "()F", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("F", "F", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .freturn() - )) - .withMethod("F_AsType", "()F", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("I", "F", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .freturn() - )) - .withMethod("I", "()I", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("I", "I", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .ireturn() - )) - .withMethod("J", "()J", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("J", "J", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .lreturn() - )) - .withMethod("J_AsType", "()J", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("I", "J", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .lreturn() - )) - .withMethod("S", "()S", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("S", "S", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Short.MAX_VALUE)) - .ireturn() - )) - .withMethod("Z_F", "()Z", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("Z", "Z", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(0)) - .ireturn() - )) - .withMethod("Z_T", "()Z", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("Z", "Z", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(1)) - .ireturn() - )) - .withMethod("null", "()Ljava/lang/Object;", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("nullRef", "Ljava/lang/Object;", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .areturn() - )) - .withMethod("string", "()Ljava/lang/String;", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("string", "Ljava/lang/String;", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .areturn() - )) - .withMethod("stringArray", "()[Ljava/lang/String;", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("stringArray", "[Ljava/lang/String;", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .areturn() - )) - .build(); + String.class, Class.class, int.class).toMethodDescriptorString(); + DirectMethodHandleDesc bsmMhDesc = MethodHandleDesc.of( + DirectMethodHandleDesc.Kind.STATIC, + ClassDesc.ofDescriptor(bsmClassDesc), + bsmMethodName, + bsmDescriptor + ); + byte[] byteArray = Classfile.of().build(ClassDesc.of(genClassName), classBuilder -> classBuilder + .withVersion(55, 0) + .withSuperclass(ConstantDescs.CD_Object) + .withMethod(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void, Classfile.ACC_PUBLIC, + methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .aload(0) + .invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME, + ConstantDescs.MTD_void, false) + .return_() + ) + ) + .withMethod("B", MethodTypeDesc.of(ConstantDescs.CD_byte), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "B", + ConstantDescs.CD_byte, + (int) Byte.MAX_VALUE)) + .ireturn() + ) + ) + .withMethod("C", MethodTypeDesc.of(ConstantDescs.CD_char), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "C", + ConstantDescs.CD_char, + (int) Character.MAX_VALUE)) + .ireturn() + ) + ) + .withMethod("D", MethodTypeDesc.of(ConstantDescs.CD_double), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "D", + ConstantDescs.CD_double, + Integer.MAX_VALUE)) + .dreturn() + ) + ) + .withMethod("D_AsType", MethodTypeDesc.of(ConstantDescs.CD_double), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "I", + ConstantDescs.CD_double, + Integer.MAX_VALUE)) + .dreturn() + ) + ) + .withMethod("F", MethodTypeDesc.of(ConstantDescs.CD_float), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "F", + ConstantDescs.CD_float, + Integer.MAX_VALUE)) + .freturn() + ) + ) + .withMethod("F_AsType", MethodTypeDesc.of(ConstantDescs.CD_float), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "I", + ConstantDescs.CD_float, + Integer.MAX_VALUE)) + .freturn() + ) + ) + .withMethod("I", MethodTypeDesc.of(ConstantDescs.CD_int), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "I", + ConstantDescs.CD_int, + Integer.MAX_VALUE)) + .ireturn() + ) + ) + .withMethod("J", MethodTypeDesc.of(ConstantDescs.CD_long), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "J", + ConstantDescs.CD_long, + Integer.MAX_VALUE)) + .lreturn() + ) + ) + .withMethod("J_AsType", MethodTypeDesc.of(ConstantDescs.CD_long), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "I", + ConstantDescs.CD_long, + Integer.MAX_VALUE)) + .lreturn() + ) + ) + .withMethod("S", MethodTypeDesc.of(ConstantDescs.CD_short), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "S", + ConstantDescs.CD_short, + ((int) Short.MAX_VALUE))) + .ireturn() + ) + ) + .withMethod("Z_F", MethodTypeDesc.of(ConstantDescs.CD_boolean), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "Z", + ConstantDescs.CD_boolean, + 0)) + .ireturn() + ) + ) + .withMethod("Z_T", MethodTypeDesc.of(ConstantDescs.CD_boolean), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "Z", + ConstantDescs.CD_boolean, + 1)) + .ireturn() + ) + ) + .withMethod("null", MethodTypeDesc.of(ConstantDescs.CD_Object), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "nullRef", + ConstantDescs.CD_Object, + Integer.MAX_VALUE)) + .areturn() + ) + ) + .withMethod("string", MethodTypeDesc.of(ConstantDescs.CD_String), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "string", + ConstantDescs.CD_String, + Integer.MAX_VALUE)) + .areturn() + ) + ) + .withMethod("stringArray", MethodTypeDesc.of(ConstantDescs.CD_String.arrayType()), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "stringArray", + ConstantDescs.CD_String.arrayType(), + Integer.MAX_VALUE)) + .areturn() + ) + ) + ); gc = MethodHandles.lookup().defineClass(byteArray); } diff --git a/test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java b/test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java index b6d343ab8dc..805cbd42fd1 100644 --- a/test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java +++ b/test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java @@ -25,19 +25,21 @@ * @test * @bug 8186046 * @summary Test for condy BSMs returning primitive values or null - * @library /lib/testlibrary/bytecode - * @build jdk.experimental.bytecode.BasicClassBuilder + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyReturnPrimitiveTest * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyReturnPrimitiveTest */ -import jdk.experimental.bytecode.BasicClassBuilder; -import jdk.experimental.bytecode.Flag; -import jdk.experimental.bytecode.TypedCodeBuilder; +import jdk.internal.classfile.Classfile; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import java.lang.constant.*; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Method; @@ -96,124 +98,194 @@ public class CondyReturnPrimitiveTest { @BeforeClass public void generateClass() throws Exception { String genClassName = CondyReturnPrimitiveTest.class.getSimpleName() + "$Code"; - String bsmClassName = CondyReturnPrimitiveTest.class.getCanonicalName().replace('.', '/'); + String bsmClassDesc = CondyReturnPrimitiveTest.class.descriptorString(); String bsmMethodName = "intConversion"; String bsmDescriptor = MethodType.methodType(Object.class, MethodHandles.Lookup.class, - String.class, Class.class, int.class).toMethodDescriptorString(); - - byte[] byteArray = new BasicClassBuilder(genClassName, 55, 0) - .withSuperclass("java/lang/Object") - .withMethod("<init>", "()V", M -> - M.withFlags(Flag.ACC_PUBLIC) - .withCode(TypedCodeBuilder::new, C -> - C.aload_0().invokespecial("java/lang/Object", "<init>", "()V", false).return_() - )) - .withMethod("B", "()B", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("B", "B", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Byte.MAX_VALUE)) - .ireturn() - )) - .withMethod("C", "()C", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("C", "C", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Character.MAX_VALUE)) - .ireturn() - )) - .withMethod("D", "()D", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("D", "D", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .dreturn() - )) - .withMethod("D_AsType", "()D", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("I", "D", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .dreturn() - )) - .withMethod("F", "()F", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("F", "F", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .freturn() - )) - .withMethod("F_AsType", "()F", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("I", "F", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .freturn() - )) - .withMethod("I", "()I", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("I", "I", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .ireturn() - )) - .withMethod("J", "()J", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("J", "J", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .lreturn() - )) - .withMethod("J_AsType", "()J", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("I", "J", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .lreturn() - )) - .withMethod("S", "()S", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("S", "S", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Short.MAX_VALUE)) - .ireturn() - )) - .withMethod("Z_F", "()Z", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("Z", "Z", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(0)) - .ireturn() - )) - .withMethod("Z_T", "()Z", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("Z", "Z", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(1)) - .ireturn() - )) - .withMethod("null", "()Ljava/lang/Object;", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("nullRef", "Ljava/lang/Object;", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .areturn() - )) - .withMethod("string", "()Ljava/lang/String;", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("string", "Ljava/lang/String;", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .areturn() - )) - .withMethod("stringArray", "()[Ljava/lang/String;", M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> - C.ldc("stringArray", "[Ljava/lang/String;", bsmClassName, bsmMethodName, bsmDescriptor, - S -> S.add(Integer.MAX_VALUE)) - .areturn() - )) - .build(); + String.class, Class.class, int.class).toMethodDescriptorString(); + DirectMethodHandleDesc bsmMhDesc = MethodHandleDesc.of( + DirectMethodHandleDesc.Kind.STATIC, + ClassDesc.ofDescriptor(bsmClassDesc), + bsmMethodName, + bsmDescriptor + ); + byte[] byteArray = Classfile.of().build(ClassDesc.of(genClassName), classBuilder -> classBuilder + .withVersion(55, 0) + .withSuperclass(ConstantDescs.CD_Object) + .withMethod(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void, Classfile.ACC_PUBLIC, + methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .aload(0) + .invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME, + ConstantDescs.MTD_void, false) + .return_() + ) + ) + .withMethod("B", MethodTypeDesc.of(ConstantDescs.CD_byte), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "B", + ConstantDescs.CD_byte, + (int) Byte.MAX_VALUE)) + .ireturn() + ) + ) + .withMethod("C", MethodTypeDesc.of(ConstantDescs.CD_char), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "C", + ConstantDescs.CD_char, + (int) Character.MAX_VALUE)) + .ireturn() + ) + ) + .withMethod("D", MethodTypeDesc.of(ConstantDescs.CD_double), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "D", + ConstantDescs.CD_double, + Integer.MAX_VALUE)) + .dreturn() + ) + ) + .withMethod("D_AsType", MethodTypeDesc.of(ConstantDescs.CD_double), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "I", + ConstantDescs.CD_double, + Integer.MAX_VALUE)) + .dreturn() + ) + ) + .withMethod("F", MethodTypeDesc.of(ConstantDescs.CD_float), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "F", + ConstantDescs.CD_float, + Integer.MAX_VALUE)) + .freturn() + ) + ) + .withMethod("F_AsType", MethodTypeDesc.of(ConstantDescs.CD_float), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "I", + ConstantDescs.CD_float, + Integer.MAX_VALUE)) + .freturn() + ) + ) + .withMethod("I", MethodTypeDesc.of(ConstantDescs.CD_int), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "I", + ConstantDescs.CD_int, + Integer.MAX_VALUE)) + .ireturn() + ) + ) + .withMethod("J", MethodTypeDesc.of(ConstantDescs.CD_long), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "J", + ConstantDescs.CD_long, + Integer.MAX_VALUE)) + .lreturn() + ) + ) + .withMethod("J_AsType", MethodTypeDesc.of(ConstantDescs.CD_long), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "I", + ConstantDescs.CD_long, + Integer.MAX_VALUE)) + .lreturn() + ) + ) + .withMethod("S", MethodTypeDesc.of(ConstantDescs.CD_short), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "S", + ConstantDescs.CD_short, + ((int) Short.MAX_VALUE))) + .ireturn() + ) + ) + .withMethod("Z_F", MethodTypeDesc.of(ConstantDescs.CD_boolean), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "Z", + ConstantDescs.CD_boolean, + 0)) + .ireturn() + ) + ) + .withMethod("Z_T", MethodTypeDesc.of(ConstantDescs.CD_boolean), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "Z", + ConstantDescs.CD_boolean, + 1)) + .ireturn() + ) + ) + .withMethod("null", MethodTypeDesc.of(ConstantDescs.CD_Object), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "nullRef", + ConstantDescs.CD_Object, + Integer.MAX_VALUE)) + .areturn() + ) + ) + .withMethod("string", MethodTypeDesc.of(ConstantDescs.CD_String), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "string", + ConstantDescs.CD_String, + Integer.MAX_VALUE)) + .areturn() + ) + ) + .withMethod("stringArray", MethodTypeDesc.of(ConstantDescs.CD_String.arrayType()), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .ldc(DynamicConstantDesc.ofNamed( + bsmMhDesc, + "stringArray", + ConstantDescs.CD_String.arrayType(), + Integer.MAX_VALUE)) + .areturn() + ) + ) + ); gc = MethodHandles.lookup().defineClass(byteArray); } diff --git a/test/jdk/java/lang/invoke/condy/CondyStaticArgumentsTest.java b/test/jdk/java/lang/invoke/condy/CondyStaticArgumentsTest.java index f2f8bcc00f3..96afb2cb377 100644 --- a/test/jdk/java/lang/invoke/condy/CondyStaticArgumentsTest.java +++ b/test/jdk/java/lang/invoke/condy/CondyStaticArgumentsTest.java @@ -25,22 +25,23 @@ * @test * @bug 8186046 * @summary Test bootstrap arguments for condy - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyStaticArgumentsTest * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyStaticArgumentsTest */ -import jdk.experimental.bytecode.PoolHelper; import org.testng.Assert; import org.testng.annotations.Test; import test.java.lang.invoke.lib.InstructionHelper; -import java.lang.invoke.ConstantCallSite; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandleInfo; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; +import java.lang.constant.*; +import java.lang.invoke.*; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.MathContext; @@ -51,6 +52,8 @@ import static java.lang.invoke.MethodType.methodType; public class CondyStaticArgumentsTest { static final MethodHandles.Lookup L = MethodHandles.lookup(); + private static final DirectMethodHandleDesc bigDecimalMhDesc = directMhDesc("bigDecimal"); + private static final DirectMethodHandleDesc mathContextMhDesc = directMhDesc("mathContext"); static class BSMInfo { final String methodName; @@ -65,8 +68,7 @@ public class CondyStaticArgumentsTest { .get(); try { handle = MethodHandles.lookup().unreflect(m); - } - catch (Exception e) { + } catch (Exception e) { throw new Error(e); } descriptor = handle.type().toMethodDescriptorString(); @@ -103,18 +105,18 @@ public class CondyStaticArgumentsTest { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "constant-name", String.class, bi.methodName, bi.handle.type(), - S -> S.add(1).add(2L).add(3.0f).add(4.0d) - .add("java/lang/Number", PoolHelper::putClass) - .add("something", PoolHelper::putString) - .add("(IJFD)V", PoolHelper::putMethodType) - .add(mhi, (P, Z) -> { - return P.putHandle(mhi.getReferenceKind(), "CondyStaticArgumentsTest", mhi.getName(), bi.descriptor); - })); + 1, 2L, 3.0f, 4.0d, + ClassDesc.ofDescriptor(Number.class.descriptorString()), + "something", + MethodTypeDesc.ofDescriptor("(IJFD)V"), + MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.valueOf(mhi.getReferenceKind()), + ClassDesc.ofDescriptor(mhi.getDeclaringClass().descriptorString()), + mhi.getName(), MethodTypeDesc.ofDescriptor(mhi.getMethodType().descriptorString())) + ); Assert.assertEquals(mh.invoke(), "constant-name-String-1-2-3.0-4.0-Number-something-(int,long,float,double)void-11"); } - static MathContext mathContext(MethodHandles.Lookup l, String value, Class<?> type) { switch (value) { case "UNLIMITED": @@ -145,22 +147,6 @@ public class CondyStaticArgumentsTest { .toString(); } - static <E> int bigDecimalPoolHelper(String value, String mc, PoolHelper<String, String, E> P) { - BSMInfo bi = BSMInfo.of("bigDecimal"); - return P.putDynamicConstant("big-decimal", "Ljava/math/BigDecimal;", InstructionHelper.csym(L.lookupClass()), bi.methodName, bi.descriptor, - S -> S.add(value, PoolHelper::putString) - .add(mc, (P2, s) -> { - return mathContextPoolHelper(s, P2); - })); - } - - static <E> int mathContextPoolHelper(String mc, PoolHelper<String, String, E> P) { - BSMInfo bi = BSMInfo.of("mathContext"); - return P.putDynamicConstant(mc, "Ljava/math/MathContext;", InstructionHelper.csym(L.lookupClass()), bi.methodName, bi.descriptor, - S -> { - }); - } - @Test public void testCondyWithCondy() throws Throwable { BSMInfo bi = BSMInfo.of("condyWithCondy"); @@ -168,9 +154,18 @@ public class CondyStaticArgumentsTest { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "big-decimal-math-context", String.class, bi.methodName, bi.handle.type(), - S -> S.add(null, (P, v) -> { - return bigDecimalPoolHelper("3.14159265358979323846", "DECIMAL32", P); - })); + DynamicConstantDesc.ofNamed( + bigDecimalMhDesc, + "big-decimal", + InstructionHelper.classDesc(BigDecimal.class), + "3.14159265358979323846", + DynamicConstantDesc.ofNamed( + mathContextMhDesc, + "DECIMAL32", + InstructionHelper.classDesc(MathContext.class) + ) + ) + ); Assert.assertEquals(mh.invoke(), "big-decimal-math-context-String-3.141593-7"); } @@ -193,9 +188,27 @@ public class CondyStaticArgumentsTest { MethodHandle mh = InstructionHelper.invokedynamic( L, "big-decimal-math-context", methodType(String.class), bi.methodName, bi.handle.type(), - S -> S.add(null, (P, v) -> { - return bigDecimalPoolHelper("3.14159265358979323846", "DECIMAL32", P); - })); + DynamicConstantDesc.ofNamed( + bigDecimalMhDesc, + "big-decimal", + InstructionHelper.classDesc(BigDecimal.class), + "3.14159265358979323846", + DynamicConstantDesc.ofNamed( + mathContextMhDesc, + "DECIMAL32", + InstructionHelper.classDesc(MathContext.class) + ) + )); Assert.assertEquals(mh.invoke(), "big-decimal-math-context-()Ljava/lang/String;-3.141593-7"); } + + private static DirectMethodHandleDesc directMhDesc(String methodName) { + MethodHandleInfo mhi = MethodHandles.lookup().revealDirect(BSMInfo.of(methodName).handle); + return MethodHandleDesc.of( + DirectMethodHandleDesc.Kind.valueOf(mhi.getReferenceKind()), + ClassDesc.ofDescriptor(mhi.getDeclaringClass().descriptorString()), + mhi.getName(), + mhi.getMethodType().descriptorString() + ); + } } diff --git a/test/jdk/java/lang/invoke/condy/CondyTypeValidationTest.java b/test/jdk/java/lang/invoke/condy/CondyTypeValidationTest.java index eebd440c864..e3a1edb725f 100644 --- a/test/jdk/java/lang/invoke/condy/CondyTypeValidationTest.java +++ b/test/jdk/java/lang/invoke/condy/CondyTypeValidationTest.java @@ -25,11 +25,17 @@ * @test * @bug 8186046 * @summary Test invalid name in name and type - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyTypeValidationTest */ +import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import test.java.lang.invoke.lib.InstructionHelper; @@ -49,29 +55,36 @@ public class CondyTypeValidationTest { .toMethodDescriptorString(); @DataProvider - public Object[][] invalidTypesProvider() throws Exception { + public Object[][] invalidTypesProvider() { return Stream.of( // ByteCode API checks for the following invalid types // "", // "[", // "A", // "a", - "L/java/lang/Object", - Stream.generate(() -> "[").limit(256).collect(Collectors.joining("", "", "I"))) - .map(e -> new Object[]{e}).toArray(Object[][]::new); + new Object[]{"L/java/lang/Object", "not a valid reference type descriptor"}, + new Object[]{ + Stream.generate(() -> "[").limit(256) + .collect(Collectors.joining("", "", "I")), + "Cannot create an array type descriptor with more than 255 dimensions" + } + ).toArray(Object[][]::new); } - @Test(dataProvider = "invalidTypesProvider", expectedExceptions = ClassFormatError.class) - public void testInvalidTypes(String type) throws Exception { - MethodHandle mh = InstructionHelper.ldcDynamicConstant( - L, "name", type, - "bsm", BSM_TYPE, - S -> { - }); + @Test(dataProvider = "invalidTypesProvider") + public void testInvalidTypes(String type, String errMessContent) throws Exception { + try { + MethodHandle mh = InstructionHelper.ldcDynamicConstant( + L, "name", type, + "bsm", BSM_TYPE + ); + } catch (IllegalArgumentException e) { + Assert.assertTrue(e.getMessage().contains(errMessContent)); + } } @DataProvider - public Object[][] validTypesProvider() throws Exception { + public Object[][] validTypesProvider() { List<String> t = new ArrayList<>(List.of("B", "C", "D", "F", "I", "J", "Ljava/lang/Object;", "S", "Z")); int l = t.size(); for (int i = 0; i < l; i++) { @@ -86,8 +99,7 @@ public class CondyTypeValidationTest { public void testValidTypes(String type) throws Exception { MethodHandle mh = InstructionHelper.ldcDynamicConstant( L, "name", type, - "bsm", BSM_TYPE, - S -> { - }); + "bsm", BSM_TYPE + ); } } diff --git a/test/jdk/java/lang/invoke/condy/CondyWithGarbageTest.java b/test/jdk/java/lang/invoke/condy/CondyWithGarbageTest.java index 2ea242f45f3..daf1755e15f 100644 --- a/test/jdk/java/lang/invoke/condy/CondyWithGarbageTest.java +++ b/test/jdk/java/lang/invoke/condy/CondyWithGarbageTest.java @@ -25,25 +25,29 @@ * @test * @bug 8186046 * @summary Stress test ldc to ensure HotSpot correctly manages oop maps - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyWithGarbageTest * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyWithGarbageTest */ -import jdk.experimental.bytecode.BasicClassBuilder; -import jdk.experimental.bytecode.Flag; -import jdk.experimental.bytecode.TypedCodeBuilder; +import jdk.internal.classfile.Classfile; +import jdk.internal.classfile.CodeBuilder; import org.testng.Assert; import org.testng.annotations.Test; +import java.lang.constant.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import static java.lang.invoke.MethodType.methodType; -import static test.java.lang.invoke.lib.InstructionHelper.cref; -import static test.java.lang.invoke.lib.InstructionHelper.csym; +import static test.java.lang.invoke.lib.InstructionHelper.classDesc; public class CondyWithGarbageTest { static final MethodHandles.Lookup L = MethodHandles.lookup(); @@ -65,46 +69,65 @@ public class CondyWithGarbageTest { } static MethodHandle lcdStringBasher() throws Exception { - byte[] byteArray = new BasicClassBuilder(csym(L.lookupClass()) + "$Code$String", 55, 0) - .withSuperclass("java/lang/Object") - .withMethod("<init>", "()V", M -> - M.withFlags(Flag.ACC_PUBLIC) - .withCode(TypedCodeBuilder::new, C -> - C.aload_0().invokespecial("java/lang/Object", "<init>", "()V", false).return_() - )) - .withMethod("m", "()" + cref(String.class), M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> { - C.new_(csym(StringBuilder.class)) - .dup() - .invokespecial(csym(StringBuilder.class), "<init>", "()V", false) - .astore_0(); + ClassDesc cd = classDesc(L.lookupClass(), "$Code$String"); + byte[] bytes = Classfile.of().build(cd, classBuilder -> classBuilder + .withVersion(55, 0) + .withSuperclass(ConstantDescs.CD_Object) + .withMethod(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void, Classfile.ACC_PUBLIC, + methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .aload(0) + .invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME, + ConstantDescs.MTD_void, false) + .return_())) + .withMethod("m", MethodTypeDesc.of(ConstantDescs.CD_String), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> { + codeBuilder + .new_(classDesc(StringBuilder.class)) + .dup() + .invokespecial(classDesc(StringBuilder.class), ConstantDescs.INIT_NAME, + ConstantDescs.MTD_void, false) + .astore(0); - for (int i = 10; i < 100; i++) { - ldcString(C, Integer.toString(i)); - C.astore_1().aload_0().aload_1(); - C.invokevirtual(csym(StringBuilder.class), "append", methodType(StringBuilder.class, String.class).toMethodDescriptorString(), false); - C.pop(); - } + for (int i = 10; i < 100; i++) { + ldcString(codeBuilder, Integer.toString(i)); + codeBuilder + .astore(1) + .aload(0) + .aload(1) + .invokevirtual( + classDesc(StringBuilder.class), + "append", + MethodTypeDesc.of( + classDesc(StringBuilder.class), + classDesc(String.class))) + .pop(); + } - C.aload_0(); - C.invokevirtual(csym(StringBuilder.class), "toString", methodType(String.class).toMethodDescriptorString(), false); - C.areturn(); - } - )) - .build(); - - Class<?> gc = L.defineClass(byteArray); + codeBuilder + .aload(0) + .invokevirtual( + classDesc(StringBuilder.class), + "toString", + MethodTypeDesc.of(classDesc(String.class))) + .areturn(); + } + ))); + Class<?> gc = L.defineClass(bytes); return L.findStatic(gc, "m", methodType(String.class)); } - static void ldcString(TypedCodeBuilder<String, String, byte[], ?> C, String name) { - C.ldc(name, cref(String.class), - csym(L.lookupClass()), - "bsmString", - methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class).toMethodDescriptorString(), - S -> { - }); + private static void ldcString(CodeBuilder codeBuilder, String name) { + codeBuilder.ldc(DynamicConstantDesc.ofNamed( + MethodHandleDesc.of( + DirectMethodHandleDesc.Kind.STATIC, + classDesc(L.lookupClass()), + "bsmString", + methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class).toMethodDescriptorString()), + name, + classDesc(String.class) + )); } @@ -125,46 +148,67 @@ public class CondyWithGarbageTest { } static MethodHandle lcdStringArrayBasher() throws Exception { - byte[] byteArray = new BasicClassBuilder(csym(L.lookupClass()) + "$Code$StringArray", 55, 0) - .withSuperclass("java/lang/Object") - .withMethod("<init>", "()V", M -> - M.withFlags(Flag.ACC_PUBLIC) - .withCode(TypedCodeBuilder::new, C -> - C.aload_0().invokespecial("java/lang/Object", "<init>", "()V", false).return_() - )) - .withMethod("m", "()" + cref(String.class), M -> - M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) - .withCode(TypedCodeBuilder::new, C -> { - C.new_(csym(StringBuilder.class)) - .dup() - .invokespecial(csym(StringBuilder.class), "<init>", "()V", false) - .astore_0(); + ClassDesc cd = classDesc(L.lookupClass(), "$Code$StringArray"); + byte[] bytes = Classfile.of().build(cd, classBuilder -> classBuilder + .withVersion(55, 0) + .withSuperclass(ConstantDescs.CD_Object) + .withMethod(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void, Classfile.ACC_PUBLIC, + methodBuilder -> methodBuilder + .withCode(codeBuilder -> codeBuilder + .aload(0) + .invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME, + ConstantDescs.MTD_void, false) + .return_())) + .withMethod("m", MethodTypeDesc.of(classDesc(String.class)), + Classfile.ACC_PUBLIC + Classfile.ACC_STATIC, methodBuilder -> methodBuilder + .withCode(codeBuilder -> { + codeBuilder + .new_(classDesc(StringBuilder.class)) + .dup() + .invokespecial(classDesc(StringBuilder.class), + ConstantDescs.INIT_NAME, ConstantDescs.MTD_void, false) + .astore(0); - for (int i = 10; i < 100; i++) { - ldcStringArray(C, Integer.toString(i)); - C.bipush(0).aaload().astore_1(); - C.aload_0().aload_1(); - C.invokevirtual(csym(StringBuilder.class), "append", methodType(StringBuilder.class, String.class).toMethodDescriptorString(), false); - C.pop(); - } + for (int i = 10; i < 100; i++) { + ldcStringArray(codeBuilder, Integer.toString(i)); + codeBuilder + .bipush(0) + .aaload() + .astore(1) + .aload(0) + .aload(1) + .invokevirtual( + classDesc(StringBuilder.class), + "append", + MethodTypeDesc.of( + classDesc(StringBuilder.class), + classDesc(String.class))) + .pop(); + } - C.aload_0(); - C.invokevirtual(csym(StringBuilder.class), "toString", methodType(String.class).toMethodDescriptorString(), false); - C.areturn(); - } - )) - .build(); - - Class<?> gc = L.defineClass(byteArray); + codeBuilder + .aload(0) + .invokevirtual( + classDesc(StringBuilder.class), + "toString", + MethodTypeDesc.of(classDesc(String.class))) + .areturn(); + } + ))); + Class<?> gc = L.defineClass(bytes); return L.findStatic(gc, "m", methodType(String.class)); } - static void ldcStringArray(TypedCodeBuilder<String, String, byte[], ?> C, String name) { - C.ldc(name, cref(String[].class), - csym(L.lookupClass()), - "bsmStringArray", - methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class).toMethodDescriptorString(), - S -> { - }); + static void ldcStringArray(CodeBuilder codeBuilder, String name) { + codeBuilder.ldc(DynamicConstantDesc.ofNamed( + MethodHandleDesc.of( + DirectMethodHandleDesc.Kind.STATIC, + classDesc(L.lookupClass()), + "bsmStringArray", + methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class).toMethodDescriptorString() + ), + name, + classDesc(String[].class) + )); } } diff --git a/test/jdk/java/lang/invoke/condy/CondyWrongType.java b/test/jdk/java/lang/invoke/condy/CondyWrongType.java index 0966ab86599..db4024c63a2 100644 --- a/test/jdk/java/lang/invoke/condy/CondyWrongType.java +++ b/test/jdk/java/lang/invoke/condy/CondyWrongType.java @@ -25,8 +25,13 @@ * @test * @bug 8186046 * @summary Test bootstrap methods returning the wrong type - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng CondyWrongType * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyWrongType */ @@ -60,7 +65,7 @@ public class CondyWrongType { "J", long.class, "S", short.class, "Z", boolean.class - ); + ); List<Object[]> cases = new ArrayList<>(); for (String name : typeMap.keySet()) { @@ -71,11 +76,10 @@ public class CondyWrongType { boolean pass = true; try { zero.asType(MethodType.methodType(typeMap.get(type))); - } - catch (WrongMethodTypeException e) { + } catch (WrongMethodTypeException e) { pass = false; } - cases.add(new Object[] { name, type, pass}); + cases.add(new Object[]{name, type, pass}); } } @@ -110,20 +114,17 @@ public class CondyWrongType { Throwable caught = null; try { mh.invoke(); - } - catch (Throwable t) { + } catch (Throwable t) { caught = t; } if (caught == null) { if (pass) { return; - } - else { + } else { Assert.fail("Throwable expected"); } - } - else if (pass) { + } else if (pass) { Assert.fail("Throwable not expected"); } @@ -165,8 +166,8 @@ public class CondyWrongType { return InstructionHelper.ldcDynamicConstant( MethodHandles.lookup(), name, type, - "bsm", methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class).toMethodDescriptorString(), - S -> { }); + "bsm", + methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class).descriptorString()); } catch (Exception e) { throw new Error(e); } diff --git a/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java b/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java index 91880c18ed5..bda6251900a 100644 --- a/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java +++ b/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java @@ -25,23 +25,24 @@ * @test * @bug 8186046 8195694 * @summary Test dynamic constant bootstraps - * @library /lib/testlibrary/bytecode /java/lang/invoke/common - * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper + * @library /java/lang/invoke/common + * @build test.java.lang.invoke.lib.InstructionHelper + * @modules java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.constantpool + * java.base/jdk.internal.classfile.instruction + * java.base/jdk.internal.classfile.components * @run testng ConstantBootstrapsTest * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 ConstantBootstrapsTest */ -import jdk.experimental.bytecode.PoolHelper; import org.testng.annotations.Test; import test.java.lang.invoke.lib.InstructionHelper; -import java.lang.invoke.ConstantBootstraps; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandleInfo; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.invoke.VarHandle; -import java.lang.invoke.WrongMethodTypeException; +import java.lang.constant.ConstantDescs; +import java.lang.constant.DirectMethodHandleDesc; +import java.lang.constant.MethodHandleDesc; +import java.lang.invoke.*; import java.math.BigInteger; import java.util.Collection; import java.util.List; @@ -61,13 +62,11 @@ public class ConstantBootstrapsTest { public void testNullConstant() throws Throwable { var handle = InstructionHelper.ldcDynamicConstant(L, "_", Object.class, - ConstantBootstraps.class, "nullConstant", lookupMT(Object.class), - S -> {}); + ConstantBootstraps.class, "nullConstant", lookupMT(Object.class)); assertNull(handle.invoke()); handle = InstructionHelper.ldcDynamicConstant(L, "_", MethodType.class, - ConstantBootstraps.class, "nullConstant", lookupMT(Object.class), - S -> {}); + ConstantBootstraps.class, "nullConstant", lookupMT(Object.class)); assertNull(handle.invoke()); } @@ -92,8 +91,7 @@ public class ConstantBootstrapsTest { for (var desc : pm.keySet()) { var handle = InstructionHelper.ldcDynamicConstant(L, desc, Class.class, - ConstantBootstraps.class, "primitiveClass", lookupMT(Class.class), - S -> {}); + ConstantBootstraps.class, "primitiveClass", lookupMT(Class.class)); assertEquals(handle.invoke(), pm.get(desc)); } } @@ -127,8 +125,7 @@ public class ConstantBootstrapsTest { public void testEnumConstant() throws Throwable { for (var v : StackWalker.Option.values()) { var handle = InstructionHelper.ldcDynamicConstant(L, v.name(), StackWalker.Option.class, - ConstantBootstraps.class, "enumConstant", lookupMT(Enum.class), - S -> { }); + ConstantBootstraps.class, "enumConstant", lookupMT(Enum.class)); assertEquals(handle.invoke(), v); } } @@ -141,21 +138,19 @@ public class ConstantBootstrapsTest { public void testGetStaticDecl() throws Throwable { var handle = InstructionHelper.ldcDynamicConstant(L, "TYPE", Class.class, - ConstantBootstraps.class, "getStaticFinal", lookupMT(Object.class, Class.class), - S -> { S.add("java/lang/Integer", PoolHelper::putClass); }); + ConstantBootstraps.class, "getStaticFinal", lookupMT(Object.class, Class.class), + InstructionHelper.classDesc(Integer.class)); assertEquals(handle.invoke(), int.class); } public void testGetStaticSelf() throws Throwable { var handle = InstructionHelper.ldcDynamicConstant(L, "MAX_VALUE", int.class, - ConstantBootstraps.class, "getStaticFinal", lookupMT(Object.class), - S -> { }); + ConstantBootstraps.class, "getStaticFinal", lookupMT(Object.class)); assertEquals(handle.invoke(), Integer.MAX_VALUE); handle = InstructionHelper.ldcDynamicConstant(L, "ZERO", BigInteger.class, - ConstantBootstraps.class, "getStaticFinal", lookupMT(Object.class), - S -> { }); + ConstantBootstraps.class, "getStaticFinal", lookupMT(Object.class)); assertEquals(handle.invoke(), BigInteger.ZERO); } @@ -164,14 +159,10 @@ public class ConstantBootstrapsTest { var handle = InstructionHelper.ldcDynamicConstant( L, "_", List.class, ConstantBootstraps.class, "invoke", lookupMT(Object.class, MethodHandle.class, Object[].class), - S -> { - S.add("", (P, Z) -> { - return P.putHandle(MethodHandleInfo.REF_invokeStatic, "java/util/List", "of", - MethodType.methodType(List.class, Object[].class).toMethodDescriptorString(), - true); - }); - S.add(1).add(2).add(3).add(4); - }); + MethodHandleDesc.of(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, ConstantDescs.CD_List, "of", + MethodType.methodType(List.class, Object[].class).toMethodDescriptorString()), + 1, 2, 3, 4 + ); assertEquals(handle.invoke(), List.of(1, 2, 3, 4)); } @@ -179,14 +170,10 @@ public class ConstantBootstrapsTest { var handle = InstructionHelper.ldcDynamicConstant( L, "_", int.class, ConstantBootstraps.class, "invoke", lookupMT(Object.class, MethodHandle.class, Object[].class), - S -> { - S.add("", (P, Z) -> { - return P.putHandle(MethodHandleInfo.REF_invokeStatic, "java/lang/Integer", "valueOf", - MethodType.methodType(Integer.class, String.class).toMethodDescriptorString(), - false); - }); - S.add("42"); - }); + MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, ConstantDescs.CD_Integer, "valueOf", + MethodType.methodType(Integer.class, String.class).toMethodDescriptorString()), + "42" + ); assertEquals(handle.invoke(), 42); } @@ -195,29 +182,25 @@ public class ConstantBootstrapsTest { var handle = InstructionHelper.ldcDynamicConstant( L, "_", Collection.class, ConstantBootstraps.class, "invoke", lookupMT(Object.class, MethodHandle.class, Object[].class), - S -> { - S.add("", (P, Z) -> { - return P.putHandle(MethodHandleInfo.REF_invokeStatic, "java/util/List", "of", - MethodType.methodType(List.class, Object[].class).toMethodDescriptorString(), - true); - }); - S.add(1).add(2).add(3).add(4); - }); + MethodHandleDesc.of(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, ConstantDescs.CD_List, "of", + MethodType.methodType(List.class, Object[].class).toMethodDescriptorString()), + 1, 2, 3, 4 + ); assertEquals(handle.invoke(), List.of(1, 2, 3, 4)); } @Test(expectedExceptions = ClassCastException.class) public void testInvokeAsTypeClassCast() throws Throwable { ConstantBootstraps.invoke(MethodHandles.lookup(), "_", String.class, - MethodHandles.lookup().findStatic(Integer.class, "valueOf", MethodType.methodType(Integer.class, String.class)), - "42"); + MethodHandles.lookup().findStatic(Integer.class, "valueOf", MethodType.methodType(Integer.class, String.class)), + "42"); } @Test(expectedExceptions = WrongMethodTypeException.class) public void testInvokeAsTypeWrongReturnType() throws Throwable { ConstantBootstraps.invoke(MethodHandles.lookup(), "_", short.class, - MethodHandles.lookup().findStatic(Integer.class, "parseInt", MethodType.methodType(int.class, String.class)), - "42"); + MethodHandles.lookup().findStatic(Integer.class, "parseInt", MethodType.methodType(int.class, String.class)), + "42"); } @@ -230,10 +213,9 @@ public class ConstantBootstrapsTest { var handle = InstructionHelper.ldcDynamicConstant( L, "f", VarHandle.class, ConstantBootstraps.class, "fieldVarHandle", lookupMT(VarHandle.class, Class.class, Class.class), - S -> { - S.add(X.class.getName().replace('.', '/'), PoolHelper::putClass). - add("java/lang/String", PoolHelper::putClass); - }); + InstructionHelper.classDesc(X.class), + InstructionHelper.classDesc(String.class) + ); var vhandle = (VarHandle) handle.invoke(); assertEquals(vhandle.varType(), String.class); @@ -244,10 +226,9 @@ public class ConstantBootstrapsTest { var handle = InstructionHelper.ldcDynamicConstant( L, "sf", VarHandle.class, ConstantBootstraps.class, "staticFieldVarHandle", lookupMT(VarHandle.class, Class.class, Class.class), - S -> { - S.add(X.class.getName().replace('.', '/'), PoolHelper::putClass). - add("java/lang/String", PoolHelper::putClass); - }); + InstructionHelper.classDesc(X.class), + InstructionHelper.classDesc(String.class) + ); var vhandle = (VarHandle) handle.invoke(); assertEquals(vhandle.varType(), String.class); @@ -258,9 +239,8 @@ public class ConstantBootstrapsTest { var handle = InstructionHelper.ldcDynamicConstant( L, "_", VarHandle.class, ConstantBootstraps.class, "arrayVarHandle", lookupMT(VarHandle.class, Class.class), - S -> { - S.add(String[].class.getName().replace('.', '/'), PoolHelper::putClass); - }); + InstructionHelper.classDesc(String[].class) + ); var vhandle = (VarHandle) handle.invoke(); assertEquals(vhandle.varType(), String.class); diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/AbstractBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/AbstractBuilder.java deleted file mode 100644 index 4e793ef8694..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/AbstractBuilder.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -/** - * Base builder. - * - * @param <S> the type of the symbol representation - * @param <T> the type of type descriptors representation - * @param <E> the type of pool entries - * @param <D> the type of this builder - */ -public class AbstractBuilder<S, T, E, D extends AbstractBuilder<S, T, E, D>> { - /** - * The helper to build the constant pool. - */ - protected final PoolHelper<S, T, E> poolHelper; - - /** - * The helper to use to manipulate type descriptors. - */ - protected final TypeHelper<S, T> typeHelper; - - /** - * Create a builder. - * - * @param poolHelper the helper to build the constant pool - * @param typeHelper the helper to use to manipulate type descriptors - */ - AbstractBuilder(PoolHelper<S, T, E> poolHelper, TypeHelper<S, T> typeHelper) { - this.poolHelper = poolHelper; - this.typeHelper = typeHelper; - } - - @SuppressWarnings("unchecked") - D thisBuilder() { - return (D) this; - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/AnnotationsBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/AnnotationsBuilder.java deleted file mode 100644 index 38b5a828dad..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/AnnotationsBuilder.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.function.Consumer; -import java.util.function.ToIntBiFunction; - -public class AnnotationsBuilder<S, T, E> extends AbstractBuilder<S, T, E, AnnotationsBuilder<S, T, E>> { - - GrowableByteBuffer annoAttribute; - int nannos; - - AnnotationsBuilder(PoolHelper<S, T, E> poolHelper, TypeHelper<S, T> typeHelper) { - super(poolHelper, typeHelper); - this.annoAttribute = new GrowableByteBuffer(); - annoAttribute.writeChar(0); - } - - public enum Kind { - RUNTIME_VISIBLE, - RUNTIME_INVISIBLE; - } - - enum Tag { - B('B'), - C('C'), - D('D'), - F('F'), - I('I'), - J('J'), - S('S'), - Z('Z'), - STRING('s'), - ENUM('e'), - CLASS('c'), - ANNO('@'), - ARRAY('['); - - char tagChar; - - Tag(char tagChar) { - this.tagChar = tagChar; - } - } - - AnnotationsBuilder<S, T, E> withAnnotation(T annoType, Consumer<? super AnnotationElementBuilder> annotationBuilder) { - annoAttribute.writeChar(poolHelper.putType(annoType)); - int offset = annoAttribute.offset; - annoAttribute.writeChar(0); - if (annotationBuilder != null) { - AnnotationElementBuilder _builder = new AnnotationElementBuilder(); - int nelems = _builder.withElements(annotationBuilder); - patchCharAt(offset, nelems); - } - nannos++; - return this; - } - - byte[] build() { - patchCharAt(0, nannos); - return annoAttribute.bytes(); - } - - private void patchCharAt(int offset, int newChar) { - int prevOffset = annoAttribute.offset; - try { - annoAttribute.offset = offset; - annoAttribute.writeChar(newChar); - } finally { - annoAttribute.offset = prevOffset; - } - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - static Consumer NO_BUILDER = - new Consumer() { - @Override - public void accept(Object o) { - //do nothing - } - }; - - public class AnnotationElementBuilder { - - int nelems; - - public AnnotationElementBuilder withString(String name, String s) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writeStringValue(s); - return this; - } - - private void writeStringValue(String s) { - annoAttribute.writeByte(Tag.STRING.tagChar); - annoAttribute.writeChar(poolHelper.putUtf8(s)); - nelems++; - } - - public AnnotationElementBuilder withClass(String name, T s) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writeClassValue(s); - return this; - } - - private void writeClassValue(T s) { - annoAttribute.writeByte(Tag.CLASS.tagChar); - annoAttribute.writeChar(poolHelper.putType(s)); - nelems++; - } - - public AnnotationElementBuilder withEnum(String name, T enumType, int constant) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writeEnumValue(enumType, constant); - return this; - } - - private void writeEnumValue(T enumType, int constant) { - annoAttribute.writeByte(Tag.ENUM.tagChar); - annoAttribute.writeChar(poolHelper.putType(enumType)); - annoAttribute.writeChar(constant); - nelems++; - } - - public AnnotationElementBuilder withAnnotation(String name, T annoType, Consumer<? super AnnotationElementBuilder> annotationBuilder) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writeAnnotationValue(annoType, annotationBuilder); - return this; - } - - private void writeAnnotationValue(T annoType, Consumer<? super AnnotationElementBuilder> annotationBuilder) { - annoAttribute.writeByte(Tag.ANNO.tagChar); - annoAttribute.writeChar(poolHelper.putType(annoType)); - int offset = annoAttribute.offset; - annoAttribute.writeChar(0); - int nelems = withNestedElements(annotationBuilder); - patchCharAt(offset, nelems); - this.nelems++; - } - - public AnnotationElementBuilder withPrimitive(String name, char c) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writePrimitiveValue(Tag.C, (int)c, PoolHelper::putInt); - return this; - } - - public AnnotationElementBuilder withPrimitive(String name, short s) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writePrimitiveValue(Tag.S, (int)s, PoolHelper::putInt); - return this; - } - - public AnnotationElementBuilder withPrimitive(String name, byte b) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writePrimitiveValue(Tag.B, (int)b, PoolHelper::putInt); - return this; - } - - public AnnotationElementBuilder withPrimitive(String name, int i) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writePrimitiveValue(Tag.I, i, PoolHelper::putInt); - return this; - } - - public AnnotationElementBuilder withPrimitive(String name, float f) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writePrimitiveValue(Tag.F, f, PoolHelper::putFloat); - return this; - } - - public AnnotationElementBuilder withPrimitive(String name, long l) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writePrimitiveValue(Tag.J, l, PoolHelper::putLong); - return this; - } - - public AnnotationElementBuilder withPrimitive(String name, double d) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writePrimitiveValue(Tag.D, d, PoolHelper::putDouble); - return this; - } - - public AnnotationElementBuilder withPrimitive(String name, boolean b) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - writePrimitiveValue(Tag.Z, b ? 1 : 0, PoolHelper::putInt); - return this; - } - - private <Z> void writePrimitiveValue(Tag tag, Z value, ToIntBiFunction<PoolHelper<S, T, E>, Z> poolFunc) { - annoAttribute.writeByte(tag.tagChar); - annoAttribute.writeChar(poolFunc.applyAsInt(poolHelper, value)); - nelems++; - } - - AnnotationElementBuilder withStrings(String name, String... ss) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(ss.length); - for (String s : ss) { - writeStringValue(s); - } - return this; - } - - @SuppressWarnings("unchecked") - AnnotationElementBuilder withClasses(String name, T... cc) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(cc.length); - for (T c : cc) { - writeClassValue(c); - } - return this; - } - - AnnotationElementBuilder withEnums(String name, T enumType, int... constants) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(constants.length); - for (int c : constants) { - writeEnumValue(enumType, c); - } - return this; - } - - @SuppressWarnings("unchecked") - public AnnotationElementBuilder withAnnotations(String name, T annoType, Consumer<? super AnnotationElementBuilder>... annotationBuilders) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(annotationBuilders.length); - for (Consumer<? super AnnotationElementBuilder> annotationBuilder : annotationBuilders) { - writeAnnotationValue(annoType, annotationBuilder); - } - return this; - } - - public AnnotationElementBuilder withPrimitives(String name, char... cc) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(cc.length); - for (char c : cc) { - writePrimitiveValue(Tag.C, (int)c, PoolHelper::putInt); - } - return this; - } - - public AnnotationElementBuilder withPrimitives(String name, short... ss) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(ss.length); - for (short s : ss) { - writePrimitiveValue(Tag.S, (int)s, PoolHelper::putInt); - } - return this; - } - - public AnnotationElementBuilder withPrimitives(String name, byte... bb) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(bb.length); - for (byte b : bb) { - writePrimitiveValue(Tag.B, (int)b, PoolHelper::putInt); - } - return this; - } - - public AnnotationElementBuilder withPrimitives(String name, int... ii) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(ii.length); - for (int i : ii) { - writePrimitiveValue(Tag.I, i, PoolHelper::putInt); - } - return this; - } - - public AnnotationElementBuilder withPrimitives(String name, float... ff) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(ff.length); - for (float f : ff) { - writePrimitiveValue(Tag.F, f, PoolHelper::putFloat); - } - return this; - } - - public AnnotationElementBuilder withPrimitives(String name, long... ll) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(ll.length); - for (long l : ll) { - writePrimitiveValue(Tag.J, l, PoolHelper::putLong); - } - return this; - } - - public AnnotationElementBuilder withPrimitives(String name, double... dd) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(dd.length); - for (double d : dd) { - writePrimitiveValue(Tag.D, d, PoolHelper::putDouble); - } - return this; - } - - public AnnotationElementBuilder withPrimitives(String name, boolean... bb) { - annoAttribute.writeChar(poolHelper.putUtf8(name)); - annoAttribute.writeChar(bb.length); - for (boolean b : bb) { - writePrimitiveValue(Tag.Z, b ? 1 : 0, PoolHelper::putInt); - } - return this; - } - - int withNestedElements(Consumer<? super AnnotationElementBuilder> annotationBuilder) { - return withElements(new AnnotationElementBuilder(), annotationBuilder); - } - - int withElements(Consumer<? super AnnotationElementBuilder> annotationBuilder) { - return withElements(this, annotationBuilder); - } - - private int withElements(AnnotationElementBuilder builder, Consumer<? super AnnotationElementBuilder> annotationBuilder) { - annotationBuilder.accept(builder); - return builder.nelems; - } - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/AttributeBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/AttributeBuilder.java deleted file mode 100644 index 80f6bfc8ed0..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/AttributeBuilder.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -/** - * Base builder for attribute containing class file entities. - * - * @param <S> the type of the symbol representation - * @param <T> the type of type descriptors representation - * @param <E> the type of pool entries - * @param <D> the type of this builder - */ - public class AttributeBuilder<S, T, E, D extends AttributeBuilder<S, T, E, D>> - extends AbstractBuilder<S, T, E, D> { - - /** - * The number of attributes. - */ - protected int nattrs; - - /** - * The attributes represented as bytes. - */ - protected GrowableByteBuffer attributes = new GrowableByteBuffer(); - - /** - * Create an attribute builder. - * - * @param poolHelper the helper to build the constant pool - * @param typeHelper the helper to use to manipulate type descriptors - */ - public AttributeBuilder(PoolHelper<S, T, E> poolHelper, TypeHelper<S, T> typeHelper) { - super(poolHelper, typeHelper); - } - - /** - * Add a class file Attribute. Defined as: - * <pre> - * {@code attribute_info { - * u2 attribute_name_index; - * u4 attribute_length; - * u1 info[attribute_length]; - * }} - * </pre> - * - * @param name the attribute name - * @param bytes the bytes of the attribute info - * @return this builder, for chained calls - */ - public D withAttribute(CharSequence name, byte[] bytes) { - attributes.writeChar(poolHelper.putUtf8(name)); - attributes.writeInt(bytes.length); - attributes.writeBytes(bytes); - nattrs++; - return thisBuilder(); - } - - /** - * Add a class file Attribute, using a writer. Defined as: - * <pre> - * {@code attribute_info { - * u2 attribute_name_index; - * u4 attribute_length; - * u1 info[attribute_length]; - * }} - * </pre> - * - * @param <Z> the type of the object representing the attribute - * @param name the attribute name - * @param attr the representation of the attribute - * @param attrWriter the writer which transform the attribute representation into bytes - * @return this builder, for chained calls - */ - public <Z> D withAttribute(CharSequence name, Z attr, AttributeWriter<S, T, E, Z> attrWriter) { - attributes.writeChar(poolHelper.putUtf8(name)); - int offset = attributes.offset; - attributes.writeInt(0); - attrWriter.write(attr, poolHelper, attributes); - int len = attributes.offset - offset - 4; - attributes.withOffset(offset, buf -> buf.writeInt(len)); - nattrs++; - return thisBuilder(); - } - - /** - * Writer for transforming attribute representations to bytes - * - * @param <S> the type of symbol representation - * @param <T> the type of type descriptors representation - * @param <E> the type of pool entries - * @param <A> the type of the object representing the attribute - */ - public interface AttributeWriter<S, T, E, A> { - - /** - * Write an attribute representation into a byte buffer. - * - * @param attr the representation of the attribute - * @param poolHelper the constant pool helper - * @param buf the buffer to collect the bytes - */ - void write(A attr, PoolHelper<S, T, E> poolHelper, GrowableByteBuffer buf); - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/BasicClassBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/BasicClassBuilder.java deleted file mode 100644 index 0449628cb61..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/BasicClassBuilder.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -public class BasicClassBuilder extends ClassBuilder<String, String, BasicClassBuilder> { - - public BasicClassBuilder(String thisClass, int majorVersion, int minorVersion) { - this(); - withMinorVersion(minorVersion); - withMajorVersion(majorVersion); - withThisClass(thisClass); - } - - public BasicClassBuilder() { - super(new BytePoolHelper<>(s->s, s->s), new BasicTypeHelper()); - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/BasicTypeHelper.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/BasicTypeHelper.java deleted file mode 100644 index 42d5e6335b2..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/BasicTypeHelper.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.Iterator; - -/** - * Helper to create and manipulate type descriptors, where type descriptors - * are represented as JVM type descriptor strings and symbols are represented - * as name strings - */ -public class BasicTypeHelper implements TypeHelper<String, String> { - - @Override - public String elemtype(String s) { - if (!s.startsWith("[")) { - throw new IllegalStateException(); - } - return s.substring(1); - } - - @Override - public String arrayOf(String s) { - return "[" + s; - } - - @Override - public String type(String s) { - return "L" + s + ";"; - } - - @Override - public TypeTag tag(String s) { - switch (s.charAt(0)) { - case '[': - case 'L': - return TypeTag.A; - case 'B': - case 'C': - case 'Z': - case 'S': - case 'I': - return TypeTag.I; - case 'F': - return TypeTag.F; - case 'J': - return TypeTag.J; - case 'D': - return TypeTag.D; - case 'V': - return TypeTag.V; - case 'Q': - return TypeTag.Q; - default: - throw new IllegalStateException("Bad type: " + s); - } - } - - @Override - public String nullType() { - // Needed in TypedCodeBuilder; ACONST_NULL pushes a 'null' onto the stack, - // and stack maps handle null differently - return "<null>"; - } - - @Override - public String commonSupertype(String t1, String t2) { - if (t1.equals(t2)) { - return t1; - } else { - try { - Class<?> c1 = from(t1); - Class<?> c2 = from(t2); - if (c1.isAssignableFrom(c2)) { - return t1; - } else if (c2.isAssignableFrom(c1)) { - return t2; - } else { - return "Ljava/lang/Object;"; - } - } catch (Exception e) { - return null; - } - } - } - - public Class<?> from(String desc) throws ReflectiveOperationException { - if (desc.startsWith("[")) { - return Class.forName(desc.replaceAll("/", ".")); - } else { - return Class.forName(symbol(desc).replaceAll("/", ".")); - } - } - - @Override - public Iterator<String> parameterTypes(String s) { - //TODO: gracefully non-method types - return new Iterator<String>() { - int ch = 1; - - @Override - public boolean hasNext() { - return s.charAt(ch) != ')'; - } - - @Override - public String next() { - char curr = s.charAt(ch); - switch (curr) { - case 'C': - case 'B': - case 'S': - case 'I': - case 'J': - case 'F': - case 'D': - case 'Z': - ch++; - return String.valueOf(curr); - case '[': - ch++; - return "[" + next(); - case 'L': - case 'Q': - StringBuilder builder = new StringBuilder(); - while (curr != ';') { - builder.append(curr); - curr = s.charAt(++ch); - } - builder.append(';'); - ch++; - return builder.toString(); - default: - throw new AssertionError("cannot parse string: " + s); - } - } - }; - } - - @Override - public String symbolFrom(String s) { - return s; - } - - @Override - public String fromTag(TypeTag tag) { - return tag.name(); - } - - @Override - public String symbol(String type) { - return (type.startsWith("L") || type.startsWith("Q")) ? type.substring(1, type.length() - 1) : type; - } - - @Override - public String returnType(String s) { - return s.substring(s.indexOf(')') + 1, s.length()); - } - -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/BytePoolHelper.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/BytePoolHelper.java deleted file mode 100644 index 6461cdfb8f1..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/BytePoolHelper.java +++ /dev/null @@ -1,752 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.lang.invoke.MethodHandleInfo; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.ToIntBiFunction; - -/** - * A helper for building and tracking constant pools whose entries are - * represented as byte arrays. - * - * @param <S> the type of the symbol representation - * @param <T> the type of type descriptors representation - */ -public class BytePoolHelper<S, T> implements PoolHelper<S, T, byte[]> { - - GrowableByteBuffer pool = new GrowableByteBuffer(); - GrowableByteBuffer bsm_attr = new GrowableByteBuffer(); - //Map<PoolKey, PoolKey> indicesMap = new HashMap<>(); - int currentIndex = 1; - int currentBsmIndex = 0; - - KeyMap<PoolKey> entries = new KeyMap<>(); - KeyMap<BsmKey> bootstraps = new KeyMap<>(); - PoolKey key = new PoolKey(); - BsmKey bsmKey = new BsmKey(); - - Function<S, String> symbolToString; - Function<T, String> typeToString; - - public BytePoolHelper(Function<S, String> symbolToString, Function<T, String> typeToString) { - this.symbolToString = symbolToString; - this.typeToString = typeToString; - } - - static class KeyMap<K extends AbstractKey<K>> { - - @SuppressWarnings("unchecked") - K[] table = (K[])new AbstractKey<?>[0x10]; - int nelems; - - public void enter(K e) { - if (nelems * 3 >= (table.length - 1) * 2) - dble(); - int hash = getIndex(e); - K old = table[hash]; - if (old == null) { - nelems++; - } - e.next = old; - table[hash] = e; - } - - protected K lookup(K other) { - K e = table[getIndex(other)]; - while (e != null && !e.equals(other)) - e = e.next; - return e; - } - - /** - * Look for slot in the table. - * We use open addressing with double hashing. - */ - int getIndex(K e) { - int hashMask = table.length - 1; - int h = e.hashCode(); - int i = h & hashMask; - // The expression below is always odd, so it is guaranteed - // to be mutually prime with table.length, a power of 2. - int x = hashMask - ((h + (h >> 16)) << 1); - for (; ; ) { - K e2 = table[i]; - if (e2 == null) - return i; - else if (e.hash == e2.hash) - return i; - i = (i + x) & hashMask; - } - } - - @SuppressWarnings("unchecked") - private void dble() { - K[] oldtable = table; - table = (K[])new AbstractKey<?>[oldtable.length * 2]; - int n = 0; - for (int i = oldtable.length; --i >= 0; ) { - K e = oldtable[i]; - if (e != null) { - table[getIndex(e)] = e; - n++; - } - } - // We don't need to update nelems for shared inherited scopes, - // since that gets handled by leave(). - nelems = n; - } - } - - public static abstract class AbstractKey<K extends AbstractKey<K>> { - int hash; - int index = -1; - K next; - - abstract K dup(); - - public abstract boolean equals(Object o); - - @Override - public int hashCode() { - return hash; - } - - void at(int index) { - this.index = index; - } - } - - public static class PoolKey extends AbstractKey<PoolKey> { - PoolTag tag; - Object o1; - Object o2; - Object o3; - Object o4; - int size = -1; - - void setUtf8(CharSequence s) { - tag = PoolTag.CONSTANT_UTF8; - o1 = s; - size = 1; - hash = tag.tag | (s.hashCode() << 1); - } - - void setClass(String clazz) { - tag = PoolTag.CONSTANT_CLASS; - o1 = clazz; - size = 1; - hash = tag.tag | (clazz.hashCode() << 1); - } - - void setNameAndType(CharSequence name, String type) { - tag = PoolTag.CONSTANT_NAMEANDTYPE; - o1 = name; - o2 = type; - size = 2; - hash = tag.tag | ((name.hashCode() | type.hashCode()) << 1); - } - - void setMemberRef(PoolTag poolTag, String owner, CharSequence name, String type) { - tag = poolTag; - o1 = owner; - o2 = name; - o3 = type; - size = 3; - hash = tag.tag | ((owner.hashCode() | name.hashCode() | type.hashCode()) << 1); - } - - void setInvokeDynamic(int bsmIndex, CharSequence name, String type) { - tag = PoolTag.CONSTANT_INVOKEDYNAMIC; - o1 = bsmIndex; - o2 = name; - o3 = type; - size = 3; - hash = tag.tag | ((bsmIndex | name.hashCode() | type.hashCode()) << 1); - } - - void setDynamicConstant(int bsmIndex, CharSequence name, String type) { - tag = PoolTag.CONSTANT_DYNAMIC; - o1 = bsmIndex; - o2 = name; - o3 = type; - size = 3; - hash = tag.tag | ((bsmIndex | name.hashCode() | type.hashCode()) << 1); - } - - void setString(String s) { - tag = PoolTag.CONSTANT_STRING; - o1 = s; - size = 1; - hash = tag.tag | (s.hashCode() << 1); - } - - void setInteger(Integer i) { - tag = PoolTag.CONSTANT_INTEGER; - o1 = i; - size = 1; - hash = tag.tag | (i.hashCode() << 1); - } - - void setFloat(Float f) { - tag = PoolTag.CONSTANT_FLOAT; - o1 = f; - size = 1; - hash = tag.tag | (f.hashCode() << 1); - } - - void setLong(Long l) { - tag = PoolTag.CONSTANT_LONG; - o1 = l; - size = 1; - hash = tag.tag | (l.hashCode() << 1); - } - - void setDouble(Double d) { - tag = PoolTag.CONSTANT_DOUBLE; - o1 = d; - size = 1; - hash = tag.tag | (d.hashCode() << 1); - } - - void setMethodType(String type) { - tag = PoolTag.CONSTANT_METHODTYPE; - o1 = type; - size = 1; - hash = tag.tag | (type.hashCode() << 1); - } - - void setMethodHandle(int bsmKind, String owner, CharSequence name, String type) { - tag = PoolTag.CONSTANT_METHODHANDLE; - o1 = bsmKind; - o2 = owner; - o3 = name; - o4 = type; - size = 4; - hash = tag.tag | (bsmKind | owner.hashCode() | name.hashCode() | type.hashCode() << 1); - } - - @Override - public boolean equals(Object obj) { - PoolKey that = (PoolKey) obj; - if (tag != that.tag) return false; - switch (size) { - case 1: - if (!o1.equals(that.o1)) { - return false; - } - break; - case 2: - if (!o2.equals(that.o2) || !o1.equals(that.o1)) { - return false; - } - break; - case 3: - if (!o3.equals(that.o3) || !o2.equals(that.o2) || !o1.equals(that.o1)) { - return false; - } - break; - case 4: - if (!o4.equals(that.o4) || !o3.equals(that.o3) || !o2.equals(that.o2) || !o1.equals(that.o1)) { - return false; - } - break; - } - return true; - } - - PoolKey dup() { - PoolKey poolKey = new PoolKey(); - poolKey.tag = tag; - poolKey.size = size; - poolKey.hash = hash; - poolKey.o1 = o1; - poolKey.o2 = o2; - poolKey.o3 = o3; - poolKey.o4 = o4; - return poolKey; - } - } - - static class BsmKey extends AbstractKey<BsmKey> { - String bsmClass; - CharSequence bsmName; - String bsmType; - List<Integer> bsmArgs; - - void set(String bsmClass, CharSequence bsmName, String bsmType, List<Integer> bsmArgs) { - this.bsmClass = bsmClass; - this.bsmName = bsmName; - this.bsmType = bsmType; - this.bsmArgs = bsmArgs; - hash = bsmClass.hashCode() | bsmName.hashCode() | bsmType.hashCode() | Objects.hash(bsmArgs); - } - - BsmKey dup() { - BsmKey bsmKey = new BsmKey(); - bsmKey.bsmClass = bsmClass; - bsmKey.bsmName = bsmName; - bsmKey.bsmType = bsmType; - bsmKey.bsmArgs = bsmArgs; - bsmKey.hash = hash; - return bsmKey; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof BsmKey) { - BsmKey that = (BsmKey)obj; - return Objects.equals(bsmClass, that.bsmClass) && - Objects.equals(bsmName, that.bsmName) && - Objects.equals(bsmType, that.bsmType) && - Objects.deepEquals(bsmArgs, that.bsmArgs); - } else { - return false; - } - } - } - - @Override - public int putClass(S symbol) { - return putClassInternal(symbolToString.apply(symbol)); - } - - private int putClassInternal(String symbol) { - key.setClass(symbol); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - int utf8_idx = putUtf8(symbol); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_CLASS.tag); - pool.writeChar(utf8_idx); - } - return poolKey.index; - } - - @Override - public int putFieldRef(S owner, CharSequence name, T type) { - return putMemberRef(PoolTag.CONSTANT_FIELDREF, owner, name, type); - } - - @Override - public int putMethodRef(S owner, CharSequence name, T type, boolean isInterface) { - return putMemberRef(isInterface ? PoolTag.CONSTANT_INTERFACEMETHODREF : PoolTag.CONSTANT_METHODREF, - owner, name, type); - } - - int putMemberRef(PoolTag poolTag, S owner, CharSequence name, T type) { - return putMemberRefInternal(poolTag, symbolToString.apply(owner), name, typeToString.apply(type)); - } - - int putMemberRefInternal(PoolTag poolTag, String owner, CharSequence name, String type) { - key.setMemberRef(poolTag, owner, name, type); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - int owner_idx = putClassInternal(owner); - int nameAndType_idx = putNameAndType(name, type); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(poolTag.tag); - pool.writeChar(owner_idx); - pool.writeChar(nameAndType_idx); - } - return poolKey.index; - } - - @Override - public int putInt(int i) { - key.setInteger(i); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_INTEGER.tag); - pool.writeInt(i); - } - return poolKey.index; - } - - @Override - public int putFloat(float f) { - key.setFloat(f); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_FLOAT.tag); - pool.writeFloat(f); - } - return poolKey.index; - } - - @Override - public int putLong(long l) { - key.setLong(l); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_LONG.tag); - pool.writeLong(l); - currentIndex++; - } - return poolKey.index; - } - - @Override - public int putDouble(double d) { - key.setDouble(d); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_DOUBLE.tag); - pool.writeDouble(d); - currentIndex++; - } - return poolKey.index; - } - - - @Override - public int putInvokeDynamic(CharSequence invokedName, T invokedType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, byte[]>> staticArgs) { - return putInvokeDynamicInternal(invokedName, typeToString.apply(invokedType), symbolToString.apply(bsmClass), bsmName, typeToString.apply(bsmType), staticArgs); - } - - @Override - public int putDynamicConstant(CharSequence constName, T constType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, byte[]>> staticArgs) { - return putDynamicConstantInternal(constName, typeToString.apply(constType), symbolToString.apply(bsmClass), bsmName, typeToString.apply(bsmType), staticArgs); - } - - private int putInvokeDynamicInternal(CharSequence invokedName, String invokedType, String bsmClass, CharSequence bsmName, String bsmType, Consumer<StaticArgListBuilder<S, T, byte[]>> staticArgs) { - int bsmIndex = putBsmInternal(bsmClass, bsmName, bsmType, staticArgs); - key.setInvokeDynamic(bsmIndex, invokedName, invokedType); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - int nameAndType_idx = putNameAndType(invokedName, invokedType); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_INVOKEDYNAMIC.tag); - pool.writeChar(bsmIndex); - pool.writeChar(nameAndType_idx); - } - return poolKey.index; - } - - private int putDynamicConstantInternal(CharSequence constName, String constType, String bsmClass, CharSequence bsmName, String bsmType, Consumer<StaticArgListBuilder<S, T, byte[]>> staticArgs) { - int bsmIndex = putBsmInternal(bsmClass, bsmName, bsmType, staticArgs); - key.setDynamicConstant(bsmIndex, constName, constType); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - int nameAndType_idx = putNameAndType(constName, constType); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_DYNAMIC.tag); - pool.writeChar(bsmIndex); - pool.writeChar(nameAndType_idx); - } - return poolKey.index; - } - - private int putBsmInternal(String bsmClass, CharSequence bsmName, String bsmType, Consumer<StaticArgListBuilder<S, T, byte[]>> staticArgs) { - ByteStaticArgListBuilder staticArgsBuilder = new ByteStaticArgListBuilder(); - staticArgs.accept(staticArgsBuilder); - List<Integer> static_idxs = staticArgsBuilder.indexes; - bsmKey.set(bsmClass, bsmName, bsmType, static_idxs); - BsmKey poolKey = bootstraps.lookup(bsmKey); - if (poolKey == null) { - poolKey = bsmKey.dup(); - // TODO the BSM could be a static method on an interface - int bsm_ref = putHandleInternal(MethodHandleInfo.REF_invokeStatic, bsmClass, bsmName, bsmType, false); - poolKey.at(currentBsmIndex++); - bootstraps.enter(poolKey); - bsm_attr.writeChar(bsm_ref); - bsm_attr.writeChar(static_idxs.size()); - for (int i : static_idxs) { - bsm_attr.writeChar(i); - } - } - return poolKey.index; - } - //where - class ByteStaticArgListBuilder implements StaticArgListBuilder<S, T, byte[]> { - - List<Integer> indexes = new ArrayList<>(); - - public ByteStaticArgListBuilder add(int i) { - indexes.add(putInt(i)); - return this; - } - public ByteStaticArgListBuilder add(float f) { - indexes.add(putFloat(f)); - return this; - } - public ByteStaticArgListBuilder add(long l) { - indexes.add(putLong(l)); - return this; - } - public ByteStaticArgListBuilder add(double d) { - indexes.add(putDouble(d)); - return this; - } - public ByteStaticArgListBuilder add(String s) { - indexes.add(putString(s)); - return this; - } - @Override - public StaticArgListBuilder<S, T, byte[]> add(int refKind, S owner, CharSequence name, T type) { - indexes.add(putHandle(refKind, owner, name, type)); - return this; - } - public <Z> ByteStaticArgListBuilder add(Z z, ToIntBiFunction<PoolHelper<S, T, byte[]>, Z> poolFunc) { - indexes.add(poolFunc.applyAsInt(BytePoolHelper.this, z)); - return this; - } - public ByteStaticArgListBuilder add(CharSequence constName, T constType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, byte[]>> staticArgs) { - indexes.add(putDynamicConstant(constName, constType, bsmClass, bsmName, bsmType, staticArgs)); - return this; - } - } - - @Override - public int putMethodType(T s) { - return putMethodTypeInternal(typeToString.apply(s)); - } - - private int putMethodTypeInternal(String s) { - key.setMethodType(s); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - int desc_idx = putUtf8(s); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_METHODTYPE.tag); - pool.writeChar(desc_idx); - } - return poolKey.index; - } - - @Override - public int putHandle(int refKind, S owner, CharSequence name, T type) { - return putHandleInternal(refKind, symbolToString.apply(owner), name, typeToString.apply(type), false); - } - - @Override - public int putHandle(int refKind, S owner, CharSequence name, T type, boolean isInterface) { - return putHandleInternal(refKind, symbolToString.apply(owner), name, typeToString.apply(type), isInterface); - } - - private int putHandleInternal(int refKind, String owner, CharSequence name, String type, boolean isInterface) { - key.setMethodHandle(refKind, owner, name, type); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - int ref_idx = putMemberRefInternal(fromKind(refKind, isInterface), owner, name, type); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_METHODHANDLE.tag); - pool.writeByte(refKind); - pool.writeChar(ref_idx); - } - return poolKey.index; - } - - PoolTag fromKind(int bsmKind, boolean isInterface) { - switch (bsmKind) { - case 1: // REF_getField - case 2: // REF_getStatic - case 3: // REF_putField - case 4: // REF_putStatic - return PoolTag.CONSTANT_FIELDREF; - case 5: // REF_invokeVirtual - case 6: // REF_invokeStatic - case 7: // REF_invokeSpecial - case 8: // REF_newInvokeSpecial - case 9: // REF_invokeInterface - return isInterface ? PoolTag.CONSTANT_INTERFACEMETHODREF : PoolTag.CONSTANT_METHODREF; - default: - throw new IllegalStateException(); - } - } - - @Override - public int putType(T s) { - return putUtf8(typeToString.apply(s)); - } - - public int putUtf8(CharSequence s) { - key.setUtf8(s); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_UTF8.tag); - putUTF8Internal(s); - } - return poolKey.index; - } - - /** - * Puts an UTF8 string into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param s a String whose UTF8 encoded length must be less than 65536. - * @return this byte vector. - */ - void putUTF8Internal(final CharSequence s) { - int charLength = s.length(); - if (charLength > 65535) { - throw new IllegalArgumentException(); - } - // optimistic algorithm: instead of computing the byte length and then - // serializing the string (which requires two loops), we assume the byte - // length is equal to char length (which is the most frequent case), and - // we start serializing the string right away. During the serialization, - // if we find that this assumption is wrong, we continue with the - // general method. - pool.writeChar(charLength); - for (int i = 0; i < charLength; ++i) { - char c = s.charAt(i); - if (c >= '\001' && c <= '\177') { - pool.writeByte((byte) c); - } else { - encodeUTF8(s, i, 65535); - break; - } - } - } - - /** - * Puts an UTF8 string into this byte vector. The byte vector is - * automatically enlarged if necessary. The string length is encoded in two - * bytes before the encoded characters, if there is space for that (i.e. if - * this.length - i - 2 >= 0). - * - * @param s the String to encode. - * @param i the index of the first character to encode. The previous - * characters are supposed to have already been encoded, using - * only one byte per character. - * @param maxByteLength the maximum byte length of the encoded string, including the - * already encoded characters. - * @return this byte vector. - */ - void encodeUTF8(final CharSequence s, int i, int maxByteLength) { - int charLength = s.length(); - int byteLength = i; - char c; - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - byteLength++; - } else if (c > '\u07FF') { - byteLength += 3; - } else { - byteLength += 2; - } - } - if (byteLength > maxByteLength) { - throw new IllegalArgumentException(); - } - int byteLengthFinal = byteLength; - pool.withOffset(pool.offset - i - 2, buf -> buf.writeChar(byteLengthFinal)); - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - pool.writeChar((byte) c); - } else if (c > '\u07FF') { - pool.writeChar((byte) (0xE0 | c >> 12 & 0xF)); - pool.writeChar((byte) (0x80 | c >> 6 & 0x3F)); - pool.writeChar((byte) (0x80 | c & 0x3F)); - } else { - pool.writeChar((byte) (0xC0 | c >> 6 & 0x1F)); - pool.writeChar((byte) (0x80 | c & 0x3F)); - } - } - } - - @Override - public int putString(String s) { - key.setString(s); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - int utf8_index = putUtf8(s); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_STRING.tag); - pool.writeChar(utf8_index); - } - return poolKey.index; - } - - int putNameAndType(CharSequence name, String type) { - key.setNameAndType(name, type); - PoolKey poolKey = entries.lookup(key); - if (poolKey == null) { - poolKey = key.dup(); - int name_idx = putUtf8(name); - int type_idx = putUtf8(type); - poolKey.at(currentIndex++); - entries.enter(poolKey); - pool.writeByte(PoolTag.CONSTANT_NAMEANDTYPE.tag); - pool.writeChar(name_idx); - pool.writeChar(type_idx); - } - return poolKey.index; - } - - @Override - public int size() { - return currentIndex - 1; - } - - @Override - public byte[] entries() { - return pool.bytes(); - } - - <Z extends ClassBuilder<S, T, Z>> void addAttributes(ClassBuilder<S , T, Z> cb) { - if (currentBsmIndex > 0) { - GrowableByteBuffer bsmAttrBuf = new GrowableByteBuffer(); - bsmAttrBuf.writeChar(currentBsmIndex); - bsmAttrBuf.writeBytes(bsm_attr); - cb.withAttribute("BootstrapMethods", bsmAttrBuf.bytes()); - } - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/ClassBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/ClassBuilder.java deleted file mode 100644 index cc1e6579d2c..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/ClassBuilder.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.function.Consumer; - -/** - * Base class builder. The base of higher level class builders. - * - * @param <S> the type of symbol representation - * @param <T> the type of type descriptors representation - * @param <C> the type of this builder - */ -public class ClassBuilder<S, T, C extends ClassBuilder<S, T, C>> - extends DeclBuilder<S, T, byte[], C> { - - /** - * The helper to use to manipulate type descriptors. - */ - protected TypeHelper<S, T> typeHelper; - - /** - * The symbol for the class being built. - */ - protected S thisClass; - - /** - * The super-interfaces of the class being built.. - */ - protected GrowableByteBuffer interfaces = new GrowableByteBuffer(); - - /** - * The fields of the class being built. - */ - protected GrowableByteBuffer fields = new GrowableByteBuffer(); - - /** - * The methods of the class being built. - */ - protected GrowableByteBuffer methods = new GrowableByteBuffer(); - - int majorVersion; - int minorVersion; - int flags; - int superclass; - int nmethods, nfields, ninterfaces; - - /** - * Create a class builder. - * - * @param poolHelper the helper to build the constant pool - * @param typeHelper the helper to use to manipulate type descriptors - */ - public ClassBuilder(BytePoolHelper<S, T> poolHelper, TypeHelper<S, T> typeHelper) { - super(poolHelper, typeHelper); - this.typeHelper = typeHelper; - } - - /** - * Set the minor class file version. - * - * @param minorVersion the minor version number - * @return this builder, for chained calls - */ - public C withMinorVersion(int minorVersion) { - this.minorVersion = minorVersion; - return thisBuilder(); - } - - /** - * Set the major class file version. - * - * @param majorVersion the major version number - * @return this builder, for chained calls - */ - public C withMajorVersion(int majorVersion) { - this.majorVersion = majorVersion; - return thisBuilder(); - } - - /** - * Set the class symbol - * - * @param thisClass the class symbol - * @return this builder, for chained calls - */ - public C withThisClass(S thisClass) { - this.thisClass = thisClass; - return thisBuilder(); - } - - /** - * Set the class access flags - * - * @param flags an array of {@code Flag} - * @return this builder, for chained calls - */ - @Override - public C withFlags(Flag... flags) { - for (Flag f : flags) { - this.flags |= f.flag; - } - return thisBuilder(); - } - - /** - * Set the superclass - * - * @param sup the superclass symbol - * @return this builder, for chained calls - */ - public C withSuperclass(S sup) { - this.superclass = poolHelper.putClass(sup); - return thisBuilder(); - } - - /** - * Add a super interface. - * - * @param sup an interface symbol - * @return this builder, for chained calls - */ - public C withSuperinterface(S sup) { - this.interfaces.writeChar(poolHelper.putClass(sup)); - ninterfaces++; - return thisBuilder(); - } - - /** - * Add a field. - * - * @param name the name of the field - * @param type the type descriptor of the field - * @return this builder, for chained calls - */ - public final C withField(CharSequence name, T type) { - return withField(name, type, FB -> { - }); - } - - /** - * Add a field. - * - * @param name the name of the field - * @param type the type descriptor of the field - * @param fieldConfig access to the {@code FieldBuilder} to allow clients to - * adjust flags, annotations and bytecode attributes on the field declaration - * @return this builder, for chained calls - */ - public C withField(CharSequence name, T type, Consumer<? super FieldBuilder<S, T, byte[]>> fieldConfig) { - FieldBuilder<S, T, byte[]> F = new FieldBuilder<>(name, type, poolHelper, typeHelper); - fieldConfig.accept(F); - F.build(fields); - nfields++; - return thisBuilder(); - } - - /** - * Add a method - * - * @param name the name of the method - * @param type the type descriptor of the method - * @return this builder, for chained calls - */ - public final C withMethod(CharSequence name, T type) { - return withMethod(name, type, MB -> { - }); - } - - /** - * Add a method - * - * @param name the name of the method - * @param type the type descriptor of the method - * @param methodConfig access to the {@code MethodBuilder} to allow clients to - * adjust flags, annotations and bytecode attributes on the method declaration - * @return this builder, for chained calls - */ - public C withMethod(CharSequence name, T type, Consumer<? super MethodBuilder<S, T, byte[]>> methodConfig) { - MethodBuilder<S, T, byte[]> M = new MethodBuilder<>(thisClass, name, type, poolHelper, typeHelper); - methodConfig.accept(M); - M.build(methods); - nmethods++; - return thisBuilder(); - } - - /** - * Build the constant pool into a byte array. - * - * @return a representation of this constant pool as a byte array - */ - @SuppressWarnings("unchecked") - public byte[] build() { - ((BytePoolHelper<S, T>)poolHelper).addAttributes(this); - addAnnotations(); - int thisClassIdx = poolHelper.putClass(thisClass); - byte[] poolBytes = poolHelper.entries(); - GrowableByteBuffer buf = new GrowableByteBuffer(); - buf.writeInt(0xCAFEBABE); - buf.writeChar(minorVersion); - buf.writeChar(majorVersion); - buf.writeChar(poolHelper.size() + 1); - buf.writeBytes(poolBytes); - buf.writeChar(flags); - buf.writeChar(thisClassIdx); - buf.writeChar(superclass); - buf.writeChar(ninterfaces); - if (ninterfaces > 0) { - buf.writeBytes(interfaces); - } - buf.writeChar(nfields); - buf.writeBytes(fields); - buf.writeChar(nmethods); - buf.writeBytes(methods); - buf.writeChar(nattrs); - buf.writeBytes(attributes); - return buf.bytes(); - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/CodeBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/CodeBuilder.java deleted file mode 100644 index d16cd138fff..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/CodeBuilder.java +++ /dev/null @@ -1,1339 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import jdk.experimental.bytecode.PoolHelper.StaticArgListBuilder; - -import java.lang.invoke.MethodHandle; -import java.util.Iterator; -import java.util.List; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.ToIntFunction; - -/** - * Builder for class file code attributes. A code attribute is defined: - * <pre> - * {@code - * Code_attribute { - * u2 attribute_name_index; - * u4 attribute_length; - * u2 max_stack; - * u2 max_locals; - * u4 code_length; - * u1 code[code_length]; - * u2 exception_table_length; - * { u2 start_pc; - * u2 end_pc; - * u2 handler_pc; - * u2 catch_type; - * } exception_table[exception_table_length]; - * u2 attributes_count; - * attribute_info attributes[attributes_count]; - * } } - * </pre> - * - * @param <S> the type of symbol representation - * @param <T> the type of type descriptors representation - * @param <E> the type of pool entries - * @param <C> the type of this code builder - */ -public class CodeBuilder<S, T, E, C extends CodeBuilder<S, T, E, C>> extends AttributeBuilder<S, T, E, C> { - - protected GrowableByteBuffer code = new GrowableByteBuffer(); - GrowableByteBuffer catchers = new GrowableByteBuffer(); - GrowableByteBuffer stackmaps = new GrowableByteBuffer(); - MethodBuilder<S, T, E> methodBuilder; - int ncatchers; - int stacksize = -1; - int localsize = -1; - int nstackmaps = 0; - - public enum JumpMode { - NARROW, - WIDE; - } - - CodeBuilder(MethodBuilder<S, T, E> methodBuilder) { - super(methodBuilder.poolHelper, methodBuilder.typeHelper); - this.methodBuilder = methodBuilder; - } - - public C getstatic(S owner, CharSequence name, T type) { - emitOp(Opcode.GETSTATIC, type); - code.writeChar(poolHelper.putFieldRef(owner, name, type)); - return thisBuilder(); - } - - public C putstatic(S owner, CharSequence name, T type) { - emitOp(Opcode.PUTSTATIC, type); - code.writeChar(poolHelper.putFieldRef(owner, name, type)); - return thisBuilder(); - } - - public C getfield(S owner, CharSequence name, T type) { - emitOp(Opcode.GETFIELD, type); - code.writeChar(poolHelper.putFieldRef(owner, name, type)); - return thisBuilder(); - } - - public C vgetfield(S owner, CharSequence name, T type) { - emitOp(Opcode.VGETFIELD, type); - code.writeChar(poolHelper.putFieldRef(owner, name, type)); - return thisBuilder(); - } - - public C putfield(S owner, CharSequence name, T type) { - emitOp(Opcode.PUTFIELD, type); - code.writeChar(poolHelper.putFieldRef(owner, name, type)); - return thisBuilder(); - } - - public C invokevirtual(S owner, CharSequence name, T type, boolean isInterface) { - emitOp(Opcode.INVOKEVIRTUAL, type); - code.writeChar(poolHelper.putMethodRef(owner, name, type, isInterface)); - return thisBuilder(); - } - - public C invokespecial(S owner, CharSequence name, T type, boolean isInterface) { - emitOp(Opcode.INVOKESPECIAL, type); - code.writeChar(poolHelper.putMethodRef(owner, name, type, isInterface)); - return thisBuilder(); - } - - public C invokestatic(S owner, CharSequence name, T type, boolean isInterface) { - emitOp(Opcode.INVOKESTATIC, type); - code.writeChar(poolHelper.putMethodRef(owner, name, type, isInterface)); - return thisBuilder(); - } - - public C invokeinterface(S owner, CharSequence name, T type) { - emitOp(Opcode.INVOKEINTERFACE, type); - code.writeChar(poolHelper.putMethodRef(owner, name, type, true)); - int nargs = 1; - Iterator<T> it = typeHelper.parameterTypes(type); - while (it.hasNext()) { - nargs += typeHelper.tag(it.next()).width; - } - code.writeByte(nargs); - code.writeByte(0); - return thisBuilder(); - } - - public C invokedynamic(CharSequence invokedName, T invokedType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, E>> staticArgs) { - emitOp(Opcode.INVOKEDYNAMIC, invokedType); - code.writeChar(poolHelper.putInvokeDynamic(invokedName, invokedType, bsmClass, bsmName, bsmType, staticArgs)); - code.writeChar(0); //padding - return thisBuilder(); - } - - public C new_(S clazz) { - emitOp(Opcode.NEW, clazz); - code.writeChar(poolHelper.putClass(clazz)); - return thisBuilder(); - } - - public C vnew_(S clazz, CharSequence name, T desc) { - emitOp(Opcode.VNEW, clazz); - code.writeChar(poolHelper.putMethodRef(clazz, name, desc, false)); - return thisBuilder(); - } - - public C vnewarray(S array) { - emitOp(Opcode.VNEWARRAY, array); - code.writeChar(poolHelper.putClass(array)); - return thisBuilder(); - } - - public C newarray(TypeTag tag) { - emitOp(Opcode.NEWARRAY, tag); - int newarraycode = tag.newarraycode; - if (newarraycode == -1) { - throw new IllegalStateException("Bad tag " + tag); - } - code.writeByte(newarraycode); - return thisBuilder(); - } - - public C anewarray(S array) { - emitOp(Opcode.ANEWARRAY, array); - code.writeChar(poolHelper.putClass(array)); - return thisBuilder(); - } - - public C checkcast(S target) { - emitOp(Opcode.CHECKCAST); - code.writeChar(poolHelper.putClass(target)); - return thisBuilder(); - } - - public C instanceof_(S target) { - emitOp(Opcode.INSTANCEOF); - code.writeChar(poolHelper.putClass(target)); - return thisBuilder(); - } - - public C multianewarray(S array, byte dims) { - emitOp(Opcode.MULTIANEWARRAY, new Object[]{array, dims}); - code.writeChar(poolHelper.putClass(array)).writeByte(dims); - return thisBuilder(); - } - - public C multivnewarray(S array, byte dims) { - emitOp(Opcode.MULTIVNEWARRAY, new Object[]{array, dims}); - code.writeChar(poolHelper.putClass(array)).writeByte(dims); - return thisBuilder(); - } - - public C vbox(S target) { - emitOp(Opcode.VBOX, target); - code.writeChar(poolHelper.putClass(target)); - return thisBuilder(); - } - - public C vunbox(S target) { - emitOp(Opcode.VUNBOX, target); - code.writeChar(poolHelper.putClass(target)); - return thisBuilder(); - } - - public C ldc(int i) { - return ldc(pool -> pool.putInt(i), false); - } - - public C ldc(long l) { - return ldc(pool -> pool.putLong(l), true); - } - - public C ldc(float f) { - return ldc(pool -> pool.putFloat(f), false); - } - - public C ldc(double d) { - return ldc(pool -> pool.putDouble(d), true); - } - - public C ldc(String s) { - return ldc(pool -> pool.putString(s), false); - } - - public C ldc(CharSequence constName, T constType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, E>> staticArgs) { - boolean fat = typeHelper.tag(constType).width() == 2; - return ldc(pool -> pool.putDynamicConstant(constName, constType, bsmClass, bsmName, bsmType, staticArgs), fat); - } - - public <Z> C ldc(Z z, BiFunction<PoolHelper<S, T, E>, Z, Integer> poolFunc) { - return ldc(pool -> poolFunc.apply(pool, z), false); - } - - protected C ldc(ToIntFunction<PoolHelper<S, T, E>> indexFunc, boolean fat) { - // @@@ This should probably be abstract - int index = indexFunc.applyAsInt(poolHelper); - return ldc(index, null, fat); - } - - protected final C ldc(int index, T type, boolean fat) { - if (fat) { - emitOp(Opcode.LDC2_W, type); - code.writeChar(index); - } else if (index > 63) { - emitOp(Opcode.LDC_W, type); - code.writeChar(index); - } else { - emitOp(Opcode.LDC, type); - code.writeByte(index); - } - return thisBuilder(); - } - - //other non-CP dependent opcodes - public C areturn() { - return emitOp(Opcode.ARETURN); - } - - public C ireturn() { - return emitOp(Opcode.IRETURN); - } - - public C freturn() { - return emitOp(Opcode.FRETURN); - } - - public C lreturn() { - return emitOp(Opcode.LRETURN); - } - - public C dreturn() { - return emitOp(Opcode.DRETURN); - } - - public C return_() { - return emitOp(Opcode.RETURN); - } - - public C vreturn() { - return emitOp(Opcode.VRETURN); - } - - protected C emitWideIfNeeded(Opcode opcode, int n) { - boolean wide = n > Byte.MAX_VALUE; - if (wide) { - wide(); - } - emitOp(opcode, n); - if (wide) { - code.writeChar(n); - } else { - code.writeByte(n); - } - return thisBuilder(); - } - - protected C emitWideIfNeeded(Opcode opcode, int n, int v) { - boolean wide = n > Byte.MAX_VALUE || v > Byte.MAX_VALUE; - if (wide) { - wide(); - } - emitOp(opcode, n); - if (wide) { - code.writeChar(n).writeChar(v); - } else { - code.writeByte(n).writeByte(v); - } - return thisBuilder(); - } - - public TypedBuilder typed(TypeTag typeTag) { - return typed(typeTag, _unused -> new TypedBuilder()); - } - - protected <TB extends TypedBuilder> TB typed(TypeTag typeTag, Function<TypeTag, TB> typedBuilderFunc) { - emitOp(Opcode.TYPED); - code.writeChar(poolHelper.putType(typeHelper.fromTag(typeTag))); - return typedBuilderFunc.apply(typeTag); - } - - public class TypedBuilder { - public C aload_0() { - return CodeBuilder.this.aload_0(); - } - - public C aload_1() { - return CodeBuilder.this.aload_1(); - } - - public C aload_2() { - return CodeBuilder.this.aload_2(); - } - - public C aload_3() { - return CodeBuilder.this.aload_3(); - } - - public C aload(int n) { - return CodeBuilder.this.aload(n); - } - - public C astore_0() { - return CodeBuilder.this.astore_0(); - } - - public C astore_1() { - return CodeBuilder.this.astore_1(); - } - - public C astore_2() { - return CodeBuilder.this.astore_2(); - } - - public C astore_3() { - return CodeBuilder.this.astore_3(); - } - - public C astore(int n) { - return CodeBuilder.this.astore(n); - } - - public C aaload() { - return CodeBuilder.this.aaload(); - } - - public C aastore() { - return CodeBuilder.this.aastore(); - } - - public C areturn() { - return CodeBuilder.this.areturn(); - } - - public C anewarray(S s) { - return CodeBuilder.this.anewarray(s); - } - - public C aconst_null() { - return CodeBuilder.this.aconst_null(); - } - - public C if_acmpeq(short target) { - return CodeBuilder.this.if_acmpeq(target); - } - - public C if_acmpne(short target) { - return CodeBuilder.this.if_acmpeq(target); - } - } - - public C vload(int i) { - return emitWideIfNeeded(Opcode.VLOAD, i); - } - - public C aload(int i) { - return emitWideIfNeeded(Opcode.ALOAD, i); - } - - public C iload(int i) { - return emitWideIfNeeded(Opcode.ILOAD, i); - } - - public C fload(int i) { - return emitWideIfNeeded(Opcode.FLOAD, i); - } - - public C lload(int i) { - return emitWideIfNeeded(Opcode.LLOAD, i); - } - - public C dload(int i) { - return emitWideIfNeeded(Opcode.DLOAD, i); - } - - public C aload_0() { - return emitOp(Opcode.ALOAD_0); - } - - public C iload_0() { - return emitOp(Opcode.ILOAD_0); - } - - public C fload_0() { - return emitOp(Opcode.FLOAD_0); - } - - public C lload_0() { - return emitOp(Opcode.LLOAD_0); - } - - public C dload_0() { - return emitOp(Opcode.DLOAD_0); - } - - public C aload_1() { - return emitOp(Opcode.ALOAD_1); - } - - public C iload_1() { - return emitOp(Opcode.ILOAD_1); - } - - public C fload_1() { - return emitOp(Opcode.FLOAD_1); - } - - public C lload_1() { - return emitOp(Opcode.LLOAD_1); - } - - public C dload_1() { - return emitOp(Opcode.DLOAD_1); - } - - public C aload_2() { - return emitOp(Opcode.ALOAD_2); - } - - public C iload_2() { - return emitOp(Opcode.ILOAD_2); - } - - public C fload_2() { - return emitOp(Opcode.FLOAD_2); - } - - public C lload_2() { - return emitOp(Opcode.LLOAD_2); - } - - public C dload_2() { - return emitOp(Opcode.DLOAD_2); - } - - public C aload_3() { - return emitOp(Opcode.ALOAD_3); - } - - public C iload_3() { - return emitOp(Opcode.ILOAD_3); - } - - public C fload_3() { - return emitOp(Opcode.FLOAD_3); - } - - public C lload_3() { - return emitOp(Opcode.LLOAD_3); - } - - public C dload_3() { - return emitOp(Opcode.DLOAD_3); - } - - public C vstore(int i) { - return emitWideIfNeeded(Opcode.VSTORE, i); - } - - public C astore(int i) { - return emitWideIfNeeded(Opcode.ASTORE, i); - } - - public C istore(int i) { - return emitWideIfNeeded(Opcode.ISTORE, i); - } - - public C fstore(int i) { - return emitWideIfNeeded(Opcode.FSTORE, i); - } - - public C lstore(int i) { - return emitWideIfNeeded(Opcode.LSTORE, i); - } - - public C dstore(int i) { - return emitWideIfNeeded(Opcode.DSTORE, i); - } - - public C astore_0() { - return emitOp(Opcode.ASTORE_0); - } - - public C istore_0() { - return emitOp(Opcode.ISTORE_0); - } - - public C fstore_0() { - return emitOp(Opcode.FSTORE_0); - } - - public C lstore_0() { - return emitOp(Opcode.LSTORE_0); - } - - public C dstore_0() { - return emitOp(Opcode.DSTORE_0); - } - - public C astore_1() { - return emitOp(Opcode.ASTORE_1); - } - - public C istore_1() { - return emitOp(Opcode.ISTORE_1); - } - - public C fstore_1() { - return emitOp(Opcode.FSTORE_1); - } - - public C lstore_1() { - return emitOp(Opcode.LSTORE_1); - } - - public C dstore_1() { - return emitOp(Opcode.DSTORE_1); - } - - public C astore_2() { - return emitOp(Opcode.ASTORE_2); - } - - public C istore_2() { - return emitOp(Opcode.ISTORE_2); - } - - public C fstore_2() { - return emitOp(Opcode.FSTORE_2); - } - - public C lstore_2() { - return emitOp(Opcode.LSTORE_2); - } - - public C dstore_2() { - return emitOp(Opcode.DSTORE_2); - } - - public C astore_3() { - return emitOp(Opcode.ASTORE_3); - } - - public C istore_3() { - return emitOp(Opcode.ISTORE_3); - } - - public C fstore_3() { - return emitOp(Opcode.FSTORE_3); - } - - public C lstore_3() { - return emitOp(Opcode.LSTORE_3); - } - - public C dstore_3() { - return emitOp(Opcode.DSTORE_3); - } - - //... - - public C iaload() { - return emitOp(Opcode.IALOAD); - } - - public C laload() { - return emitOp(Opcode.LALOAD); - } - - public C faload() { - return emitOp(Opcode.FALOAD); - } - - public C daload() { - return emitOp(Opcode.DALOAD); - } - - public C vaload() { - return emitOp(Opcode.VALOAD); - } - - public C aaload() { - return emitOp(Opcode.AALOAD); - } - - public C baload() { - return emitOp(Opcode.BALOAD); - } - - public C caload() { - return emitOp(Opcode.CALOAD); - } - - public C saload() { - return emitOp(Opcode.SALOAD); - } - - public C iastore() { - return emitOp(Opcode.IASTORE); - } - - public C lastore() { - return emitOp(Opcode.LASTORE); - } - - public C fastore() { - return emitOp(Opcode.FASTORE); - } - - public C dastore() { - return emitOp(Opcode.DASTORE); - } - - public C vastore() { - return emitOp(Opcode.VASTORE); - } - - public C aastore() { - return emitOp(Opcode.AASTORE); - } - - public C bastore() { - return emitOp(Opcode.BASTORE); - } - - public C castore() { - return emitOp(Opcode.CASTORE); - } - - public C sastore() { - return emitOp(Opcode.SASTORE); - } - - public C nop() { - return emitOp(Opcode.NOP); - } - - public C aconst_null() { - return emitOp(Opcode.ACONST_NULL); - } - - public C iconst_0() { - return emitOp(Opcode.ICONST_0); - } - - public C iconst_1() { - return emitOp(Opcode.ICONST_1); - } - - public C iconst_2() { - return emitOp(Opcode.ICONST_2); - } - - public C iconst_3() { - return emitOp(Opcode.ICONST_3); - } - - public C iconst_4() { - return emitOp(Opcode.ICONST_4); - } - - public C iconst_5() { - return emitOp(Opcode.ICONST_5); - } - - public C iconst_m1() { - return emitOp(Opcode.ICONST_M1); - } - - public C lconst_0() { - return emitOp(Opcode.LCONST_0); - } - - public C lconst_1() { - return emitOp(Opcode.LCONST_1); - } - - public C fconst_0() { - return emitOp(Opcode.FCONST_0); - } - - public C fconst_1() { - return emitOp(Opcode.FCONST_1); - } - - public C fconst_2() { - return emitOp(Opcode.FCONST_2); - } - - public C dconst_0() { - return emitOp(Opcode.DCONST_0); - } - - public C dconst_1() { - return emitOp(Opcode.DCONST_1); - } - - public C sipush(int s) { - emitOp(Opcode.SIPUSH); - code.writeChar(s); - return thisBuilder(); - } - - public C bipush(int b) { - emitOp(Opcode.BIPUSH); - code.writeByte(b); - return thisBuilder(); - } - - public C pop() { - return emitOp(Opcode.POP); - } - - public C pop2() { - return emitOp(Opcode.POP2); - } - - public C dup() { - return emitOp(Opcode.DUP); - } - - public C dup_x1() { - return emitOp(Opcode.DUP_X1); - } - - public C dup_x2() { - return emitOp(Opcode.DUP_X2); - } - - public C dup2() { - return emitOp(Opcode.DUP2); - } - - public C dup2_x1() { - return emitOp(Opcode.DUP2_X1); - } - - public C dup2_x2() { - return emitOp(Opcode.DUP2_X2); - } - - public C swap() { - return emitOp(Opcode.SWAP); - } - - public C iadd() { - return emitOp(Opcode.IADD); - } - - public C ladd() { - return emitOp(Opcode.LADD); - } - - public C fadd() { - return emitOp(Opcode.FADD); - } - - public C dadd() { - return emitOp(Opcode.DADD); - } - - public C isub() { - return emitOp(Opcode.ISUB); - } - - public C lsub() { - return emitOp(Opcode.LSUB); - } - - public C fsub() { - return emitOp(Opcode.FSUB); - } - - public C dsub() { - return emitOp(Opcode.DSUB); - } - - public C imul() { - return emitOp(Opcode.IMUL); - } - - public C lmul() { - return emitOp(Opcode.LMUL); - } - - public C fmul() { - return emitOp(Opcode.FMUL); - } - - public C dmul() { - return emitOp(Opcode.DMUL); - } - - public C idiv() { - return emitOp(Opcode.IDIV); - } - - public C ldiv() { - return emitOp(Opcode.LDIV); - } - - public C fdiv() { - return emitOp(Opcode.FDIV); - } - - public C ddiv() { - return emitOp(Opcode.DDIV); - } - - public C irem() { - return emitOp(Opcode.IREM); - } - - public C lrem() { - return emitOp(Opcode.LREM); - } - - public C frem() { - return emitOp(Opcode.FREM); - } - - public C drem() { - return emitOp(Opcode.DREM); - } - - public C ineg() { - return emitOp(Opcode.INEG); - } - - public C lneg() { - return emitOp(Opcode.LNEG); - } - - public C fneg() { - return emitOp(Opcode.FNEG); - } - - public C dneg() { - return emitOp(Opcode.DNEG); - } - - public C ishl() { - return emitOp(Opcode.ISHL); - } - - public C lshl() { - return emitOp(Opcode.LSHL); - } - - public C ishr() { - return emitOp(Opcode.ISHR); - } - - public C lshr() { - return emitOp(Opcode.LSHR); - } - - public C iushr() { - return emitOp(Opcode.IUSHR); - } - - public C lushr() { - return emitOp(Opcode.LUSHR); - } - - public C iand() { - return emitOp(Opcode.IAND); - } - - public C land() { - return emitOp(Opcode.LAND); - } - - public C ior() { - return emitOp(Opcode.IOR); - } - - public C lor() { - return emitOp(Opcode.LOR); - } - - public C ixor() { - return emitOp(Opcode.IXOR); - } - - public C lxor() { - return emitOp(Opcode.LXOR); - } - - public C iinc(int index, int val) { - return emitWideIfNeeded(Opcode.IINC, index, val); - } - - public C i2l() { - return emitOp(Opcode.I2L); - } - - public C i2f() { - return emitOp(Opcode.I2F); - } - - public C i2d() { - return emitOp(Opcode.I2D); - } - - public C l2i() { - return emitOp(Opcode.L2I); - } - - public C l2f() { - return emitOp(Opcode.L2F); - } - - public C l2d() { - return emitOp(Opcode.L2D); - } - - public C f2i() { - return emitOp(Opcode.F2I); - } - - public C f2l() { - return emitOp(Opcode.F2L); - } - - public C f2d() { - return emitOp(Opcode.F2D); - } - - public C d2i() { - return emitOp(Opcode.D2I); - } - - public C d2l() { - return emitOp(Opcode.D2L); - } - - public C d2f() { - return emitOp(Opcode.D2F); - } - - public C i2b() { - return emitOp(Opcode.I2B); - } - - public C i2c() { - return emitOp(Opcode.I2C); - } - - public C i2s() { - return emitOp(Opcode.I2S); - } - - public C lcmp() { - return emitOp(Opcode.LCMP); - } - - public C fcmpl() { - return emitOp(Opcode.FCMPL); - } - - public C fcmpg() { - return emitOp(Opcode.FCMPG); - } - - public C dcmpl() { - return emitOp(Opcode.DCMPL); - } - - public C dcmpg() { - return emitOp(Opcode.DCMPG); - } - - public C ifeq(short target) { - return emitNarrowJumpOp(Opcode.IFEQ, target); - } - - public C ifne(short target) { - return emitNarrowJumpOp(Opcode.IFNE, target); - } - - public C iflt(short target) { - return emitNarrowJumpOp(Opcode.IFLT, target); - } - - public C ifge(short target) { - return emitNarrowJumpOp(Opcode.IFGE, target); - } - - public C ifgt(short target) { - return emitNarrowJumpOp(Opcode.IFGT, target); - } - - public C ifle(short target) { - return emitNarrowJumpOp(Opcode.IFLE, target); - } - - public C if_icmpeq(short target) { - return emitNarrowJumpOp(Opcode.IF_ICMPEQ, target); - } - - public C if_icmpne(short target) { - return emitNarrowJumpOp(Opcode.IF_ICMPNE, target); - } - - public C if_icmplt(short target) { - return emitNarrowJumpOp(Opcode.IF_ICMPLT, target); - } - - public C if_icmpge(short target) { - return emitNarrowJumpOp(Opcode.IF_ICMPGE, target); - } - - public C if_icmpgt(short target) { - return emitNarrowJumpOp(Opcode.IF_ICMPGT, target); - } - - public C if_icmple(short target) { - return emitNarrowJumpOp(Opcode.IF_ICMPLE, target); - } - - public C if_acmpeq(short target) { - return emitNarrowJumpOp(Opcode.IF_ACMPEQ, target); - } - - public C if_acmpne(short target) { - return emitNarrowJumpOp(Opcode.IF_ACMPNE, target); - } - - public C goto_(short target) { - return emitNarrowJumpOp(Opcode.GOTO_, target); - } - - public C jsr(short target) { - return emitNarrowJumpOp(Opcode.JSR, target); - } - - public C ret(int index) { - return emitWideIfNeeded(Opcode.RET, index); - } - - public C tableswitch(int low, int high, int defaultTarget, int... targets) { - if (high - low + 1 != targets.length) throw new IllegalStateException("Bad targets length"); - emitOp(Opcode.TABLESWITCH); - //padding - int start = code.offset; - if ((start % 4) != 0) { - //add padding - for (int i = 0; i < 4 - (start % 4); i++) { - code.writeByte(0); - } - } - code.writeInt(defaultTarget) - .writeInt(low) - .writeInt(high); - for (int target : targets) { - code.writeInt(target); - } - return thisBuilder(); - } - - public C lookupswitch(int defaultTarget, int... npairs) { - if (npairs.length % 2 != 0) throw new IllegalStateException("Bad npairs length"); - emitOp(Opcode.LOOKUPSWITCH); - //padding - int start = code.offset; - for (int i = 0; i < (4 - (start % 4)); i++) { - code.writeByte(0); - } - code.writeInt(defaultTarget) - .writeInt(npairs.length / 2); - for (int i = 0; i < npairs.length; i += 2) { - code.writeInt(npairs[i]); - code.writeInt(npairs[i + 1]); - } - return thisBuilder(); - } - - public C arraylength() { - return emitOp(Opcode.ARRAYLENGTH); - } - - public C athrow() { - return emitOp(Opcode.ATHROW); - } - - public C monitorenter() { - return emitOp(Opcode.MONITORENTER); - } - - public C monitorexit() { - return emitOp(Opcode.MONITOREXIT); - } - - public C wide() { - return emitOp(Opcode.WIDE); - } - - public C if_null(short offset) { - return emitNarrowJumpOp(Opcode.IF_NULL, offset); - } - - public C if_nonnull(short offset) { - return emitNarrowJumpOp(Opcode.IF_NONNULL, offset); - } - - public C goto_w(int target) { - return emitWideJumpOp(Opcode.GOTO_W, target); - } - - public C jsr_w(int target) { - return emitWideJumpOp(Opcode.JSR_W, target); - } - - public C withCatch(S type, int start, int end, int offset) { - catchers.writeChar(start); - catchers.writeChar(end); - catchers.writeChar(offset); - catchers.writeChar(type != null ? poolHelper.putClass(type) : 0); - ncatchers++; - return thisBuilder(); - } - - public C withLocalSize(int localsize) { - this.localsize = localsize; - return thisBuilder(); - } - - public C withStackSize(int stacksize) { - this.stacksize = stacksize; - return thisBuilder(); - } - - protected int localsize() { - return localsize; - } - - void build(GrowableByteBuffer buf) { - buf.writeChar(stacksize); //max stack size - buf.writeChar(localsize()); //max locals - buf.writeInt(code.offset); - buf.writeBytes(code); - buf.writeChar(ncatchers); - buf.writeBytes(catchers); - buf.writeChar(nattrs); //attributes - buf.writeBytes(attributes); - } - - byte[] build() { - GrowableByteBuffer buf = new GrowableByteBuffer(); - build(buf); - return buf.bytes(); - } - - protected C emitNarrowJumpOp(Opcode opcode, short target) { - emitOp(opcode); - emitOffset(code, JumpMode.NARROW, target); - return thisBuilder(); - } - - protected C emitWideJumpOp(Opcode opcode, int target) { - emitOp(opcode); - emitOffset(code, JumpMode.WIDE, target); - return thisBuilder(); - } - - protected C emitOp(Opcode opcode) { - return emitOp(opcode, null); - } - - protected C emitOp(Opcode opcode, Object optPoolValue) { - code.writeByte(opcode.code); - return thisBuilder(); - } - - protected void emitOffset(GrowableByteBuffer buf, JumpMode jumpMode, int offset) { - if (jumpMode == JumpMode.NARROW) { - buf.writeChar((short) offset); - } else { - buf.writeInt(offset); - } - } - - int offset() { - return code.offset; - } - - /*** stackmap support ***/ - - /** - * The tags and constants used in compressed stackmap. - */ - static final int SAME_FRAME_SIZE = 64; - static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247; - static final int SAME_FRAME_EXTENDED = 251; - static final int FULL_FRAME = 255; - static final int MAX_LOCAL_LENGTH_DIFF = 4; - - @SuppressWarnings("unchecked") - private void writeStackMapType(T t) { - if (t == null) { - stackmaps.writeByte(0); - } else { - switch (typeHelper.tag(t)) { - case B: - case C: - case S: - case I: - case Z: - stackmaps.writeByte(1); - break; - case F: - stackmaps.writeByte(2); - break; - case D: - stackmaps.writeByte(3); - break; - case J: - stackmaps.writeByte(4); - break; - case A: - if (t == typeHelper.nullType()) { - stackmaps.writeByte(5); //null - } else { - //TODO: uninit this, top? - stackmaps.writeByte(7); - stackmaps.writeChar(poolHelper.putClass(typeHelper.symbol(t))); - } - break; - default: - throw new IllegalStateException("Bad type"); - } - } - } - - public void sameFrame(int offsetDelta) { - int frameType = (offsetDelta < SAME_FRAME_SIZE) ? - offsetDelta : SAME_FRAME_EXTENDED; - stackmaps.writeByte(frameType); - if (frameType == SAME_FRAME_EXTENDED) { - stackmaps.writeChar(offsetDelta); - } - } - - public void sameLocals1StackItemFrame(int offsetDelta, T stackItem) { - int frameType = (offsetDelta < SAME_FRAME_SIZE) ? - (SAME_FRAME_SIZE + offsetDelta) : SAME_LOCALS_1_STACK_ITEM_EXTENDED; - stackmaps.writeByte(frameType); - if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { - stackmaps.writeChar(offsetDelta); - } - writeStackMapType(stackItem); - } - - public void appendFrame(int offsetDelta, int prevLocalsSize, List<T> locals) { - int frameType = SAME_FRAME_EXTENDED + (locals.size() - prevLocalsSize); - stackmaps.writeByte(frameType); - stackmaps.writeChar(offsetDelta); - for (int i = prevLocalsSize; i < locals.size(); i++) { - writeStackMapType(locals.get(i)); - } - } - - public void chopFrame(int offsetDelta, int droppedVars) { - int frameType = SAME_FRAME_EXTENDED - droppedVars; - stackmaps.writeByte(frameType); - stackmaps.writeChar(offsetDelta); - } - - public void fullFrame(int offsetDelta, List<T> locals, List<T> stackItems) { - stackmaps.writeByte(FULL_FRAME); - stackmaps.writeChar(offsetDelta); - stackmaps.writeChar(locals.size()); - for (T local : locals) { - writeStackMapType(local); - } - - stackmaps.writeChar(stackItems.size()); - for (T stackType : stackItems) { - writeStackMapType(stackType); - } - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/DeclBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/DeclBuilder.java deleted file mode 100644 index 7e77ae3fe2a..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/DeclBuilder.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.function.Consumer; - -/** - * Declaration (class, class member, ...) builder. - * - * @param <S> the type of symbol representation - * @param <T> the type of type descriptors representation - * @param <E> the type of pool entries - * @param <D> the type of this builder - */ -public class DeclBuilder<S, T, E, D extends DeclBuilder<S, T, E, D>> - extends AttributeBuilder<S, T, E, D> { - - /** - * The access flags of the declaration, as bit flags. - */ - protected int flags; - - AnnotationsBuilder<S, T, E> runtimeInvisibleAnnotations; - AnnotationsBuilder<S, T, E> runtimeVisibleAnnotations; - - /** - * Create a declaration builder, - * - * @param poolHelper the helper to build the constant pool - * @param typeHelper the helper to use to manipulate type descriptors - */ - DeclBuilder(PoolHelper<S, T, E> poolHelper, TypeHelper<S, T> typeHelper) { - super(poolHelper, typeHelper); - } - - /** - * Specify the class file flags for this declaration. - * - * @param flags the flags as {@code Flag} objects - * @return this builder, for chained calls - */ - public D withFlags(Flag... flags) { - for (Flag f : flags) { - this.flags |= f.flag; - } - return thisBuilder(); - } - - /** - * Specify, via bits, the class file flags for this declaration. - * - * @param flags the flags as bit settings - * @return this builder, for chained calls - */ - public D withFlags(int flags) { - withFlags(Flag.parse(flags)); - return thisBuilder(); - } - - public D withAnnotation(AnnotationsBuilder.Kind kind, T annoType) { - getAnnotations(kind).withAnnotation(annoType, null); - return thisBuilder(); - } - - public D withAnnotation(AnnotationsBuilder.Kind kind, T annoType, Consumer<? super AnnotationsBuilder<S, T, E>.AnnotationElementBuilder> annotations) { - getAnnotations(kind).withAnnotation(annoType, annotations); - return thisBuilder(); - } - - private AnnotationsBuilder<S, T, E> getAnnotations(AnnotationsBuilder.Kind kind) { - switch (kind) { - case RUNTIME_INVISIBLE: - if (runtimeInvisibleAnnotations == null) { - runtimeInvisibleAnnotations = new AnnotationsBuilder<>(poolHelper, typeHelper); - } - return runtimeInvisibleAnnotations; - case RUNTIME_VISIBLE: - if (runtimeVisibleAnnotations == null) { - runtimeVisibleAnnotations = new AnnotationsBuilder<>(poolHelper, typeHelper); - } - return runtimeVisibleAnnotations; - } - throw new IllegalStateException(); - } - - void addAnnotations() { - if (runtimeVisibleAnnotations != null) { - withAttribute("RuntimeVisibleAnnotations", runtimeVisibleAnnotations.build()); - } - if (runtimeInvisibleAnnotations != null) { - withAttribute("RuntimeInvisibleAnnotations", runtimeVisibleAnnotations.build()); - } - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/FieldBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/FieldBuilder.java deleted file mode 100644 index 688d3addef0..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/FieldBuilder.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -/** - * Field builder. - * - * @param <S> the type of symbol representation - * @param <T> the type of type descriptor representation - * @param <E> the type of pool entries - */ -public class FieldBuilder<S, T, E> extends MemberBuilder<S, T, E, FieldBuilder<S, T, E>> { - public FieldBuilder(CharSequence name, T type, PoolHelper<S, T, E> poolHelper, TypeHelper<S, T> typeHelper) { - super(name, type, poolHelper, typeHelper); - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/Flag.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/Flag.java deleted file mode 100644 index 47da97ab1a6..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/Flag.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.EnumSet; - -public enum Flag { - ACC_PUBLIC(0x0001), - ACC_PROTECTED(0x0004), - ACC_PRIVATE(0x0002), - ACC_INTERFACE(0x0200), - ACC_ENUM(0x4000), - ACC_ANNOTATION(0x2000), - ACC_SUPER(0x0020), - ACC_ABSTRACT(0x0400), - ACC_VOLATILE(0x0040), - ACC_TRANSIENT(0x0080), - ACC_SYNTHETIC(0x1000), - ACC_STATIC(0x0008), - ACC_FINAL(0x0010), - ACC_SYNCHRONIZED(0x0020), - ACC_BRIDGE(0x0040), - ACC_VARARGS(0x0080), - ACC_NATIVE(0x0100), - ACC_STRICT(0x0800); - - public int flag; - - Flag(int flag) { - this.flag = flag; - } - - static Flag[] parse(int flagsMask) { - EnumSet<Flag> flags = EnumSet.noneOf(Flag.class); - for (Flag f : Flag.values()) { - if ((f.flag & flagsMask) != 0) { - flags.add(f); - } - } - return flags.stream().toArray(Flag[]::new); - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/GrowableByteBuffer.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/GrowableByteBuffer.java deleted file mode 100644 index b87228e73d7..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/GrowableByteBuffer.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.function.Consumer; - -public class GrowableByteBuffer { - - public GrowableByteBuffer() { - } - - byte[] elems = new byte[64]; - int offset = 0; - - public GrowableByteBuffer writeByte(int b) { - return writeBytes(1, b); - } - - public GrowableByteBuffer writeChar(int x) { - return writeBytes(2, x); - } - - public GrowableByteBuffer writeInt(int x) { - return writeBytes(4, x); - } - - public GrowableByteBuffer writeFloat(float x) { - return writeInt(Float.floatToIntBits(x)); - } - - public GrowableByteBuffer writeLong(long x) { - return writeBytes(8, x); - } - - public GrowableByteBuffer writeDouble(double x) { - writeLong(Double.doubleToLongBits(x)); - return this; - } - - public GrowableByteBuffer writeBytes(byte[] barr) { - expandIfNeeded(barr.length); - System.arraycopy(barr, 0, elems, offset, barr.length); - offset += barr.length; - return this; - } - - public GrowableByteBuffer writeBytes(GrowableByteBuffer bb) { - expandIfNeeded(bb.offset); - System.arraycopy(bb.elems, 0, elems, offset, bb.offset); - offset += bb.offset; - return this; - } - - public GrowableByteBuffer withOffset(int offset, Consumer<GrowableByteBuffer> actions) { - int prevOffset = this.offset; - this.offset = offset; - actions.accept(this); - this.offset = prevOffset; - return this; - } - - private GrowableByteBuffer writeBytes(int size, long x) { - expandIfNeeded(size); - for (int i = 0; i < size; i++) { - elems[offset++] = (byte) ((x >> 8 * (size - i - 1)) & 0xFF); - } - return this; - } - - void expandIfNeeded(int increment) { - if (offset + increment > elems.length) { - int newsize = elems.length * 2; - while (offset + increment > newsize) { - newsize *= 2; - } - byte[] newelems = new byte[newsize]; - System.arraycopy(elems, 0, newelems, 0, offset); - elems = newelems; - } - } - - public byte[] bytes() { - byte[] bytes = new byte[offset]; - System.arraycopy(elems, 0, bytes, 0, offset); - return bytes; - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/IsolatedMethodBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/IsolatedMethodBuilder.java deleted file mode 100644 index 7d84af52263..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/IsolatedMethodBuilder.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodHandles.Lookup; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.ToIntFunction; - -public class IsolatedMethodBuilder extends MethodBuilder<Class<?>, String, Object[]> { - - public IsolatedMethodBuilder(Lookup lookup, String name, String type) { - super(null, name, type, new IsolatedMethodPoolHelper(lookup), null); - } - - static class IsolatedMethodPoolHelper implements PoolHelper<Class<?>, String, Object[]> { - Map<Object, Integer> constants = new HashMap<>(); - Lookup lookup; - - private IsolatedMethodPoolHelper(Lookup lookup) { - this.lookup = lookup; - } - - @Override - public int putClass(Class<?> symbol) { - return putIfAbsent(symbol); - } - - @Override - public int putFieldRef(Class<?> owner, CharSequence name, String type) { - try { - Field f = owner.getDeclaredField(name.toString()); //TODO: we should unreflect for a var handle - return putIfAbsent(lookup.unreflectGetter(f)); - } catch (Throwable ex) { - ex.printStackTrace(); - return -1; - } - } - - @Override - public int putMethodRef(Class<?> owner, CharSequence name, String type, boolean isInterface) { - try { - Method m = owner.getDeclaredMethod(name.toString()); //we should unreflect according to method vs. constructor - //and static vs. private etc. - return putIfAbsent(lookup.unreflect(m)); - } catch (Throwable ex) { - ex.printStackTrace(); - return -1; - } - } - - @Override - public int putInt(int i) { - return putIfAbsent(i); - } - - @Override - public int putFloat(float f) { - return putIfAbsent(f); - } - - @Override - public int putLong(long l) { - return putIfAbsent(l); - } - - @Override - public int putDouble(double d) { - return putIfAbsent(d); - } - - @Override - public int putString(String s) { - return putIfAbsent(s); - } - - @Override - public int putInvokeDynamic(CharSequence invokedName, String invokedType, Class<?> bsmClass, CharSequence bsmName, String bsmType, Consumer<StaticArgListBuilder<Class<?>, String, Object[]>> staticArgs) { - return 0; //??? - } - - @Override - public int putDynamicConstant(CharSequence constName, String constType, Class<?> bsmClass, CharSequence bsmName, String bsmType, Consumer<StaticArgListBuilder<Class<?>, String, Object[]>> staticArgs) { - return 0; //??? - } - - @Override - public int putHandle(int refKind, Class<?> owner, CharSequence name, String type) { - return 0; //??? - } - - @Override - public int putHandle(int refKind, Class<?> owner, CharSequence name, String type, boolean isInterface) { - return 0; //??? - } - - @Override - public int putMethodType(String s) { - return 0; //??? - } - - @Override - public int putUtf8(CharSequence s) { - return putIfAbsent(s); - } - - @Override - public int putType(String s) { - return putIfAbsent(s); - } - - @Override - public int size() { - return constants.size(); - } - - @Override - public Object[] entries() { - return constants.keySet().toArray(); - } - - int putIfAbsent(Object o) { - int nextIndex = constants.size() + 1; - Object res = constants.putIfAbsent(o, nextIndex); - return res == null ? - nextIndex : (Integer)res; - } - } - - public Object[] entries() { - return poolHelper.entries(); - } - - @Override - public byte[] build() { - byte[] arr = super.build(); - int codelength_offset = 2 + 2 + 2 + 2 + - 2 + 4 + 2 + 2; - int code_offset = codelength_offset + 4; - int length = ByteBuffer.wrap(arr).getInt(codelength_offset); - byte[] opcodes = new byte[length]; - System.arraycopy(arr, code_offset, opcodes, 0, length); - return opcodes; - } - - public static void main(String[] args) { - IsolatedMethodBuilder imb = new IsolatedMethodBuilder(MethodHandles.lookup(), "foo", "(java/lang/String;)I"); - imb.withCode(C -> - C.aload_0() - .invokevirtual(String.class, "length", "()I", false) - .ireturn()); - byte[] opcodes = imb.build(); - System.out.println(Arrays.toString(opcodes)); - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/MacroCodeBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/MacroCodeBuilder.java deleted file mode 100644 index 4cd50cc8789..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/MacroCodeBuilder.java +++ /dev/null @@ -1,712 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.function.Consumer; - -public class MacroCodeBuilder<S, T, E, C extends MacroCodeBuilder<S, T, E, C>> extends CodeBuilder<S, T, E, C> { - - JumpMode jumpMode = JumpMode.NARROW; - - Map<CharSequence, Integer> labels = new HashMap<>(); - List<PendingJump> pendingJumps = new LinkedList<>(); - - class PendingJump { - CharSequence label; - int pc; - - PendingJump(CharSequence label, int pc) { - this.label = label; - this.pc = pc; - } - - boolean resolve(CharSequence label, int offset) { - if (this.label.equals(label)) { - //patch offset - code.withOffset(pc + 1, buf -> emitOffset(buf, jumpMode, offset - pc)); - return true; - } else { - return false; - } - } - } - - public enum InvocationKind { - INVOKESTATIC, - INVOKEVIRTUAL, - INVOKESPECIAL, - INVOKEINTERFACE; - } - - public enum FieldAccessKind { - STATIC, - INSTANCE; - } - - public enum CondKind { - EQ(0), - NE(1), - LT(2), - GE(3), - GT(4), - LE(5); - - int offset; - - CondKind(int offset) { - this.offset = offset; - } - - public CondKind negate() { - switch (this) { - case EQ: - return NE; - case NE: - return EQ; - case LT: - return GE; - case GE: - return LT; - case GT: - return LE; - case LE: - return GT; - default: - throw new IllegalStateException("Unknown cond"); - } - } - } - - static class WideJumpException extends RuntimeException { - static final long serialVersionUID = 42L; - } - - public MacroCodeBuilder(MethodBuilder<S, T, E> methodBuilder) { - super(methodBuilder); - } - - public C load(TypeTag type, int n) { - if (type == TypeTag.Q) { - return vload(n); - } else { - switch (n) { - case 0: - return emitOp(Opcode.ILOAD_0.at(type, 4)); - case 1: - return emitOp(Opcode.ILOAD_1.at(type, 4)); - case 2: - return emitOp(Opcode.ILOAD_2.at(type, 4)); - case 3: - return emitOp(Opcode.ILOAD_3.at(type, 4)); - default: - return emitWideIfNeeded(Opcode.ILOAD.at(type), n); - } - } - } - - public C store(TypeTag type, int n) { - if (type == TypeTag.Q) { - return vstore(n); - } else { - switch (n) { - case 0: - return emitOp(Opcode.ISTORE_0.at(type, 4)); - case 1: - return emitOp(Opcode.ISTORE_1.at(type, 4)); - case 2: - return emitOp(Opcode.ISTORE_2.at(type, 4)); - case 3: - return emitOp(Opcode.ISTORE_3.at(type, 4)); - default: - return emitWideIfNeeded(Opcode.ISTORE.at(type), n); - } - } - } - - public C arrayload(TypeTag type) { - return emitOp(Opcode.IALOAD.at(type)); - } - - public C arraystore(TypeTag type, int n) { - return emitOp(Opcode.IASTORE.at(type)); - } - - public C const_(int i) { - switch (i) { - case -1: - return iconst_m1(); - case 0: - return iconst_0(); - case 1: - return iconst_1(); - case 2: - return iconst_2(); - case 3: - return iconst_3(); - case 4: - return iconst_4(); - case 5: - return iconst_5(); - default: - if (i > 0 && i <= Byte.MAX_VALUE) { - return bipush(i); - } else if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) { - return sipush(i); - } else { - return ldc(i); - } - } - } - - public C const_(long l) { - if (l == 0) { - return lconst_0(); - } else if (l == 1) { - return lconst_1(); - } else { - return ldc(l); - } - } - - public C const_(float f) { - if (f == 0) { - return fconst_0(); - } else if (f == 1) { - return fconst_1(); - } else if (f == 2) { - return fconst_2(); - } else { - return ldc(f); - } - } - - public C const_(double d) { - if (d == 0) { - return dconst_0(); - } else if (d == 1) { - return dconst_1(); - } else { - return ldc(d); - } - } - - public C getfield(FieldAccessKind fak, S owner, CharSequence name, T type) { - switch (fak) { - case INSTANCE: - return getfield(owner, name, type); - case STATIC: - return getstatic(owner, name, type); - default: - throw new IllegalStateException(); - } - } - - public C putfield(FieldAccessKind fak, S owner, CharSequence name, T type) { - switch (fak) { - case INSTANCE: - return putfield(owner, name, type); - case STATIC: - return putstatic(owner, name, type); - default: - throw new IllegalStateException(); - } - } - - public C invoke(InvocationKind ik, S owner, CharSequence name, T type, boolean isInterface) { - switch (ik) { - case INVOKESTATIC: - return invokestatic(owner, name, type, isInterface); - case INVOKEVIRTUAL: - return invokevirtual(owner, name, type, isInterface); - case INVOKESPECIAL: - return invokespecial(owner, name, type, isInterface); - case INVOKEINTERFACE: - if (!isInterface) throw new AssertionError(); - return invokeinterface(owner, name, type); - default: - throw new IllegalStateException(); - } - } - - public C add(TypeTag type) { - return emitOp(Opcode.IADD.at(type)); - } - - public C sub(TypeTag type) { - return emitOp(Opcode.ISUB.at(type)); - } - - public C mul(TypeTag type) { - return emitOp(Opcode.IMUL.at(type)); - } - - public C div(TypeTag type) { - return emitOp(Opcode.IDIV.at(type)); - } - - public C rem(TypeTag type) { - return emitOp(Opcode.IREM.at(type)); - } - - public C neg(TypeTag type) { - return emitOp(Opcode.INEG.at(type)); - } - - public C shl(TypeTag type) { - return emitOp(Opcode.ISHL.at(type)); - } - - public C shr(TypeTag type) { - return emitOp(Opcode.ISHR.at(type)); - } - - public C ushr(TypeTag type) { - return emitOp(Opcode.ISHR.at(type)); - } - - public C and(TypeTag type) { - return emitOp(Opcode.IAND.at(type)); - } - - public C or(TypeTag type) { - return emitOp(Opcode.IOR.at(type)); - } - - public C xor(TypeTag type) { - return emitOp(Opcode.IXOR.at(type)); - } - - public C return_(TypeTag type) { - switch (type) { - case V: - return return_(); - case Q: - return vreturn(); - default: - return emitOp(Opcode.IRETURN.at(type)); - } - } - - @Override - public LabelledTypedBuilder typed(TypeTag typeTag) { - return super.typed(typeTag, _unused -> new LabelledTypedBuilder()); - } - - public class LabelledTypedBuilder extends TypedBuilder { - public C if_acmpeq(CharSequence target) { - return ifcmp(TypeTag.A, CondKind.EQ, target); - } - - public C if_acmpne(CharSequence target) { - return ifcmp(TypeTag.A, CondKind.NE, target); - } - } - - public C conv(TypeTag from, TypeTag to) { - switch (from) { - case B: - case C: - case S: - switch (to) { - case J: - return i2l(); - case F: - return i2f(); - case D: - return i2d(); - } - break; - case I: - switch (to) { - case J: - return i2l(); - case F: - return i2f(); - case D: - return i2d(); - case B: - return i2b(); - case C: - return i2c(); - case S: - return i2s(); - } - break; - case J: - switch (to) { - case I: - return l2i(); - case F: - return l2f(); - case D: - return l2d(); - } - break; - case F: - switch (to) { - case I: - return f2i(); - case J: - return f2l(); - case D: - return f2d(); - } - break; - case D: - switch (to) { - case I: - return d2i(); - case J: - return d2l(); - case F: - return d2f(); - } - break; - } - //no conversion is necessary - do nothing! - return thisBuilder(); - } - - public C if_null(CharSequence label) { - return emitCondJump(Opcode.IF_NULL, Opcode.IF_NONNULL, label); - } - - public C if_nonnull(CharSequence label) { - return emitCondJump(Opcode.IF_NONNULL, Opcode.IF_NULL, label); - } - - public C ifcmp(TypeTag type, CondKind cond, CharSequence label) { - switch (type) { - case I: - return emitCondJump(Opcode.IF_ICMPEQ, cond, label); - case A: - return emitCondJump(Opcode.IF_ACMPEQ, cond, label); - case J: - return lcmp().emitCondJump(Opcode.IFEQ, cond, label); - case D: - return dcmpg().emitCondJump(Opcode.IFEQ, cond, label); - case F: - return fcmpg().emitCondJump(Opcode.IFEQ, cond, label); - default: - throw new IllegalArgumentException("Bad cmp type"); - } - } - - public C goto_(CharSequence label) { - emitOp(jumpMode == JumpMode.NARROW ? Opcode.GOTO_ : Opcode.GOTO_W); - emitOffset(code, jumpMode, labelOffset(label)); - return thisBuilder(); - } - - protected int labelOffset(CharSequence label) { - int pc = code.offset - 1; - Integer labelPc = labels.get(label); - if (labelPc == null) { - addPendingJump(label, pc); - } - return labelPc == null ? 0 : (labelPc - pc); - } - - public C label(CharSequence s) { - int pc = code.offset; - Object old = labels.put(s, pc); - if (old != null) { - throw new IllegalStateException("label already exists"); - } - resolveJumps(s, pc); - return thisBuilder(); - } - - //FIXME: address this jumpy mess - i.e. offset and state update work against each other! - public C emitCondJump(Opcode opcode, CondKind ck, CharSequence label) { - return emitCondJump(opcode.at(ck), opcode.at(ck.negate()), label); - } - - public C emitCondJump(Opcode pos, Opcode neg, CharSequence label) { - if (jumpMode == JumpMode.NARROW) { - emitOp(pos); - emitOffset(code, jumpMode, labelOffset(label)); - } else { - emitOp(neg); - emitOffset(code, JumpMode.NARROW, 8); - goto_w(labelOffset(label)); - } - return thisBuilder(); - } - - void addPendingJump(CharSequence label, int pc) { - pendingJumps.add(new PendingJump(label, pc)); - } - - void resolveJumps(CharSequence label, int pc) { - Iterator<PendingJump> jumpsIt = pendingJumps.iterator(); - while (jumpsIt.hasNext()) { - PendingJump jump = jumpsIt.next(); - if (jump.resolve(label, pc)) { - jumpsIt.remove(); - } - } - } - - @Override - protected void emitOffset(GrowableByteBuffer buf, JumpMode jumpMode, int offset) { - if (jumpMode == JumpMode.NARROW && (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE)) { - throw new WideJumpException(); - } - super.emitOffset(buf, jumpMode, offset); - } - - public C jsr(CharSequence label) { - emitOp(jumpMode == JumpMode.NARROW ? Opcode.JSR : Opcode.JSR_W); - emitOffset(code, jumpMode, labelOffset(label)); - return thisBuilder(); - } - - @SuppressWarnings("unchecked") - public C withTry(Consumer<? super C> tryBlock, Consumer<? super CatchBuilder> catchBlocks) { - int start = code.offset; - tryBlock.accept((C) this); - int end = code.offset; - CatchBuilder catchBuilder = makeCatchBuilder(start, end); - catchBlocks.accept(catchBuilder); - catchBuilder.build(); - return thisBuilder(); - } - - void clear() { - code.offset = 0; - catchers.offset = 0; - ncatchers = 0; - labels.clear(); - pendingJumps = null; - } - - protected CatchBuilder makeCatchBuilder(int start, int end) { - return new CatchBuilder(start, end); - } - - public class CatchBuilder { - int start, end; - - String endLabel = labelName(); - - Map<S, Consumer<? super C>> catchers = new LinkedHashMap<>(); - public Consumer<? super C> finalizer; - List<Integer> pendingGaps = new ArrayList<>(); - - public CatchBuilder(int start, int end) { - this.start = start; - this.end = end; - } - - public CatchBuilder withCatch(S exc, Consumer<? super C> catcher) { - catchers.put(exc, catcher); - return this; - } - - public CatchBuilder withFinally(Consumer<? super C> finalizer) { - this.finalizer = finalizer; - return this; - } - - @SuppressWarnings("unchecked") - void build() { - if (finalizer != null) { - finalizer.accept((C) MacroCodeBuilder.this); - } - goto_(endLabel); - for (Map.Entry<S, Consumer<? super C>> catcher_entry : catchers.entrySet()) { - emitCatch(catcher_entry.getKey(), catcher_entry.getValue()); - } - if (finalizer != null) { - emitFinalizer(); - } - resolveJumps(endLabel, code.offset); - } - - @SuppressWarnings("unchecked") - protected void emitCatch(S exc, Consumer<? super C> catcher) { - int offset = code.offset; - MacroCodeBuilder.this.withCatch(exc, start, end, offset); - catcher.accept((C) MacroCodeBuilder.this); - if (finalizer != null) { - int startFinalizer = code.offset; - finalizer.accept((C) MacroCodeBuilder.this); - pendingGaps.add(startFinalizer); - pendingGaps.add(code.offset); - } - goto_(endLabel); - } - - @SuppressWarnings("unchecked") - protected void emitFinalizer() { - int offset = code.offset; - pop(); - for (int i = 0; i < pendingGaps.size(); i += 2) { - MacroCodeBuilder.this.withCatch(null, pendingGaps.get(i), pendingGaps.get(i + 1), offset); - } - MacroCodeBuilder.this.withCatch(null, start, end, offset); - finalizer.accept((C) MacroCodeBuilder.this); - } - -// @SuppressWarnings("unchecked") -// CatchBuilder withCatch(S exc, Consumer<? super C> catcher) { -// int offset = code.offset; -// MacroCodeBuilder.this.withCatch(exc, start, end, offset); -// catcher.accept((C)MacroCodeBuilder.this); -// return this; -// } -// -// @SuppressWarnings("unchecked") -// CatchBuilder withFinally(Consumer<? super C> catcher) { -// int offset = code.offset; -// MacroCodeBuilder.this.withCatch(null, start, end, offset); -// catcher.accept((C)MacroCodeBuilder.this); -// return this; -// } - } - - @SuppressWarnings("unchecked") - public C switch_(Consumer<? super SwitchBuilder> consumer) { - int start = code.offset; - SwitchBuilder sb = makeSwitchBuilder(); - consumer.accept(sb); - int nlabels = sb.cases.size(); - switch (sb.switchCode()) { - case LOOKUPSWITCH: { - int[] lookupOffsets = new int[nlabels * 2]; - int i = 0; - for (Integer v : sb.cases.keySet()) { - lookupOffsets[i] = v; - i += 2; - } - lookupswitch(0, lookupOffsets); - //backpatch lookup - int curr = code.offset - (8 * nlabels) - 8; - int defaultOffset = code.offset - start; - code.withOffset(curr, buf -> emitOffset(buf, JumpMode.WIDE, defaultOffset)); - sb.defaultCase.accept((C) this); - curr += 12; - for (Consumer<? super C> case_ : sb.cases.values()) { - int offset = code.offset; - code.withOffset(curr, buf -> emitOffset(buf, JumpMode.WIDE, offset - start)); - case_.accept((C) this); - curr += 8; - } - break; - } - case TABLESWITCH: { - int[] tableOffsets = new int[sb.hi - sb.lo + 1]; - tableswitch(sb.lo, sb.hi, 0, tableOffsets); - //backpatch table - int curr = code.offset - (4 * tableOffsets.length) - 12; - int defaultOffset = code.offset - start; - code.withOffset(curr, buf -> emitOffset(buf, JumpMode.WIDE, defaultOffset)); - sb.defaultCase.accept((C) this); - curr += 12; - int lastCasePc = -1; - for (int i = sb.lo; i <= sb.hi; i++) { - Consumer<? super C> case_ = sb.cases.get(i); - if (case_ != null) { - lastCasePc = code.offset; - case_.accept((C) this); - } - int offset = lastCasePc - start; - code.withOffset(curr, buf -> emitOffset(buf, JumpMode.WIDE, offset)); - curr += 4; - } - } - } - resolveJumps(sb.endLabel, code.offset); - return thisBuilder(); - } - - private static int labelCount = 0; - - String labelName() { - return "label" + labelCount++; - } - - protected SwitchBuilder makeSwitchBuilder() { - return new SwitchBuilder(); - } - - public class SwitchBuilder { - Map<Integer, Consumer<? super C>> cases = new TreeMap<>(); - int lo = Integer.MAX_VALUE; - int hi = Integer.MIN_VALUE; - String endLabel = labelName(); - - public Consumer<? super C> defaultCase; - - @SuppressWarnings("unchecked") - public SwitchBuilder withCase(int value, Consumer<? super C> case_, boolean fallthrough) { - if (value > hi) { - hi = value; - } - if (value < lo) { - lo = value; - } - if (!fallthrough) { - Consumer<? super C> prevCase = case_; - case_ = C -> { - prevCase.accept(C); - C.goto_(endLabel); - }; - } - cases.put(value, case_); - return this; - } - - @SuppressWarnings("unchecked") - public SwitchBuilder withDefault(Consumer<? super C> defaultCase) { - if (this.defaultCase != null) { - throw new IllegalStateException("default already set"); - } - this.defaultCase = defaultCase; - return this; - } - - Opcode switchCode() { - int nlabels = cases.size(); - // Determine whether to issue a tableswitch or a lookupswitch - // instruction. - long table_space_cost = 4 + ((long) hi - lo + 1); // words - long lookup_space_cost = 3 + 2 * (long) nlabels; - return - nlabels > 0 && - table_space_cost <= lookup_space_cost - ? - Opcode.TABLESWITCH : Opcode.LOOKUPSWITCH; - } - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/MemberBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/MemberBuilder.java deleted file mode 100644 index 45a29d8534e..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/MemberBuilder.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -/** - * Class member builder. - * - * @param <S> the type of symbol representation - * @param <T> the type of type descriptors representation - * @param <E> the type of pool entries - * @param <M> the type of this builder - */ -public class MemberBuilder<S, T, E, M extends MemberBuilder<S, T, E, M>> extends DeclBuilder<S, T, E, M> { - - CharSequence name; - T desc; - - /** - * Create a member builder. - * - * @param name the name of the class member - * @param type the type descriptor of the class member - * @param poolHelper the helper to build the constant pool - * @param typeHelper the helper to use to manipulate type descriptors - */ - MemberBuilder(CharSequence name, T type, PoolHelper<S, T, E> poolHelper, TypeHelper<S, T> typeHelper) { - super(poolHelper, typeHelper); - this.name = name; - this.desc = type; - } - - /** - * Build the member. - * - * @param buf the {@code GrowableByteBuffer} to build the member into - */ - protected void build(GrowableByteBuffer buf) { - addAnnotations(); - buf.writeChar(flags); - buf.writeChar(poolHelper.putUtf8(name)); - buf.writeChar(poolHelper.putType(desc)); - buf.writeChar(nattrs); - buf.writeBytes(attributes); - } - - /** - * Build the member. - * - * @return a byte array representation of the member - */ - protected byte[] build() { - GrowableByteBuffer buf = new GrowableByteBuffer(); - addAnnotations(); - build(buf); - return buf.bytes(); - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/MethodBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/MethodBuilder.java deleted file mode 100644 index ee5945808f3..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/MethodBuilder.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import jdk.experimental.bytecode.CodeBuilder.JumpMode; - -import java.util.Iterator; -import java.util.function.Consumer; -import java.util.function.Function; - -public class MethodBuilder<S, T, E> extends MemberBuilder<S, T, E, MethodBuilder<S, T, E>> { - - S thisClass; - ParameterAnnotationsBuilder runtimeVisibleParameterAnnotations; - ParameterAnnotationsBuilder runtimeInvisibleParameterAnnotations; - - public MethodBuilder(S thisClass, CharSequence name, T type, PoolHelper<S, T, E> pool, TypeHelper<S, T> typeHelper) { - super(name, type, pool, typeHelper); - this.thisClass = thisClass; - } - - public <C extends CodeBuilder<S, T, E, ?>> MethodBuilder<S, T, E> withCode(Function<? super MethodBuilder<S, T, E>, ? extends C> func, - Consumer<? super C> code) { - C codeBuilder = func.apply(this); - int start = attributes.offset; - try { - code.accept(codeBuilder); - } catch (MacroCodeBuilder.WideJumpException ex) { - //wide jumps! Redo the code - ((MacroCodeBuilder<S, T, E, ?>) codeBuilder).jumpMode = JumpMode.WIDE; - ((MacroCodeBuilder<S, T, E, ?>) codeBuilder).clear(); - code.accept(codeBuilder); - } - - attributes.writeChar(poolHelper.putUtf8("Code")); - attributes.writeInt(0); - codeBuilder.build(attributes); - int length = attributes.offset - start; - //avoid using lambda here - int prevOffset = attributes.offset; - try { - attributes.offset = start + 2; - attributes.writeInt(length - 6); - } finally { - attributes.offset = prevOffset; - } - nattrs++; - return this; - } - - public MethodBuilder<S, T, E> withCode(Consumer<? super CodeBuilder<S, T, E, ?>> code) { - return withCode(CodeBuilder::new, code); - } - - @SuppressWarnings({"varargs", "unchecked"}) - public MethodBuilder<S, T, E> withExceptions(S... exceptions) { - attributes.writeChar(poolHelper.putUtf8("Exceptions")); - attributes.writeInt(2 + (2 * exceptions.length)); - attributes.writeChar(exceptions.length); - for (S exception : exceptions) { - attributes.writeChar(poolHelper.putClass(exception)); - } - nattrs++; - return this; - } - - public MethodBuilder<S, T, E> withParameterAnnotation(AnnotationsBuilder.Kind kind, int nparam, T annoType) { - getParameterAnnotations(kind).builders[nparam].withAnnotation(annoType, null); - return this; - } - - public MethodBuilder<S, T, E> withParameterAnnotation(AnnotationsBuilder.Kind kind, int nparam, T annoType, Consumer<? super AnnotationsBuilder<S, T, E>.AnnotationElementBuilder> annotations) { - getParameterAnnotations(kind).builders[nparam].withAnnotation(annoType, annotations); - return this; - } - - private ParameterAnnotationsBuilder getParameterAnnotations(AnnotationsBuilder.Kind kind) { - switch (kind) { - case RUNTIME_INVISIBLE: - if (runtimeInvisibleParameterAnnotations == null) { - runtimeInvisibleParameterAnnotations = new ParameterAnnotationsBuilder(); - } - return runtimeInvisibleParameterAnnotations; - case RUNTIME_VISIBLE: - if (runtimeVisibleParameterAnnotations == null) { - runtimeVisibleParameterAnnotations = new ParameterAnnotationsBuilder(); - } - return runtimeVisibleParameterAnnotations; - } - throw new IllegalStateException(); - } - - class ParameterAnnotationsBuilder { - - GrowableByteBuffer parameterAnnos = new GrowableByteBuffer(); - - @SuppressWarnings({"unchecked", "rawtypes"}) - AnnotationsBuilder<S, T, E>[] builders = new AnnotationsBuilder[nparams()]; - - ParameterAnnotationsBuilder() { - for (int i = 0; i < builders.length; i++) { - builders[i] = new AnnotationsBuilder<>(poolHelper, typeHelper); - } - } - - byte[] build() { - parameterAnnos.writeByte(builders.length); - for (AnnotationsBuilder<S, T, E> builder : builders) { - parameterAnnos.writeBytes(builder.build()); - } - return parameterAnnos.bytes(); - } - - int nparams() { - Iterator<T> paramsIt = typeHelper.parameterTypes(desc); - int nparams = 0; - while (paramsIt.hasNext()) { - paramsIt.next(); - nparams++; - } - return nparams; - } - } - - @Override - void addAnnotations() { - super.addAnnotations(); - if (runtimeInvisibleParameterAnnotations != null) { - withAttribute("RuntimeInvisibleParameterAnnotations", runtimeInvisibleParameterAnnotations.build()); - } - if (runtimeVisibleParameterAnnotations != null) { - withAttribute("RuntimeVisibleParameterAnnotations", runtimeVisibleParameterAnnotations.build()); - } - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/Opcode.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/Opcode.java deleted file mode 100644 index d3fa013e650..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/Opcode.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import jdk.experimental.bytecode.MacroCodeBuilder.CondKind; - -public enum Opcode { - - NOP(0), - ACONST_NULL(1), - ICONST_M1(2), - ICONST_0(3), - ICONST_1(4), - ICONST_2(5), - ICONST_3(6), - ICONST_4(7), - ICONST_5(8), - LCONST_0(9), - LCONST_1(10), - FCONST_0(11), - FCONST_1(12), - FCONST_2(13), - DCONST_0(14), - DCONST_1(15), - BIPUSH(16), - SIPUSH(17), - LDC(18), - LDC_W(19), - LDC2_W(20), - ILOAD(21), - LLOAD(22), - FLOAD(23), - DLOAD(24), - ALOAD(25), - ILOAD_0(26), - ILOAD_1(27), - ILOAD_2(28), - ILOAD_3(29), - LLOAD_0(30), - LLOAD_1(31), - LLOAD_2(32), - LLOAD_3(33), - FLOAD_0(34), - FLOAD_1(35), - FLOAD_2(36), - FLOAD_3(37), - DLOAD_0(38), - DLOAD_1(39), - DLOAD_2(40), - DLOAD_3(41), - ALOAD_0(42), - ALOAD_1(43), - ALOAD_2(44), - ALOAD_3(45), - IALOAD(46), - LALOAD(47), - FALOAD(48), - DALOAD(49), - AALOAD(50), - BALOAD(51), - CALOAD(52), - SALOAD(53), - ISTORE(54), - LSTORE(55), - FSTORE(56), - DSTORE(57), - ASTORE(58), - ISTORE_0(59), - ISTORE_1(60), - ISTORE_2(61), - ISTORE_3(62), - LSTORE_0(63), - LSTORE_1(64), - LSTORE_2(65), - LSTORE_3(66), - FSTORE_0(67), - FSTORE_1(68), - FSTORE_2(69), - FSTORE_3(70), - DSTORE_0(71), - DSTORE_1(72), - DSTORE_2(73), - DSTORE_3(74), - ASTORE_0(75), - ASTORE_1(76), - ASTORE_2(77), - ASTORE_3(78), - IASTORE(79), - LASTORE(80), - FASTORE(81), - DASTORE(82), - AASTORE(83), - BASTORE(84), - CASTORE(85), - SASTORE(86), - POP(87), - POP2(88), - DUP(89), - DUP_X1(90), - DUP_X2(91), - DUP2(92), - DUP2_X1(93), - DUP2_X2(94), - SWAP(95), - IADD(96), - LADD(97), - FADD(98), - DADD(99), - ISUB(100), - LSUB(101), - FSUB(102), - DSUB(103), - IMUL(104), - LMUL(105), - FMUL(106), - DMUL(107), - IDIV(108), - LDIV(109), - FDIV(110), - DDIV(111), - IREM(112), - LREM(113), - FREM(114), - DREM(115), - INEG(116), - LNEG(117), - FNEG(118), - DNEG(119), - ISHL(120), - LSHL(121), - ISHR(122), - LSHR(123), - IUSHR(124), - LUSHR(125), - IAND(126), - LAND(127), - IOR(128), - LOR(129), - IXOR(130), - LXOR(131), - IINC(132), - I2L(133), - I2F(134), - I2D(135), - L2I(136), - L2F(137), - L2D(138), - F2I(139), - F2L(140), - F2D(141), - D2I(142), - D2L(143), - D2F(144), - I2B(145), - I2C(146), - I2S(147), - LCMP(148), - FCMPL(149), - FCMPG(150), - DCMPL(151), - DCMPG(152), - IFEQ(153), - IFNE(154), - IFLT(155), - IFGE(156), - IFGT(157), - IFLE(158), - IF_ICMPEQ(159), - IF_ICMPNE(160), - IF_ICMPLT(161), - IF_ICMPGE(162), - IF_ICMPGT(163), - IF_ICMPLE(164), - IF_ACMPEQ(165), - IF_ACMPNE(166), - GOTO_(167), - JSR(168), - RET(169), - TABLESWITCH(170), - LOOKUPSWITCH(171), - IRETURN(172), - LRETURN(173), - FRETURN(174), - DRETURN(175), - ARETURN(176), - RETURN(177), - GETSTATIC(178), - PUTSTATIC(179), - GETFIELD(180), - PUTFIELD(181), - INVOKEVIRTUAL(182), - INVOKESPECIAL(183), - INVOKESTATIC(184), - INVOKEINTERFACE(185), - INVOKEDYNAMIC(186), - NEW(187), - NEWARRAY(188), - ANEWARRAY(189), - ARRAYLENGTH(190), - ATHROW(191), - CHECKCAST(192), - INSTANCEOF(193), - MONITORENTER(194), - MONITOREXIT(195), - WIDE(196), - MULTIANEWARRAY(197), - IF_NULL(198), - IF_NONNULL(199), - GOTO_W(200), - JSR_W(201), - VLOAD(203), - VSTORE(204), - VALOAD(205), - VASTORE(206), - VNEW(207), - VNEWARRAY(208), - MULTIVNEWARRAY(209), - VRETURN(210), - VGETFIELD(211), - TYPED(212), - VBOX(216), - VUNBOX(217); - - int code; - - Opcode(int code) { - this.code = code; - } - - protected Opcode at(TypeTag type) { - return at(type, 1); - } - - protected Opcode at(CondKind cond) { - return at(cond.offset, 1); - } - - protected Opcode at(TypeTag type, int multiplier) { - return at(type.offset, multiplier); - } - - private Opcode at(int offset, int multiplier) { - if (offset < 0) throw new AssertionError(); - return Opcode.values()[code + (multiplier * offset)]; - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/PoolHelper.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/PoolHelper.java deleted file mode 100644 index d85579635e1..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/PoolHelper.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.function.Consumer; -import java.util.function.ToIntBiFunction; - -/** - * An interface for building and tracking constant pools. - * - * @param <S> the type of the symbol representation - * @param <T> the type of type descriptors representation - * @param <E> the type of pool entries - */ -public interface PoolHelper<S, T, E> { - int putClass(S symbol); - - int putFieldRef(S owner, CharSequence name, T type); - - int putMethodRef(S owner, CharSequence name, T type, boolean isInterface); - - int putUtf8(CharSequence s); - - int putInt(int i); - - int putFloat(float f); - - int putLong(long l); - - int putDouble(double d); - - int putString(String s); - - int putType(T t); - - int putMethodType(T t); - - int putHandle(int refKind, S owner, CharSequence name, T type); - - int putHandle(int refKind, S owner, CharSequence name, T type, boolean isInterface); - - int putInvokeDynamic(CharSequence invokedName, T invokedType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, E>> staticArgs); - - int putDynamicConstant(CharSequence constName, T constType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, E>> staticArgs); - - int size(); - - E entries(); - - interface StaticArgListBuilder<S, T, E> { - StaticArgListBuilder<S, T, E> add(int i); - StaticArgListBuilder<S, T, E> add(float f); - StaticArgListBuilder<S, T, E> add(long l); - StaticArgListBuilder<S, T, E> add(double d); - StaticArgListBuilder<S, T, E> add(String s); - StaticArgListBuilder<S, T, E> add(int refKind, S owner, CharSequence name, T type); - <Z> StaticArgListBuilder<S, T, E> add(Z z, ToIntBiFunction<PoolHelper<S, T, E>, Z> poolFunc); - StaticArgListBuilder<S, T, E> add(CharSequence constName, T constType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, E>> staticArgList); - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/PoolTag.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/PoolTag.java deleted file mode 100644 index bb60e42fb6f..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/PoolTag.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -public enum PoolTag { - CONSTANT_UTF8(1), - CONSTANT_UNICODE(2), - CONSTANT_INTEGER(3), - CONSTANT_FLOAT(4), - CONSTANT_LONG(5), - CONSTANT_DOUBLE(6), - CONSTANT_CLASS(7), - CONSTANT_STRING(8), - CONSTANT_FIELDREF(9), - CONSTANT_METHODREF(10), - CONSTANT_INTERFACEMETHODREF(11), - CONSTANT_NAMEANDTYPE(12), - CONSTANT_METHODHANDLE(15), - CONSTANT_METHODTYPE(16), - CONSTANT_DYNAMIC(17), - CONSTANT_INVOKEDYNAMIC(18); - - public final int tag; - - PoolTag(int tag) { - this.tag = tag; - } - - static PoolTag from(int tag) { - return values()[tag - 1]; - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/Type.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/Type.java deleted file mode 100644 index cacc3f81dc6..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/Type.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -public interface Type { - TypeTag getTag(); -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/TypeHelper.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/TypeHelper.java deleted file mode 100644 index fedb6043209..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/TypeHelper.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.Iterator; - -/** - * Helper to create and manipulate type descriptors of T. - * - * @param <S> the type of symbols - * @param <T> the type of type descriptors - */ -public interface TypeHelper<S, T> { - /** - * Return the type descriptor of an element given the type - * descriptor of an array. - * - * @param t the type descriptor of the array - * @return the element type - */ - T elemtype(T t); - - /** - * Return the type descriptor of an array given the type descriptor - * of an element. - * - * @param t the type descriptor of the element - * @return the type descriptor of the array - */ - T arrayOf(T t); - - /** - * Return an iterator over the type descriptors of the parameters of a - * method. - * - * @param t the method type descriptor - * @return an iterator over the type descriptors of the parameters - */ - Iterator<T> parameterTypes(T t); - - /** - * Return the type descriptor of a {@code TypeTag}. - * - * @param tag the {@code TypeTag} of a primitive type - * @return the type descriptor of the primitive type - */ - T fromTag(TypeTag tag); - - /** - * Return the return type descriptor of a method. - * - * @param t the method type descriptor - * @return the return type descriptor - */ - T returnType(T t); - - /** - * Return the type descriptor for a symbol. - * - * @param s the symbol - * @return the type descriptor - */ - T type(S s); - - /** - * Return the symbol corresponding to a type descriptor. - * - * @param type the type descriptor - * @return the symbol - */ - S symbol(T type); - - /** - * Return the {@code TypeTag} corresponding to a type descriptor. Reference - * types return {@code TypeTag.A}. - * - * @param t a type descriptor - * @return the corresponding {@code TypeTag} - */ - TypeTag tag(T t); - - /** - * Return the symbol corresponding to a JVM type descriptor string. - * - * @param s a JVM type descriptor string - * @return the corresponding symbol - */ - S symbolFrom(String s); - - /** - * Return the common supertype descriptor of two type descriptors. - * - * @param t1 a type descriptor - * @param t2 a type descriptor - * @return the common supertype descriptor - */ - T commonSupertype(T t1, T t2); - - /** - * Return the type descriptor for the null type. - * - * @return the type descriptor for the null type - */ - T nullType(); -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/TypeTag.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/TypeTag.java deleted file mode 100644 index 52f4f6cfe84..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/TypeTag.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -public enum TypeTag implements Type { - /** - * byte - */ - B("B", 0, 1, 8), - /** - * short - */ - S("S", 0, 1, 9), - /** - * int - */ - I("I", 0, 1, 10), - /** - * float - */ - F("F", 2, 1, 6), - /** - * long - */ - J("J", 1, 2, 11), - /** - * double - */ - D("D", 3, 2, 7), - /** - * Reference type - */ - A("A", 4, 1, -1), - /** - * char - */ - C("C", 0, 1, 5), - /** - * boolean - */ - Z("Z", 0, 1, 4), - /** - * void - */ - V("V", -1, -1, -1), - /** - * Value type - */ - Q("Q", -1, 1, -1); - - String typeStr; - int offset; - int width; - int newarraycode; - - TypeTag(String typeStr, int offset, int width, int newarraycode) { - this.typeStr = typeStr; - this.offset = offset; - this.width = width; - this.newarraycode = newarraycode; - } - - static TypeTag commonSupertype(TypeTag t1, TypeTag t2) { - if (t1.isIntegral() && t2.isIntegral()) { - int p1 = t1.ordinal(); - int p2 = t2.ordinal(); - return (p1 <= p2) ? t2 : t1; - } else { - return null; - } - } - - public int width() { - return width; - } - - boolean isIntegral() { - switch (this) { - case B: - case S: - case I: - return true; - default: - return false; - } - } - - @Override - public TypeTag getTag() { - return this; - } -} diff --git a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/TypedCodeBuilder.java b/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/TypedCodeBuilder.java deleted file mode 100644 index dc82ad67af3..00000000000 --- a/test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/TypedCodeBuilder.java +++ /dev/null @@ -1,1221 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -package jdk.experimental.bytecode; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Vector; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.function.ToIntFunction; - -public class TypedCodeBuilder<S, T, E, C extends TypedCodeBuilder<S, T, E, C>> extends MacroCodeBuilder<S, T, E, C> { - - State lastStackMapState; - int lastStackMapPc = -1; - Map<CharSequence, LocalVarInfo> lvarOffsets = new HashMap<>(); - protected State state; - int depth = 0; - int currLocalOffset = 0; - - class StatefulPendingJump extends PendingJump { - - State state; - - StatefulPendingJump(CharSequence label, int pc, State state) { - super(label, pc); - this.state = state; - } - - @Override - boolean resolve(CharSequence label, int pc) { - boolean b = super.resolve(label, pc); - if (b) { - TypedCodeBuilder.this.state = TypedCodeBuilder.this.state.merge(state); - } - return b; - } - } - - class LocalVarInfo { - CharSequence name; - int offset; - int depth; - TypeTag type; - - LocalVarInfo(CharSequence name, int offset, int depth, TypeTag type) { - this.name = name; - this.offset = offset; - this.depth = depth; - this.type = type; - } - } - - public TypedCodeBuilder(MethodBuilder<S, T, E> methodBuilder) { - super(methodBuilder); - T t = methodBuilder.desc; - state = new State(); - if ((methodBuilder.flags & Flag.ACC_STATIC.flag) == 0) { - T clazz = typeHelper.type(methodBuilder.thisClass); - state.load(clazz, currLocalOffset++); //TODO: uninit?? - } - Iterator<T> paramsIt = typeHelper.parameterTypes(t); - while (paramsIt.hasNext()) { - T p = paramsIt.next(); - state.load(p, currLocalOffset); - currLocalOffset += typeHelper.tag(p).width; - } - lastStackMapState = state.dup(); - stacksize = state.stack.size(); - localsize = state.locals.size(); - } - - @Override - protected C emitOp(Opcode opcode, Object optPoolValue) { - updateState(opcode, optPoolValue); - return super.emitOp(opcode, optPoolValue); - } - - @Override - protected SwitchBuilder makeSwitchBuilder() { - return new TypedSwitchBuilder(); - } - - class TypedSwitchBuilder extends SwitchBuilder { - - @Override - public SwitchBuilder withCase(int value, Consumer<? super C> case_, boolean fallthrough) { - super.withCase(value, c -> { - withLocalScope(() -> { - State prevState = state; - state = prevState.dup(); - emitStackMap(c.offset()); - case_.accept(c); - state = prevState; - }); - }, fallthrough); - return this; - } - - @Override - public SwitchBuilder withDefault(Consumer<? super C> defaultCase) { - super.withDefault(c -> { - withLocalScope(() -> { - State prevState = state; - state = prevState.dup(); - emitStackMap(c.offset()); - defaultCase.accept(c); - state = prevState; - }); - }); - return this; - } - } - - @Override - public StatefulTypedBuilder typed(TypeTag tag) { - return super.typed(tag, StatefulTypedBuilder::new); - } - - public class StatefulTypedBuilder extends LabelledTypedBuilder { - - TypeTag tag; - - StatefulTypedBuilder(TypeTag tag) { - this.tag = tag; - } - - @Override - public C astore_0() { - return storeAndUpdate(super::astore_0); - } - - @Override - public C astore_1() { - return storeAndUpdate(super::astore_1); - } - - @Override - public C astore_2() { - return storeAndUpdate(super::astore_2); - } - - @Override - public C astore_3() { - return storeAndUpdate(super::astore_3); - } - - @Override - public C astore(int n) { - return storeAndUpdate(() -> super.astore(n)); - } - - @Override - public C aastore() { - return storeAndUpdate(super::aastore); - } - - @Override - public C areturn() { - state.pop(tag); - state.push(typeHelper.nullType()); - return super.areturn(); - } - - @Override - public C anewarray(S s) { - super.anewarray(s); - state.pop(); - state.push(typeHelper.arrayOf(typeHelper.type(s))); - return thisBuilder(); - } - - @Override - public C aconst_null() { - super.aconst_null(); - state.pop(); - state.push(tag); - return thisBuilder(); - } - - public C if_acmpeq(CharSequence label) { - return jumpAndUpdate(() -> super.if_acmpeq(label)); - } - - public C if_acmpne(CharSequence label) { - return jumpAndUpdate(() -> super.if_acmpne(label)); - } - - private C storeAndUpdate(Supplier<C> op) { - state.pop(tag); - state.push(typeHelper.nullType()); - return op.get(); - } - - private C jumpAndUpdate(Supplier<C> op) { - state.pop(tag); - state.pop(tag); - state.push(typeHelper.nullType()); - state.push(typeHelper.nullType()); - return op.get(); - } - } - - public class State { - public final ArrayList<T> stack; - public final Vector<T> locals; - boolean alive; - - State(ArrayList<T> stack, Vector<T> locals) { - this.stack = stack; - this.locals = locals; - } - - State() { - this(new ArrayList<>(), new Vector<>()); - } - - void push(TypeTag tag) { - switch (tag) { - case A: - case V: - throw new IllegalStateException("Bad type tag"); - default: - push(typeHelper.fromTag(tag)); - } - } - - void push(T t) { - stack.add(t); - if (width(t) == 2) { - stack.add(null); - } - if (stack.size() > stacksize) { - stacksize = stack.size(); - } - } - - T peek() { - return stack.get(stack.size() - 1); - } - - T tosType() { - T tos = peek(); - if (tos == null) { - //double slot - tos = stack.get(stack.size() - 2); - } - return tos; - } - - T popInternal() { - return stack.remove(stack.size() - 1); - } - - @SuppressWarnings("unchecked") - T pop() { - if (stack.size() == 0 || peek() == null) throw new IllegalStateException(); - return popInternal(); - } - - T pop2() { - T o = stack.get(stack.size() - 2); - TypeTag t = typeHelper.tag(o); - if (t.width != 2) throw new IllegalStateException(); - popInternal(); - popInternal(); - return o; - } - - T pop(TypeTag t) { - return (t.width() == 2) ? - pop2() : pop(); - } - - void load(TypeTag tag, int index) { - if (tag == TypeTag.A) throw new IllegalStateException("Bad type tag"); - load(typeHelper.fromTag(tag), index); - } - - void load(T t, int index) { - ensureDefined(index); - locals.set(index, t); - if (width(t) == 2) { - locals.add(null); - } - if (locals.size() > localsize) { - localsize = locals.size(); - } - } - - void ensureDefined(int index) { - if (index >= locals.size()) { - locals.setSize(index + 1); - } - } - - State dup() { - State newState = new State(new ArrayList<>(stack), new Vector<>(locals)); - return newState; - } - - State merge(State that) { - if (!alive) { return that; } - if (that.stack.size() != stack.size()) { - throw new IllegalStateException("Bad stack size at merge point"); - } - for (int i = 0; i < stack.size(); i++) { - T t1 = stack.get(i); - T t2 = that.stack.get(i); - stack.set(i, merge(t1, t2, "Bad stack type at merge point")); - } - int nlocals = locals.size() > that.locals.size() ? that.locals.size() : locals.size(); - for (int i = 0; i < nlocals; i++) { - T t1 = locals.get(i); - T t2 = that.locals.get(i); - locals.set(i, merge(t1, t2, "Bad local type at merge point")); - } - if (locals.size() > nlocals) { - for (int i = nlocals; i < locals.size(); i++) { - locals.remove(i); - } - } - return this; - } - - T merge(T t1, T t2, String msg) { - if (t1 == null && t2 == null) { - return t1; - } - T res; - TypeTag tag1 = typeHelper.tag(t1); - TypeTag tag2 = typeHelper.tag(t2); - if (tag1 != TypeTag.A && tag2 != TypeTag.A && - tag1 != TypeTag.Q && tag2 != TypeTag.Q) { - res = typeHelper.fromTag(TypeTag.commonSupertype(tag1, tag2)); - } else if (t1 == typeHelper.nullType()) { - res = t2; - } else if (t2 == typeHelper.nullType()) { - res = t1; - } else { - res = typeHelper.commonSupertype(t1, t2); - } - if (res == null) { - throw new IllegalStateException(msg); - } - return res; - } - - @Override - public String toString() { - return String.format("[locals = %s, stack = %s]", locals, stack); - } - } - - int width(T o) { - return o == typeHelper.nullType() ? - TypeTag.A.width() : - typeHelper.tag(o).width; - } - - @SuppressWarnings("unchecked") - public void updateState(Opcode op, Object optValue) { - switch (op) { - case VALOAD: - case AALOAD: - state.pop(); - state.push(typeHelper.elemtype(state.pop())); - break; - case GOTO_: - state.alive = false; - break; - case NOP: - case INEG: - case LNEG: - case FNEG: - case DNEG: - break; - case ACONST_NULL: - state.push(typeHelper.nullType()); - break; - case ICONST_M1: - case ICONST_0: - case ICONST_1: - case ICONST_2: - case ICONST_3: - case ICONST_4: - case ICONST_5: - state.push(TypeTag.I); - break; - case LCONST_0: - case LCONST_1: - state.push(TypeTag.J); - break; - case FCONST_0: - case FCONST_1: - case FCONST_2: - state.push(TypeTag.F); - break; - case DCONST_0: - case DCONST_1: - state.push(TypeTag.D); - break; - case ILOAD_0: - case FLOAD_0: - case ALOAD_0: - case LLOAD_0: - case DLOAD_0: - state.push(state.locals.get(0)); - break; - case ILOAD_1: - case FLOAD_1: - case ALOAD_1: - case LLOAD_1: - case DLOAD_1: - state.push(state.locals.get(1)); - break; - case ILOAD_2: - case FLOAD_2: - case ALOAD_2: - case LLOAD_2: - case DLOAD_2: - state.push(state.locals.get(2)); - break; - case ILOAD_3: - case FLOAD_3: - case ALOAD_3: - case LLOAD_3: - case DLOAD_3: - state.push(state.locals.get(3)); - break; - case ILOAD: - case FLOAD: - case ALOAD: - case LLOAD: - case DLOAD: - case VLOAD: - state.push(state.locals.get((Integer) optValue)); - break; - case IALOAD: - case BALOAD: - case CALOAD: - case SALOAD: - state.pop(); - state.pop(); - state.push(TypeTag.I); - break; - case LALOAD: - state.pop(); - state.pop(); - state.push(TypeTag.J); - break; - case FALOAD: - state.pop(); - state.pop(); - state.push(TypeTag.F); - break; - case DALOAD: - state.pop(); - state.pop(); - state.push(TypeTag.D); - break; - case ISTORE_0: - case FSTORE_0: - case ASTORE_0: - state.load(state.pop(), 0); - break; - case ISTORE_1: - case FSTORE_1: - case ASTORE_1: - state.load(state.pop(), 1); - break; - case ISTORE_2: - case FSTORE_2: - case ASTORE_2: - state.load(state.pop(), 2); - break; - case ISTORE_3: - case FSTORE_3: - case ASTORE_3: - state.load(state.pop(), 3); - break; - case ISTORE: - case FSTORE: - case ASTORE: - case VSTORE: - state.load(state.pop(), (int) optValue); - break; - case LSTORE_0: - case DSTORE_0: - state.load(state.pop2(), 0); - break; - case LSTORE_1: - case DSTORE_1: - state.load(state.pop2(), 1); - break; - case LSTORE_2: - case DSTORE_2: - state.load(state.pop2(), 2); - break; - case LSTORE_3: - case DSTORE_3: - state.load(state.pop2(), 3); - break; - case LSTORE: - case DSTORE: - state.load(state.pop2(), (int) optValue); - break; - case POP: - case LSHR: - case LSHL: - case LUSHR: - state.pop(); - break; - case VRETURN: - case ARETURN: - case IRETURN: - case FRETURN: - state.pop(); - break; - case ATHROW: - state.pop(); - break; - case POP2: - state.pop2(); - break; - case LRETURN: - case DRETURN: - state.pop2(); - break; - case DUP: - state.push(state.peek()); - break; - case RETURN: - break; - case ARRAYLENGTH: - state.pop(); - state.push(TypeTag.I); - break; - case ISUB: - case IADD: - case IMUL: - case IDIV: - case IREM: - case ISHL: - case ISHR: - case IUSHR: - case IAND: - case IOR: - case IXOR: - state.pop(); - state.pop(); - state.push(TypeTag.I); - break; - case VASTORE: - case AASTORE: - state.pop(); - state.pop(); - state.pop(); - break; - case LAND: - case LOR: - case LXOR: - case LREM: - case LDIV: - case LMUL: - case LSUB: - case LADD: - state.pop2(); - state.pop2(); - state.push(TypeTag.J); - break; - case LCMP: - state.pop2(); - state.pop2(); - state.push(TypeTag.I); - break; - case L2I: - state.pop2(); - state.push(TypeTag.I); - break; - case I2L: - state.pop(); - state.push(TypeTag.J); - break; - case I2F: - state.pop(); - state.push(TypeTag.F); - break; - case I2D: - state.pop(); - state.push(TypeTag.D); - break; - case L2F: - state.pop2(); - state.push(TypeTag.F); - break; - case L2D: - state.pop2(); - state.push(TypeTag.D); - break; - case F2I: - state.pop(); - state.push(TypeTag.I); - break; - case F2L: - state.pop(); - state.push(TypeTag.J); - break; - case F2D: - state.pop(); - state.push(TypeTag.D); - break; - case D2I: - state.pop2(); - state.push(TypeTag.I); - break; - case D2L: - state.pop2(); - state.push(TypeTag.J); - break; - case D2F: - state.pop2(); - state.push(TypeTag.F); - break; - case TABLESWITCH: - case LOOKUPSWITCH: - state.pop(); - break; - case DUP_X1: { - T val1 = state.pop(); - T val2 = state.pop(); - state.push(val1); - state.push(val2); - state.push(val1); - break; - } - case BASTORE: - state.pop(); - state.pop(); - state.pop(); - break; - case I2B: - case I2C: - case I2S: - break; - case FMUL: - case FADD: - case FSUB: - case FDIV: - case FREM: - state.pop(); - state.pop(); - state.push(TypeTag.F); - break; - case CASTORE: - case IASTORE: - case FASTORE: - case SASTORE: - state.pop(); - state.pop(); - state.pop(); - break; - case LASTORE: - case DASTORE: - state.pop2(); - state.pop(); - state.pop(); - break; - case DUP2: - if (state.peek() != null) { - //form 1 - T value1 = state.pop(); - T value2 = state.pop(); - state.push(value2); - state.push(value1); - state.push(value2); - state.push(value1); - } else { - //form 2 - T value = state.pop2(); - state.push(value); - state.push(value); - } - break; - case DUP2_X1: - if (state.peek() != null) { - T value1 = state.pop(); - T value2 = state.pop(); - T value3 = state.pop(); - state.push(value2); - state.push(value1); - state.push(value3); - state.push(value2); - state.push(value1); - } else { - T value1 = state.pop2(); - T value2 = state.pop(); - state.push(value1); - state.push(value2); - state.push(value1); - } - break; - case DUP2_X2: - if (state.peek() != null) { - T value1 = state.pop(); - T value2 = state.pop(); - if (state.peek() != null) { - // form 1 - T value3 = state.pop(); - T value4 = state.pop(); - state.push(value2); - state.push(value1); - state.push(value4); - state.push(value3); - state.push(value2); - state.push(value1); - } else { - // form 3 - T value3 = state.pop2(); - state.push(value2); - state.push(value1); - state.push(value3); - state.push(value2); - state.push(value1); - } - } else { - T value1 = state.pop2(); - if (state.peek() != null) { - // form 2 - T value2 = state.pop(); - T value3 = state.pop(); - state.push(value1); - state.push(value3); - state.push(value2); - state.push(value1); - } else { - // form 4 - T value2 = state.pop2(); - state.push(value1); - state.push(value2); - state.push(value1); - } - } - break; - case DUP_X2: { - T value1 = state.pop(); - if (state.peek() != null) { - // form 1 - T value2 = state.pop(); - T value3 = state.pop(); - state.push(value1); - state.push(value3); - state.push(value2); - state.push(value1); - } else { - // form 2 - T value2 = state.pop2(); - state.push(value1); - state.push(value2); - state.push(value1); - } - } - break; - case FCMPL: - case FCMPG: - state.pop(); - state.pop(); - state.push(TypeTag.I); - break; - case DCMPL: - case DCMPG: - state.pop2(); - state.pop2(); - state.push(TypeTag.I); - break; - case SWAP: { - T value1 = state.pop(); - T value2 = state.pop(); - state.push(value1); - state.push(value2); - break; - } - case DADD: - case DSUB: - case DMUL: - case DDIV: - case DREM: - state.pop2(); - state.pop2(); - state.push(TypeTag.D); - break; - case RET: - break; - case WIDE: - // must be handled by the caller. - return; - case MONITORENTER: - case MONITOREXIT: - state.pop(); - break; - case VNEW: - case NEW: - state.push(typeHelper.type((S) optValue)); - break; - case NEWARRAY: - state.pop(); - state.push(typeHelper.arrayOf(typeHelper.fromTag((TypeTag) optValue))); - break; - case ANEWARRAY: - state.pop(); - state.push(typeHelper.arrayOf(typeHelper.arrayOf(typeHelper.type((S)optValue)))); - break; - case VNEWARRAY: - case VBOX: - case VUNBOX: - state.pop(); - state.push(typeHelper.type((S) optValue)); - break; - case MULTIVNEWARRAY: - case MULTIANEWARRAY: - for (int i = 0; i < (byte) ((Object[]) optValue)[1]; i++) { - state.pop(); - } - state.push(typeHelper.type((S) ((Object[]) optValue)[0])); - break; - case INVOKEINTERFACE: - case INVOKEVIRTUAL: - case INVOKESPECIAL: - case INVOKESTATIC: - case INVOKEDYNAMIC: - processInvoke(op, (T) optValue); - break; - case GETSTATIC: - state.push((T) optValue); - break; - case VGETFIELD: - case GETFIELD: - state.pop(); - state.push((T) optValue); - break; - case PUTSTATIC: { - TypeTag tag = typeHelper.tag((T) optValue); - if (tag.width == 1) { - state.pop(); - } else { - state.pop2(); - } - break; - } - case PUTFIELD: { - TypeTag tag = typeHelper.tag((T) optValue); - if (tag.width == 1) { - state.pop(); - } else { - state.pop2(); - } - state.pop(); - break; - } - case BIPUSH: - case SIPUSH: - state.push(TypeTag.I); - break; - case LDC: - case LDC_W: - case LDC2_W: - state.push((T)optValue); - break; - case IF_ACMPEQ: - case IF_ICMPEQ: - case IF_ACMPNE: - case IF_ICMPGE: - case IF_ICMPGT: - case IF_ICMPLE: - case IF_ICMPLT: - case IF_ICMPNE: - state.pop(); - state.pop(); - break; - case IF_NONNULL: - case IF_NULL: - case IFEQ: - case IFGE: - case IFGT: - case IFLE: - case IFLT: - case IFNE: - state.pop(); - break; - case INSTANCEOF: - state.pop(); - state.push(TypeTag.Z); - break; - case TYPED: - case CHECKCAST: - break; - - default: - throw new UnsupportedOperationException("Unsupported opcode: " + op); - } - } - - void processInvoke(Opcode opcode, T invokedType) { - Iterator<T> paramsIt = typeHelper.parameterTypes(invokedType); - while (paramsIt.hasNext()) { - T t = paramsIt.next(); - TypeTag tag = typeHelper.tag(t); - if (tag.width == 2) { - state.popInternal(); - state.popInternal(); - } else { - state.popInternal(); - } - } - if (opcode != Opcode.INVOKESTATIC && opcode != Opcode.INVOKEDYNAMIC) { - state.pop(); //receiver - } - T retType = typeHelper.returnType(invokedType); - TypeTag retTag = typeHelper.tag(retType); - if (retTag != TypeTag.V) - state.push(retType); - } - - @Override - protected C ldc(ToIntFunction<PoolHelper<S, T, E>> indexFunc, boolean fat) { - LdcPoolHelper ldcPoolHelper = new LdcPoolHelper(); - int index = indexFunc.applyAsInt(ldcPoolHelper); - fat = typeHelper.tag(ldcPoolHelper.type).width() == 2; - return super.ldc(index, ldcPoolHelper.type, fat); - } - //where - class LdcPoolHelper implements PoolHelper<S, T, E> { - - T type; - - @Override - public int putClass(S symbol) { - type = typeHelper.type(symbol); - return poolHelper.putClass(symbol); - } - - @Override - public int putInt(int i) { - type = typeHelper.fromTag(TypeTag.I); - return poolHelper.putInt(i); - } - - @Override - public int putFloat(float f) { - type = typeHelper.fromTag(TypeTag.F); - return poolHelper.putFloat(f); - } - - @Override - public int putLong(long l) { - type = typeHelper.fromTag(TypeTag.J); - return poolHelper.putLong(l); - } - - @Override - public int putDouble(double d) { - type = typeHelper.fromTag(TypeTag.D); - return poolHelper.putDouble(d); - } - - @Override - public int putString(String s) { - type = typeHelper.type(typeHelper.symbolFrom("java/lang/String")); - return poolHelper.putString(s); - } - - @Override - public int putDynamicConstant(CharSequence constName, T constType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, E>> staticArgs) { - type = constType; - return poolHelper.putDynamicConstant(constName, constType, bsmClass, bsmName, bsmType, staticArgs); - } - - @Override - public int putFieldRef(S owner, CharSequence name, T type) { - throw new IllegalStateException(); - } - - @Override - public int putMethodRef(S owner, CharSequence name, T type, boolean isInterface) { - throw new IllegalStateException(); - } - - @Override - public int putUtf8(CharSequence s) { - throw new IllegalStateException(); - } - - @Override - public int putType(T t) { - throw new IllegalStateException(); - } - - @Override - public int putMethodType(T t) { - type = typeHelper.type(typeHelper.symbolFrom("java/lang/invoke/MethodType")); - return poolHelper.putMethodType(t); - } - - @Override - public int putHandle(int refKind, S owner, CharSequence name, T t) { - type = typeHelper.type(typeHelper.symbolFrom("java/lang/invoke/MethodHandle")); - return poolHelper.putHandle(refKind, owner, name, t); - } - - @Override - public int putHandle(int refKind, S owner, CharSequence name, T t, boolean isInterface) { - type = typeHelper.type(typeHelper.symbolFrom("java/lang/invoke/MethodHandle")); - return poolHelper.putHandle(refKind, owner, name, t, isInterface); - } - - @Override - public int putInvokeDynamic(CharSequence invokedName, T invokedType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, E>> staticArgs) { - throw new IllegalStateException(); - } - - @Override - public int size() { - throw new IllegalStateException(); - } - - @Override - public E entries() { - throw new IllegalStateException(); - } - } - - public C load(int index) { - return load(typeHelper.tag(state.locals.get(index)), index); - } - - public C store(int index) { - return store(typeHelper.tag(state.tosType()), index); - } - - @Override - public C withLocalSize(int localsize) { - throw new IllegalStateException("Local size automatically computed"); - } - - @Override - public C withStackSize(int stacksize) { - throw new IllegalStateException("Stack size automatically computed"); - } - - public C withLocal(CharSequence name, T type) { - int offset = currLocalOffset; - TypeTag tag = typeHelper.tag(type); - lvarOffsets.put(name, new LocalVarInfo(name, offset, depth, tag)); - state.load(type, offset); - currLocalOffset += tag.width; - return thisBuilder(); - } - - public C load(CharSequence local) { - return load(lvarOffsets.get(local).offset); - } - - public C store(CharSequence local) { - return store(lvarOffsets.get(local).offset); - } - - @Override - public C withTry(Consumer<? super C> tryBlock, Consumer<? super CatchBuilder> catchBlocks) { - return super.withTry(c -> { - withLocalScope(() -> { - tryBlock.accept(c); - }); - }, catchBlocks); - } - - @Override - protected CatchBuilder makeCatchBuilder(int start, int end) { - return new TypedCatchBuilder(start, end); - } - - class TypedCatchBuilder extends CatchBuilder { - - State initialState = state.dup(); - - TypedCatchBuilder(int start, int end) { - super(start, end); - } - - @Override - protected void emitCatch(S exc, Consumer<? super C> catcher) { - withLocalScope(() -> { - state.push(typeHelper.type(exc)); - emitStackMap(code.offset); - super.emitCatch(exc, catcher); - state = initialState; - }); - } - - @Override - protected void emitFinalizer() { - withLocalScope(() -> { - state.push(typeHelper.type(typeHelper.symbolFrom("java/lang/Throwable"))); - emitStackMap(code.offset); - super.emitFinalizer(); - }); - } - } - - protected void withLocalScope(Runnable runnable) { - int prevDepth = depth; - try { - depth++; - runnable.run(); - } finally { - Iterator<Entry<CharSequence, LocalVarInfo>> lvarIt = lvarOffsets.entrySet().iterator(); - while (lvarIt.hasNext()) { - LocalVarInfo lvi = lvarIt.next().getValue(); - if (lvi.depth == depth) { - int width = lvi.type.width; - currLocalOffset -= width; - lvarIt.remove(); - } - } - depth = prevDepth; - } - } - - @Override - void addPendingJump(CharSequence label, int pc) { - pendingJumps.add(new StatefulPendingJump(label, pc, state.dup())); - } - - @Override - void resolveJumps(CharSequence label, int pc) { - super.resolveJumps(label, pc); - emitStackMap(pc); - } - - //TODO: optimize stackmap generation by avoiding intermediate classes - protected void emitStackMap(int pc) { - //stack map generation - if (pc > lastStackMapPc) { - writeStackMapFrame(pc); - lastStackMapState = state.dup(); - lastStackMapPc = pc; - nstackmaps++; - } - } - - @Override - void build(GrowableByteBuffer buf) { - if (stacksize == -1) { - throw new IllegalStateException("Bad stack size"); - } - if (localsize == -1) { - throw new IllegalStateException("Bad locals size"); - } - if (nstackmaps > 0) { - GrowableByteBuffer stackmapsAttr = new GrowableByteBuffer(); - stackmapsAttr.writeChar(nstackmaps); - stackmapsAttr.writeBytes(stackmaps); - withAttribute("StackMapTable", stackmapsAttr.bytes()); - } - super.build(buf); - } - - /** - * Compare this frame with the previous frame and produce - * an entry of compressed stack map frame. - */ - void writeStackMapFrame(int pc) { - List<T> locals = state.locals; - List<T> stack = state.stack; - List<T> prev_locals = lastStackMapState.locals; - int offset_delta = lastStackMapPc == -1 ? pc : pc - lastStackMapPc - 1; - if (stack.size() == 1) { - if (locals.size() == prev_locals.size() && prev_locals.equals(locals)) { - sameLocals1StackItemFrame(offset_delta, stack.get(stack.size() - 1)); - return; - } - } else if (stack.size() == 0) { - int diff_length = prev_locals.size() - locals.size(); - if (diff_length == 0) { - sameFrame(offset_delta); - return; - } else if (-MAX_LOCAL_LENGTH_DIFF < diff_length && diff_length < 0) { - appendFrame(offset_delta, prev_locals.size(), locals); - return; - } else if (0 < diff_length && diff_length < MAX_LOCAL_LENGTH_DIFF) { - chopFrame(offset_delta, diff_length); - return; - } - } - fullFrame(offset_delta, locals, stack); - } -}