< prev index next >

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

Print this page




  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);


< prev index next >