< prev index next >

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

Print this page
*** 24,10 ***
--- 24,11 ---
   */
  
  package java.lang.invoke;
  
  import sun.invoke.util.Wrapper;
+ import sun.util.logging.PlatformLogger;
  
  import java.lang.classfile.ClassFile;
  import java.lang.classfile.attribute.SourceFileAttribute;
  import java.lang.constant.ClassDesc;
  import java.util.ArrayList;

*** 71,11 ***
      static class HolderClassBuilder {
  
  
          private final TreeSet<String> speciesTypes = new TreeSet<>();
          private final TreeSet<String> invokerTypes = new TreeSet<>();
-         private final TreeSet<String> linkerTypes = new TreeSet<>();
          private final TreeSet<String> callSiteTypes = new TreeSet<>();
          private final Map<String, Set<String>> dmhMethods = new TreeMap<>();
  
          HolderClassBuilder addSpeciesType(String type) {
              speciesTypes.add(expandSignature(type));
--- 72,10 ---

*** 86,16 ***
              validateMethodType(methodType);
              invokerTypes.add(methodType);
              return this;
          }
  
-         HolderClassBuilder addLinkerType(String methodType) {
-             validateMethodType(methodType);
-             linkerTypes.add(methodType);
-             return this;
-         }
- 
          HolderClassBuilder addCallSiteType(String csType) {
              validateMethodType(csType);
              callSiteTypes.add(csType);
              return this;
          }
--- 86,10 ---

*** 117,14 ***
                      if (mt.parameterCount() < 1 ||
                              mt.parameterType(0) != Object.class) {
                          throw new RuntimeException(
                                  "DMH type parameter must start with L: " + dmhType + " " + type);
                      }
- 
                      // Adapt the method type of the LF to retrieve
                      directMethodTypes[index] = mt.dropParameterTypes(0, 1);
- 
                      // invokeVirtual and invokeInterface must have a leading Object
                      // parameter, i.e., the receiver
                      dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType);
                      if (dmhTypes[index] == LF_INVINTERFACE || dmhTypes[index] == LF_INVVIRTUAL) {
                          if (mt.parameterCount() < 2 ||
--- 111,12 ---

*** 135,37 ***
                      }
                      index++;
                  }
              }
  
-             // The linker type to ask for is retrieved by removing the first
-             // and the last argument, which needs to be of Object.class
-             MethodType[] linkerMethodTypes = new MethodType[linkerTypes.size()];
-             index = 0;
-             for (String linkerType : linkerTypes) {
-                 MethodType mt = asMethodType(linkerType);
-                 final int lastParam = mt.parameterCount() - 1;
-                 if (!checkLinkerTypeParams(mt)) {
-                     throw new RuntimeException(
-                             "Linker type parameter must start and end with Object: " + linkerType);
-                 }
-                 mt = mt.dropParameterTypes(lastParam, lastParam + 1);
-                 linkerMethodTypes[index] = mt.dropParameterTypes(0, 1);
-                 index++;
-             }
- 
              // The invoker type to ask for is retrieved by removing the first
!             // argument, which needs to be of Object.class
              MethodType[] invokerMethodTypes = new MethodType[invokerTypes.size()];
              index = 0;
              for (String invokerType : invokerTypes) {
                  MethodType mt = asMethodType(invokerType);
                  if (!checkInvokerTypeParams(mt)) {
                      throw new RuntimeException(
!                             "Invoker type parameter must start with 2 Objects: " + invokerType);
                  }
!                 invokerMethodTypes[index] = mt.dropParameterTypes(0, 2);
                  index++;
              }
  
              // The callSite type to ask for is retrieved by removing the last
              // argument, which needs to be of Object.class
--- 127,23 ---
                      }
                      index++;
                  }
              }
  
              // The invoker type to ask for is retrieved by removing the first
!             // and the last argument, which needs to be of Object.class
              MethodType[] invokerMethodTypes = new MethodType[invokerTypes.size()];
              index = 0;
              for (String invokerType : invokerTypes) {
                  MethodType mt = asMethodType(invokerType);
+                 final int lastParam = mt.parameterCount() - 1;
                  if (!checkInvokerTypeParams(mt)) {
                      throw new RuntimeException(
!                             "Invoker type parameter must start and end with Object: " + invokerType);
                  }
!                 mt = mt.dropParameterTypes(lastParam, lastParam + 1);
+                 invokerMethodTypes[index] = mt.dropParameterTypes(0, 1);
                  index++;
              }
  
              // The callSite type to ask for is retrieved by removing the last
              // argument, which needs to be of Object.class

