< prev index next >

src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java

Print this page
rev 13971 : 8152641: Plugin to generate BMH$Species classes ahead-of-time
Reviewed-by: plevart, mchung, forax

*** 23,32 **** --- 23,33 ---- * questions. */ package java.lang.invoke; + import jdk.internal.loader.BootLoader; import jdk.internal.vm.annotation.Stable; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor; import sun.invoke.util.ValueConversions;
*** 487,497 **** // only once per key. return CLASS_CACHE.computeIfAbsent( types, new Function<String, Class<? extends BoundMethodHandle>>() { @Override public Class<? extends BoundMethodHandle> apply(String types) { ! return generateConcreteBMHClass(types); } }); } /** --- 488,506 ---- // only once per key. return CLASS_CACHE.computeIfAbsent( types, new Function<String, Class<? extends BoundMethodHandle>>() { @Override public Class<? extends BoundMethodHandle> apply(String types) { ! String shortTypes = LambdaForm.shortenSignature(types); ! Class<?> c = BootLoader.loadClassOrNull( ! "java.lang.invoke.BoundMethodHandle$Species_" + shortTypes); ! if (c != null) { ! return c.asSubclass(BoundMethodHandle.class); ! } else { ! // Not pregenerated, generate the class ! return generateConcreteBMHClass(shortTypes, types); ! } } }); } /**
*** 556,622 **** * </pre> * * @param types the type signature, wherein reference types are erased to 'L' * @return the generated concrete BMH class */ ! static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) { ! final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); ! ! String shortTypes = LambdaForm.shortenSignature(types); final String className = SPECIES_PREFIX_PATH + shortTypes; final String sourceFile = SPECIES_PREFIX_NAME + shortTypes; final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null); cw.visitSource(sourceFile, null); - // emit static types and SPECIES_DATA fields FieldVisitor fw = cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null); fw.visitAnnotation(STABLE_SIG, true); fw.visitEnd(); - // emit bound argument fields for (int i = 0; i < types.length(); ++i) { final char t = types.charAt(i); final String fieldName = makeFieldName(types, i); final String fieldDesc = t == 'L' ? JLO_SIG : String.valueOf(t); cw.visitField(ACC_FINAL, fieldName, fieldDesc, null, null).visitEnd(); } - MethodVisitor mv; - // emit constructor mv = cw.visitMethod(ACC_PRIVATE, "<init>", makeSignature(types, true), null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); // this mv.visitVarInsn(ALOAD, 1); // type mv.visitVarInsn(ALOAD, 2); // form - mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false); - for (int i = 0, j = 0; i < types.length(); ++i, ++j) { // i counts the arguments, j counts corresponding argument slots char t = types.charAt(i); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(typeLoadOp(t), j + 3); // parameters start at 3 mv.visitFieldInsn(PUTFIELD, className, makeFieldName(types, i), typeSig(t)); if (t == 'J' || t == 'D') { ++j; // adjust argument register access } } - mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); - // emit implementation of speciesData() mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null); mv.visitCode(); mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); - // emit implementation of fieldCount() mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "fieldCount", INT_SIG, null, null); mv.visitCode(); int fc = types.length(); if (fc <= (ICONST_5 - ICONST_0)) { --- 565,635 ---- * </pre> * * @param types the type signature, wherein reference types are erased to 'L' * @return the generated concrete BMH class */ ! static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String shortTypes, String types) { final String className = SPECIES_PREFIX_PATH + shortTypes; final String sourceFile = SPECIES_PREFIX_NAME + shortTypes; + + byte[] classFile = generateConcreteBMHClassBytes(className, sourceFile, types); + + // load class + InvokerBytecodeGenerator.maybeDump(className, classFile); + Class<? extends BoundMethodHandle> bmhClass = + //UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class); + UNSAFE.defineClass(className, classFile, 0, classFile.length, + BoundMethodHandle.class.getClassLoader(), null) + .asSubclass(BoundMethodHandle.class); + + return bmhClass; + } + + static byte[] generateConcreteBMHClassBytes(final String className, final String sourceFile, final String types) { + final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null); cw.visitSource(sourceFile, null); // emit static types and SPECIES_DATA fields FieldVisitor fw = cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null); fw.visitAnnotation(STABLE_SIG, true); fw.visitEnd(); // emit bound argument fields for (int i = 0; i < types.length(); ++i) { final char t = types.charAt(i); final String fieldName = makeFieldName(types, i); final String fieldDesc = t == 'L' ? JLO_SIG : String.valueOf(t); cw.visitField(ACC_FINAL, fieldName, fieldDesc, null, null).visitEnd(); } MethodVisitor mv; // emit constructor mv = cw.visitMethod(ACC_PRIVATE, "<init>", makeSignature(types, true), null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); // this mv.visitVarInsn(ALOAD, 1); // type mv.visitVarInsn(ALOAD, 2); // form mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false); for (int i = 0, j = 0; i < types.length(); ++i, ++j) { // i counts the arguments, j counts corresponding argument slots char t = types.charAt(i); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(typeLoadOp(t), j + 3); // parameters start at 3 mv.visitFieldInsn(PUTFIELD, className, makeFieldName(types, i), typeSig(t)); if (t == 'J' || t == 'D') { ++j; // adjust argument register access } } mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); // emit implementation of speciesData() mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null); mv.visitCode(); mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); // emit implementation of fieldCount() mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "fieldCount", INT_SIG, null, null); mv.visitCode(); int fc = types.length(); if (fc <= (ICONST_5 - ICONST_0)) {
*** 643,659 **** mv.visitVarInsn(typeLoadOp(t), j + 2); // parameters start at 3 if (t == 'J' || t == 'D') { ++j; // adjust argument register access } } - // finally, invoke the constructor and return mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); - // emit copyWith() mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWith", makeSignature("", false), null, null); mv.visitCode(); // make instance mv.visitTypeInsn(NEW, className); --- 656,670 ----
*** 666,676 **** // finally, invoke the constructor and return mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); - // for each type, emit copyWithExtendT() for (BasicType type : BasicType.ARG_TYPES) { int ord = type.ordinal(); char btChar = type.basicTypeChar(); mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE); --- 677,686 ----
*** 694,716 **** mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + btChar, false), false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } - cw.visitEnd(); ! ! // load class ! final byte[] classFile = cw.toByteArray(); ! InvokerBytecodeGenerator.maybeDump(className, classFile); ! Class<? extends BoundMethodHandle> bmhClass = ! //UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class); ! UNSAFE.defineClass(className, classFile, 0, classFile.length, ! BoundMethodHandle.class.getClassLoader(), null) ! .asSubclass(BoundMethodHandle.class); ! ! return bmhClass; } private static int typeLoadOp(char t) { switch (t) { case 'L': return ALOAD; --- 704,715 ---- mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + btChar, false), false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } cw.visitEnd(); ! return cw.toByteArray(); } private static int typeLoadOp(char t) { switch (t) { case 'L': return ALOAD;
< prev index next >