48 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeSpecial; 49 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic; 50 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeVirtual; 51 import static java.lang.invoke.MethodHandleNatives.Constants.REF_putField; 52 import static java.lang.invoke.MethodHandleNatives.Constants.REF_putStatic; 53 import static java.lang.invoke.MethodHandleStatics.PROFILE_GWT; 54 import static java.lang.invoke.MethodHandleStatics.PROFILE_LEVEL; 55 import static java.lang.invoke.MethodHandleStatics.newInternalError; 56 import static jdk.experimental.bytecode.MacroCodeBuilder.CondKind.EQ; 57 import static jdk.experimental.bytecode.MacroCodeBuilder.CondKind.NE; 58 59 /** 60 * Utility class for spinning classfiles associated with lambda forms. 61 */ 62 class LambdaFormBuilder extends MethodHandleBuilder { 63 64 private static final String OBJ = "java/lang/Object"; 65 private static final String CLASS_PREFIX = "java/lang/invoke/LambdaForm$Value$"; 66 private static final String DEFAULT_CLASS = "MH"; 67 private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";"; 68 69 private static final String MH = "java/lang/invoke/MethodHandle"; 70 private static final String MHARY2 = "[[L" + MH + ";"; 71 72 static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) { 73 String invokerName = form.lambdaName(); 74 int p = invokerName.indexOf('.'); 75 boolean overrideNames = p != -1; 76 String methodName = overrideNames ? invokerName.substring(p + 1) : invokerName; 77 String className = overrideNames ? 78 CLASS_PREFIX + invokerName.substring(0, p) : 79 CLASS_PREFIX + DEFAULT_CLASS; 80 if (MinimalValueTypes_1_0.DUMP_CLASS_FILES) { 81 // When DUMP_CLASS_FILES is true methodName will have a unique id 82 className = className + "_" + methodName; 83 } 84 return MethodHandleBuilder.loadCode(Lookup.IMPL_LOOKUP.in(LambdaForm.class), className, methodName, invokerType.toMethodDescriptorString(), 85 M -> new LambdaFormCodeBuilder(form, invokerType, M), clazz -> InvokerBytecodeGenerator.resolveInvokerMember(clazz, methodName, invokerType), 86 C -> new LambdaFormBuilder(C, form).generateLambdaFormBody()); 87 } 88 89 LambdaFormCodeBuilder builder; 90 LambdaForm lambdaForm; 91 92 LambdaFormBuilder(LambdaFormCodeBuilder builder, LambdaForm lambdaForm) { 93 this.builder = builder; 94 this.lambdaForm = lambdaForm; 95 } 96 97 void generateLambdaFormBody() { 98 // iterate over the form's names, generating bytecode instructions for each 99 // start iterating at the first name following the arguments 100 Name onStack = null; 101 for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) { 102 Name name = lambdaForm.names[i]; 103 104 if (onStack != null && onStack.type != V_TYPE) { 105 // non-void: actually assign 106 builder.store(fromBasicType(onStack.type), onStack.index()); 107 } 108 onStack = name; // unless otherwise modified below 109 MemberName member = name.function.member(); 110 MethodHandleImpl.Intrinsic intr = name.function.intrinsicName(); 111 switch (intr) { 112 case SELECT_ALTERNATIVE: { 113 assert lambdaForm.isSelectAlternative(i); 114 if (PROFILE_GWT) { 115 assert(name.arguments[0] instanceof Name && 116 ((Name)name.arguments[0]).refersTo(MethodHandleImpl.class, "profileBoolean")); 117 builder.method().withAnnotation(AnnotationsBuilder.Kind.RUNTIME_VISIBLE, InvokerBytecodeGenerator.INJECTEDPROFILE_SIG); | 48 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeSpecial; 49 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic; 50 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeVirtual; 51 import static java.lang.invoke.MethodHandleNatives.Constants.REF_putField; 52 import static java.lang.invoke.MethodHandleNatives.Constants.REF_putStatic; 53 import static java.lang.invoke.MethodHandleStatics.PROFILE_GWT; 54 import static java.lang.invoke.MethodHandleStatics.PROFILE_LEVEL; 55 import static java.lang.invoke.MethodHandleStatics.newInternalError; 56 import static jdk.experimental.bytecode.MacroCodeBuilder.CondKind.EQ; 57 import static jdk.experimental.bytecode.MacroCodeBuilder.CondKind.NE; 58 59 /** 60 * Utility class for spinning classfiles associated with lambda forms. 61 */ 62 class LambdaFormBuilder extends MethodHandleBuilder { 63 64 private static final String OBJ = "java/lang/Object"; 65 private static final String CLASS_PREFIX = "java/lang/invoke/LambdaForm$Value$"; 66 private static final String DEFAULT_CLASS = "MH"; 67 private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";"; 68 private static final String LLV_SIG = "(L" + OBJ + ";L" + OBJ + ";)V"; 69 70 private static final String MH = "java/lang/invoke/MethodHandle"; 71 private static final String MHARY2 = "[[L" + MH + ";"; 72 73 static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) { 74 String invokerName = form.lambdaName(); 75 int p = invokerName.indexOf('.'); 76 boolean overrideNames = p != -1; 77 String methodName = overrideNames ? invokerName.substring(p + 1) : invokerName; 78 String className = overrideNames ? 79 CLASS_PREFIX + invokerName.substring(0, p) : 80 CLASS_PREFIX + DEFAULT_CLASS; 81 if (MinimalValueTypes_1_0.DUMP_CLASS_FILES) { 82 // When DUMP_CLASS_FILES is true methodName will have a unique id 83 className = className + "_" + methodName; 84 } 85 return MethodHandleBuilder.loadCode(Lookup.IMPL_LOOKUP.in(LambdaForm.class), className, methodName, invokerType.toMethodDescriptorString(), 86 M -> new LambdaFormCodeBuilder(form, invokerType, M), clazz -> InvokerBytecodeGenerator.resolveInvokerMember(clazz, methodName, invokerType), 87 C -> new LambdaFormBuilder(C, form).generateLambdaFormBody()); 88 } 89 90 LambdaFormCodeBuilder builder; 91 LambdaForm lambdaForm; 92 93 LambdaFormBuilder(LambdaFormCodeBuilder builder, LambdaForm lambdaForm) { 94 this.builder = builder; 95 this.lambdaForm = lambdaForm; 96 } 97 98 /** Generates code to check that actual receiver and LambdaForm matches */ 99 private boolean checkActualReceiver() { 100 // Expects MethodHandle on the stack and actual receiver MethodHandle in slot #0 101 builder.dup().load(0).invokestatic(MethodHandleImpl.class, "assertSame", LLV_SIG, false); 102 return true; 103 } 104 105 void generateLambdaFormBody() { 106 if (lambdaForm.customized != null && MethodHandleBuilder.ENABLE_POOL_PATCHES) { 107 // Since LambdaForm is customized for a particular MethodHandle, it's safe to substitute 108 // receiver MethodHandle (at slot #0) with an embedded constant and use it instead. 109 // It enables more efficient code generation in some situations, since embedded constants 110 // are compile-time constants for JIT compiler. 111 builder.ldc(lambdaForm.customized) 112 .checkcast(MethodHandle.class); 113 assert(checkActualReceiver()); // generates runtime check 114 builder.store(0); 115 } 116 117 // iterate over the form's names, generating bytecode instructions for each 118 // start iterating at the first name following the arguments 119 Name onStack = null; 120 for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) { 121 Name name = lambdaForm.names[i]; 122 123 if (onStack != null && onStack.type != V_TYPE) { 124 // non-void: actually assign 125 builder.store(fromBasicType(onStack.type), onStack.index()); 126 } 127 onStack = name; // unless otherwise modified below 128 MemberName member = name.function.member(); 129 MethodHandleImpl.Intrinsic intr = name.function.intrinsicName(); 130 switch (intr) { 131 case SELECT_ALTERNATIVE: { 132 assert lambdaForm.isSelectAlternative(i); 133 if (PROFILE_GWT) { 134 assert(name.arguments[0] instanceof Name && 135 ((Name)name.arguments[0]).refersTo(MethodHandleImpl.class, "profileBoolean")); 136 builder.method().withAnnotation(AnnotationsBuilder.Kind.RUNTIME_VISIBLE, InvokerBytecodeGenerator.INJECTEDPROFILE_SIG); |