*** 180,35 ***
                              "CallSite type parameter must end with Object: " + callSiteType);
                  }
                  callSiteMethodTypes[index] = mt.dropParameterTypes(lastParam, lastParam + 1);
                  index++;
              }
- 
              Map<String, byte[]> result = new TreeMap<>();
              result.put(DIRECT_HOLDER,
                         generateDirectMethodHandleHolderClassBytes(
                              DIRECT_HOLDER, directMethodTypes, dmhTypes));
              result.put(DELEGATING_HOLDER,
                         generateDelegatingMethodHandleHolderClassBytes(
                              DELEGATING_HOLDER, directMethodTypes));
              result.put(INVOKERS_HOLDER,
                         generateInvokersHolderClassBytes(INVOKERS_HOLDER,
!                             linkerMethodTypes, invokerMethodTypes, callSiteMethodTypes));
              result.put(BASIC_FORMS_HOLDER,
                         generateBasicFormsClassBytes(BASIC_FORMS_HOLDER));
  
              speciesTypes.forEach(types -> {
                  Map.Entry<String, byte[]> entry = generateConcreteBMHClassBytes(types);
                  result.put(entry.getKey(), entry.getValue());
              });
- 
              // clear builder
              speciesTypes.clear();
              invokerTypes.clear();
              callSiteTypes.clear();
              dmhMethods.clear();
- 
              return result;
          }
  
          public static MethodType asMethodType(String basicSignatureString) {
              String[] parts = basicSignatureString.split("_");
--- 158,32 ---
                              "CallSite type parameter must end with Object: " + callSiteType);
                  }
                  callSiteMethodTypes[index] = mt.dropParameterTypes(lastParam, lastParam + 1);
                  index++;
              }
              Map<String, byte[]> result = new TreeMap<>();
              result.put(DIRECT_HOLDER,
                         generateDirectMethodHandleHolderClassBytes(
                              DIRECT_HOLDER, directMethodTypes, dmhTypes));
              result.put(DELEGATING_HOLDER,
                         generateDelegatingMethodHandleHolderClassBytes(
                              DELEGATING_HOLDER, directMethodTypes));
              result.put(INVOKERS_HOLDER,
                         generateInvokersHolderClassBytes(INVOKERS_HOLDER,
!                             invokerMethodTypes, callSiteMethodTypes));
              result.put(BASIC_FORMS_HOLDER,
                         generateBasicFormsClassBytes(BASIC_FORMS_HOLDER));
  
              speciesTypes.forEach(types -> {
                  Map.Entry<String, byte[]> entry = generateConcreteBMHClassBytes(types);
                  result.put(entry.getKey(), entry.getValue());
              });
              // clear builder
              speciesTypes.clear();
              invokerTypes.clear();
              callSiteTypes.clear();
              dmhMethods.clear();
              return result;
          }
  
          public static MethodType asMethodType(String basicSignatureString) {
              String[] parts = basicSignatureString.split("_");

*** 226,16 ***
                  return MethodType.methodType(rtype, ptypes);
              }
          }
  
          public static boolean checkInvokerTypeParams(MethodType mt) {
-             return (mt.parameterCount() >= 2 &&
-                     mt.parameterType(0) == Object.class &&
-                     mt.parameterType(1) == Object.class);
-         }
- 
-         public static boolean checkLinkerTypeParams(MethodType mt) {
              final int lastParam = mt.parameterCount() - 1;
              return (mt.parameterCount() >= 2 &&
                      mt.parameterType(0) == Object.class &&
                      mt.parameterType(lastParam) == Object.class);
          }
--- 201,10 ---

*** 345,15 ***
                              String methodType = parts[3];
                              if (parts[1].equals(INVOKERS_HOLDER_CLASS_NAME)) {
                                  if ("linkToTargetMethod".equals(parts[2]) ||
                                          "linkToCallSite".equals(parts[2])) {
                                      builder.addCallSiteType(methodType);
-                                 } else if (parts[2].endsWith("nvoker")) {
-                                     // MH.exactInvoker exactInvoker MH.invoker invoker
-                                     builder.addInvokerType(methodType);
                                  } else {
!                                     builder.addLinkerType(methodType);
                                  }
                              } else if (parts[1].contains("DirectMethodHandle")) {
                                  String dmh = parts[2];
                                  // ignore getObject etc for now (generated by default)
                                  if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) {
--- 314,19 ---
                              String methodType = parts[3];
                              if (parts[1].equals(INVOKERS_HOLDER_CLASS_NAME)) {
                                  if ("linkToTargetMethod".equals(parts[2]) ||
                                          "linkToCallSite".equals(parts[2])) {
                                      builder.addCallSiteType(methodType);
                                  } else {
!                                     MethodType mt = HolderClassBuilder.asMethodType(methodType);
+                                     // Work around JDK-8327499
+                                     if (HolderClassBuilder.checkInvokerTypeParams(mt)) {
+                                         builder.addInvokerType(methodType);
+                                     } else {
+                                         PlatformLogger.getLogger("java.lang.invoke")
+                                                 .warning("Invalid LF_RESOLVE " + parts[1] + " " + parts[2] + " " + parts[3]);
+                                     }
                                  }
                              } else if (parts[1].contains("DirectMethodHandle")) {
                                  String dmh = parts[2];
                                  // ignore getObject etc for now (generated by default)
                                  if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) {

*** 486,56 ***
                  forms.toArray(new LambdaForm[0]));
      }
  
      /**
       * Returns a {@code byte[]} representation of a class implementing
!      * the invoker forms for the set of supplied {@code linkerMethodTypes}
!      * {@code invokerMethodTypes}, and {@code callSiteMethodTypes}.
       */
      static byte[] generateInvokersHolderClassBytes(String className,
!             MethodType[] linkerMethodTypes, MethodType[] invokerMethodTypes,
-             MethodType[] callSiteMethodTypes) {
  
          HashSet<MethodType> dedupSet = new HashSet<>();
          ArrayList<LambdaForm> forms = new ArrayList<>();
          ArrayList<String> names = new ArrayList<>();
! 
!         int[] invokerTypes = {
              MethodTypeForm.LF_EX_INVOKER,
!             MethodTypeForm.LF_GEN_INVOKER,
          };
  
!         for (MethodType methodType : invokerMethodTypes) {
              // generate methods representing invokers of the specified type
!             if (dedupSet.add(methodType)) {
!                 for (int type : invokerTypes) {
!                     LambdaForm invokerForm = Invokers.invokeHandleForm(methodType,
                              /*customized*/false, type);
                      forms.add(invokerForm);
                      names.add(invokerForm.kind.defaultLambdaName);
                  }
              }
          }
  
-         int[] linkerTypes = {
-                 MethodTypeForm.LF_EX_LINKER,
-                 MethodTypeForm.LF_GEN_LINKER,
-         };
- 
-         dedupSet = new HashSet<>();
-         for (MethodType methodType : linkerMethodTypes) {
-             // generate methods representing linkers of the specified type
-             if (dedupSet.add(methodType)) {
-                 for (int type : linkerTypes) {
-                     LambdaForm linkerForm = Invokers.invokeHandleForm(methodType,
-                             /*customized*/false, type);
-                     forms.add(linkerForm);
-                     names.add(linkerForm.kind.defaultLambdaName);
-                 }
-             }
-         }
- 
          dedupSet = new HashSet<>();
          for (int i = 0; i < callSiteMethodTypes.length; i++) {
              // generate methods representing invokers of the specified type
              if (dedupSet.add(callSiteMethodTypes[i])) {
                  LambdaForm callSiteForm = Invokers.callSiteForm(callSiteMethodTypes[i], true);
--- 459,38 ---
                  forms.toArray(new LambdaForm[0]));
      }
  
      /**
       * Returns a {@code byte[]} representation of a class implementing
!      * the invoker forms for the set of supplied {@code invokerMethodTypes}
!      * and {@code callSiteMethodTypes}.
       */
      static byte[] generateInvokersHolderClassBytes(String className,
!             MethodType[] invokerMethodTypes, MethodType[] callSiteMethodTypes) {
  
          HashSet<MethodType> dedupSet = new HashSet<>();
          ArrayList<LambdaForm> forms = new ArrayList<>();
          ArrayList<String> names = new ArrayList<>();
!         int[] types = {
!             MethodTypeForm.LF_EX_LINKER,
              MethodTypeForm.LF_EX_INVOKER,
!             MethodTypeForm.LF_GEN_LINKER,
+             MethodTypeForm.LF_GEN_INVOKER
          };
  
!         for (int i = 0; i < invokerMethodTypes.length; i++) {
              // generate methods representing invokers of the specified type
!             if (dedupSet.add(invokerMethodTypes[i])) {
!                 for (int type : types) {
!                     LambdaForm invokerForm = Invokers.invokeHandleForm(invokerMethodTypes[i],
                              /*customized*/false, type);
                      forms.add(invokerForm);
                      names.add(invokerForm.kind.defaultLambdaName);
                  }
              }
          }
  
          dedupSet = new HashSet<>();
          for (int i = 0; i < callSiteMethodTypes.length; i++) {
              // generate methods representing invokers of the specified type
              if (dedupSet.add(callSiteMethodTypes[i])) {
                  LambdaForm callSiteForm = Invokers.callSiteForm(callSiteMethodTypes[i], true);
< prev index next >