< prev index next >

src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java

Print this page
rev 49208 : 8199471: Enable generation of callSiteForms at link time
Reviewed-by: psandoz


  52  * Plugin to generate java.lang.invoke classes.
  53  */
  54 public final class GenerateJLIClassesPlugin implements Plugin {
  55 
  56     private static final String NAME = "generate-jli-classes";
  57 
  58     private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME);
  59 
  60     private static final String DEFAULT_TRACE_FILE = "default_jli_trace.txt";
  61 
  62     private static final String DIRECT_HOLDER = "java/lang/invoke/DirectMethodHandle$Holder";
  63     private static final String DMH_INVOKE_VIRTUAL = "invokeVirtual";
  64     private static final String DMH_INVOKE_STATIC = "invokeStatic";
  65     private static final String DMH_INVOKE_SPECIAL = "invokeSpecial";
  66     private static final String DMH_NEW_INVOKE_SPECIAL = "newInvokeSpecial";
  67     private static final String DMH_INVOKE_INTERFACE = "invokeInterface";
  68     private static final String DMH_INVOKE_STATIC_INIT = "invokeStaticInit";
  69 
  70     private static final String DELEGATING_HOLDER = "java/lang/invoke/DelegatingMethodHandle$Holder";
  71     private static final String BASIC_FORMS_HOLDER = "java/lang/invoke/LambdaForm$Holder";
  72     private static final String INVOKERS_HOLDER = "java/lang/invoke/Invokers$Holder";


  73 
  74     private static final JavaLangInvokeAccess JLIA
  75             = SharedSecrets.getJavaLangInvokeAccess();
  76 
  77     Set<String> speciesTypes = Set.of();
  78 
  79     Set<String> invokerTypes = Set.of();
  80 


  81     Map<String, Set<String>> dmhMethods = Map.of();
  82 
  83     String mainArgument;
  84 
  85     public GenerateJLIClassesPlugin() {
  86     }
  87 
  88     @Override
  89     public String getName() {
  90         return NAME;
  91     }
  92 
  93     @Override
  94     public String getDescription() {
  95         return DESCRIPTION;
  96     }
  97 
  98     @Override
  99     public Set<State> getState() {
 100         return EnumSet.of(State.AUTO_ENABLED, State.FUNCTIONAL);


 111     }
 112 
 113     /**
 114      * @return the default Species forms to generate.
 115      *
 116      * This list was derived from running a small startup benchmark.
 117      * A better long-term solution is to define and run a set of quick
 118      * generators and extracting this list as a step in the build process.
 119      */
 120     public static Set<String> defaultSpecies() {
 121         return Set.of("LL", "L3", "L4", "L5", "L6", "L7", "L7I",
 122                 "L7II", "L7IIL", "L8", "L9", "L10", "L10I", "L10II", "L10IIL",
 123                 "L11", "L12", "L13", "LI", "D", "L3I", "LIL", "LLI", "LLIL",
 124                 "LILL", "I", "LLILL");
 125     }
 126 
 127     /**
 128      * @return the default invoker forms to generate.
 129      */
 130     private static Set<String> defaultInvokers() {
 131         return Set.of("LL_L", "LL_I", "LILL_I", "L6_L");
 132     }
 133 
 134     /**
 135      * @return the list of default DirectMethodHandle methods to generate.
 136      */
 137     private static Map<String, Set<String>> defaultDMHMethods() {
 138         return Map.of(
 139             DMH_INVOKE_VIRTUAL, Set.of("L_L", "LL_L", "LLI_I", "L3_V"),
 140             DMH_INVOKE_SPECIAL, Set.of("LL_I", "LL_L", "LLF_L", "LLD_L", "L3_L",
 141                 "L4_L", "L5_L", "L6_L", "L7_L", "L8_L", "LLI_I", "LLI_L",
 142                 "LLIL_I", "LLII_I", "LLII_L", "L3I_L", "L3I_I", "LLILI_I",
 143                 "LLIIL_L", "LLIILL_L", "LLIILL_I", "LLIIL_I", "LLILIL_I",
 144                 "LLILILL_I", "LLILII_I", "LLI3_I", "LLI3L_I", "LLI3LL_I",
 145                 "LLI3_L", "LLI4_I"),
 146             DMH_INVOKE_STATIC, Set.of("LII_I", "LIL_I", "LILIL_I", "LILII_I",
 147                 "L_I", "L_L", "L_V", "LD_L", "LF_L", "LI_I", "LII_L", "LLI_L",
 148                 "LL_V", "LL_L", "L3_L", "L4_L", "L5_L", "L6_L", "L7_L",
 149                 "L8_L", "L9_L", "L10_L", "L10I_L", "L10II_L", "L10IIL_L",
 150                 "L11_L", "L12_L", "L13_L", "L14_L", "L14I_L", "L14II_L"),
 151             DMH_NEW_INVOKE_SPECIAL, Set.of("L_L", "LL_L")


 192                         new BufferedReader(
 193                             new InputStreamReader(traceFile)).lines());
 194                 }
 195             } catch (Exception e) {
 196                 throw new PluginException("Couldn't read " + DEFAULT_TRACE_FILE, e);
 197             }
 198         } else {
 199             File file = new File(mainArgument.substring(1));
 200             if (file.exists()) {
 201                 readTraceConfig(fileLines(file));
 202             }
 203         }
 204     }
 205 
 206     private void readTraceConfig(Stream<String> lines) {
 207         // Use TreeSet/TreeMap to keep things sorted in a deterministic
 208         // order to avoid scrambling the layout on small changes and to
 209         // ease finding methods in the generated code
 210         speciesTypes = new TreeSet<>(speciesTypes);
 211         invokerTypes = new TreeSet<>(invokerTypes);


 212         TreeMap<String, Set<String>> newDMHMethods = new TreeMap<>();
 213         for (Map.Entry<String, Set<String>> entry : dmhMethods.entrySet()) {
 214             newDMHMethods.put(entry.getKey(), new TreeSet<>(entry.getValue()));
 215         }
 216         dmhMethods = newDMHMethods;
 217         lines.map(line -> line.split(" "))
 218              .forEach(parts -> {
 219                 switch (parts[0]) {
 220                     case "[SPECIES_RESOLVE]":
 221                         // Allow for new types of species data classes being resolved here
 222                         if (parts.length == 3 && parts[1].startsWith("java.lang.invoke.BoundMethodHandle$Species_")) {
 223                             String species = parts[1].substring("java.lang.invoke.BoundMethodHandle$Species_".length());
 224                             if (!"L".equals(species)) {
 225                                 speciesTypes.add(expandSignature(species));
 226                             }
 227                         }
 228                         break;
 229                     case "[LF_RESOLVE]":
 230                         String methodType = parts[3];
 231                         validateMethodType(methodType);
 232                         if (parts[1].contains("Invokers")) {




 233                             invokerTypes.add(methodType);

 234                         } else if (parts[1].contains("DirectMethodHandle")) {
 235                             String dmh = parts[2];
 236                             // ignore getObject etc for now (generated
 237                             // by default)
 238                             if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) {
 239                                 addDMHMethodType(dmh, methodType);
 240                             }
 241                         }
 242                         break;
 243                     default: break; // ignore
 244                 }
 245             });
 246     }
 247 
 248     private void addDMHMethodType(String dmh, String methodType) {
 249         validateMethodType(methodType);
 250         Set<String> methodTypes = dmhMethods.get(dmh);
 251         if (methodTypes == null) {
 252             methodTypes = new TreeSet<>();
 253             dmhMethods.put(dmh, methodTypes);


 277             throw new PluginException(
 278                     "Method type signature must be of form [LJIFD]*_[LJIFDV]");
 279         }
 280         // expand and check arguments (first part)
 281         expandSignature(typeParts[0]);
 282     }
 283 
 284     private static void requireBasicType(char c) {
 285         if ("LIJFD".indexOf(c) < 0) {
 286             throw new PluginException(
 287                     "Character " + c + " must correspond to a basic field type: LIJFD");
 288         }
 289     }
 290 
 291     @Override
 292     public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
 293         initialize(in);
 294         // Copy all but DMH_ENTRY to out
 295         in.transformAndCopy(entry -> {
 296                 // filter out placeholder entries
 297                 if (entry.path().equals(DIRECT_METHOD_HOLDER_ENTRY) ||
 298                     entry.path().equals(DELEGATING_METHOD_HOLDER_ENTRY) ||
 299                     entry.path().equals(INVOKERS_HOLDER_ENTRY) ||
 300                     entry.path().equals(BASIC_FORMS_HOLDER_ENTRY)) {

 301                     return null;
 302                 } else {
 303                     return entry;
 304                 }
 305             }, out);
 306 
 307         // Generate BMH Species classes
 308         speciesTypes.forEach(types -> generateBMHClass(types, out));
 309 
 310         // Generate LambdaForm Holder classes
 311         generateHolderClasses(out);
 312 
 313         // Let it go
 314         speciesTypes = null;
 315         invokerTypes = null;
 316         dmhMethods = null;
 317 
 318         return out.build();
 319     }
 320 


 344         }
 345         MethodType[] directMethodTypes = new MethodType[count];
 346         int[] dmhTypes = new int[count];
 347         int index = 0;
 348         for (Map.Entry<String, Set<String>> entry : dmhMethods.entrySet()) {
 349             String dmhType = entry.getKey();
 350             for (String type : entry.getValue()) {
 351                 // The DMH type to actually ask for is retrieved by removing
 352                 // the first argument, which needs to be of Object.class
 353                 MethodType mt = asMethodType(type);
 354                 if (mt.parameterCount() < 1 ||
 355                     mt.parameterType(0) != Object.class) {
 356                     throw new PluginException(
 357                             "DMH type parameter must start with L");
 358                 }
 359                 directMethodTypes[index] = mt.dropParameterTypes(0, 1);
 360                 dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType);
 361                 index++;
 362             }
 363         }



 364         MethodType[] invokerMethodTypes = new MethodType[this.invokerTypes.size()];
 365         int i = 0;
 366         for (String invokerType : invokerTypes) {
 367             // The invoker type to ask for is retrieved by removing the first
 368             // and the last argument, which needs to be of Object.class
 369             MethodType mt = asMethodType(invokerType);
 370             final int lastParam = mt.parameterCount() - 1;
 371             if (mt.parameterCount() < 2 ||
 372                     mt.parameterType(0) != Object.class ||
 373                     mt.parameterType(lastParam) != Object.class) {
 374                 throw new PluginException(
 375                         "Invoker type parameter must start and end with L");
 376             }
 377             mt = mt.dropParameterTypes(lastParam, lastParam + 1);
 378             invokerMethodTypes[i] = mt.dropParameterTypes(0, 1);
 379             i++;
 380         }
















 381         try {
 382             byte[] bytes = JLIA.generateDirectMethodHandleHolderClassBytes(
 383                     DIRECT_HOLDER, directMethodTypes, dmhTypes);
 384             ResourcePoolEntry ndata = ResourcePoolEntry
 385                     .create(DIRECT_METHOD_HOLDER_ENTRY, bytes);
 386             out.add(ndata);
 387 
 388             bytes = JLIA.generateDelegatingMethodHandleHolderClassBytes(
 389                     DELEGATING_HOLDER, directMethodTypes);
 390             ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HOLDER_ENTRY, bytes);
 391             out.add(ndata);
 392 
 393             bytes = JLIA.generateInvokersHolderClassBytes(INVOKERS_HOLDER,
 394                     invokerMethodTypes);
 395             ndata = ResourcePoolEntry.create(INVOKERS_HOLDER_ENTRY, bytes);
 396             out.add(ndata);
 397 
 398             bytes = JLIA.generateBasicFormsClassBytes(BASIC_FORMS_HOLDER);
 399             ndata = ResourcePoolEntry.create(BASIC_FORMS_HOLDER_ENTRY, bytes);
 400             out.add(ndata);
 401         } catch (Exception ex) {
 402             throw new PluginException(ex);
 403         }
 404     }
 405     private static final String DIRECT_METHOD_HOLDER_ENTRY =
 406             "/java.base/" + DIRECT_HOLDER + ".class";
 407     private static final String DELEGATING_METHOD_HOLDER_ENTRY =
 408             "/java.base/" + DELEGATING_HOLDER + ".class";
 409     private static final String BASIC_FORMS_HOLDER_ENTRY =
 410             "/java.base/" + BASIC_FORMS_HOLDER + ".class";
 411     private static final String INVOKERS_HOLDER_ENTRY =
 412             "/java.base/" + INVOKERS_HOLDER + ".class";
 413 
 414     // Convert LL -> LL, L3 -> LLL
 415     public static String expandSignature(String signature) {
 416         StringBuilder sb = new StringBuilder();
 417         char last = 'X';
 418         int count = 0;
 419         for (int i = 0; i < signature.length(); i++) {
 420             char c = signature.charAt(i);
 421             if (c >= '0' && c <= '9') {
 422                 count *= 10;
 423                 count += (c - '0');
 424             } else {
 425                 requireBasicType(c);
 426                 for (int j = 1; j < count; j++) {
 427                     sb.append(last);
 428                 }
 429                 sb.append(c);
 430                 last = c;
 431                 count = 0;
 432             }




  52  * Plugin to generate java.lang.invoke classes.
  53  */
  54 public final class GenerateJLIClassesPlugin implements Plugin {
  55 
  56     private static final String NAME = "generate-jli-classes";
  57 
  58     private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME);
  59 
  60     private static final String DEFAULT_TRACE_FILE = "default_jli_trace.txt";
  61 
  62     private static final String DIRECT_HOLDER = "java/lang/invoke/DirectMethodHandle$Holder";
  63     private static final String DMH_INVOKE_VIRTUAL = "invokeVirtual";
  64     private static final String DMH_INVOKE_STATIC = "invokeStatic";
  65     private static final String DMH_INVOKE_SPECIAL = "invokeSpecial";
  66     private static final String DMH_NEW_INVOKE_SPECIAL = "newInvokeSpecial";
  67     private static final String DMH_INVOKE_INTERFACE = "invokeInterface";
  68     private static final String DMH_INVOKE_STATIC_INIT = "invokeStaticInit";
  69 
  70     private static final String DELEGATING_HOLDER = "java/lang/invoke/DelegatingMethodHandle$Holder";
  71     private static final String BASIC_FORMS_HOLDER = "java/lang/invoke/LambdaForm$Holder";
  72 
  73     private static final String INVOKERS_HOLDER_NAME = "java.lang.invoke.Invokers$Holder";
  74     private static final String INVOKERS_HOLDER_INTERNAL_NAME = INVOKERS_HOLDER_NAME.replace('.', '/');
  75 
  76     private static final JavaLangInvokeAccess JLIA
  77             = SharedSecrets.getJavaLangInvokeAccess();
  78 
  79     Set<String> speciesTypes = Set.of();
  80 
  81     Set<String> invokerTypes = Set.of();
  82 
  83     Set<String> callSiteTypes = Set.of();
  84 
  85     Map<String, Set<String>> dmhMethods = Map.of();
  86 
  87     String mainArgument;
  88 
  89     public GenerateJLIClassesPlugin() {
  90     }
  91 
  92     @Override
  93     public String getName() {
  94         return NAME;
  95     }
  96 
  97     @Override
  98     public String getDescription() {
  99         return DESCRIPTION;
 100     }
 101 
 102     @Override
 103     public Set<State> getState() {
 104         return EnumSet.of(State.AUTO_ENABLED, State.FUNCTIONAL);


 115     }
 116 
 117     /**
 118      * @return the default Species forms to generate.
 119      *
 120      * This list was derived from running a small startup benchmark.
 121      * A better long-term solution is to define and run a set of quick
 122      * generators and extracting this list as a step in the build process.
 123      */
 124     public static Set<String> defaultSpecies() {
 125         return Set.of("LL", "L3", "L4", "L5", "L6", "L7", "L7I",
 126                 "L7II", "L7IIL", "L8", "L9", "L10", "L10I", "L10II", "L10IIL",
 127                 "L11", "L12", "L13", "LI", "D", "L3I", "LIL", "LLI", "LLIL",
 128                 "LILL", "I", "LLILL");
 129     }
 130 
 131     /**
 132      * @return the default invoker forms to generate.
 133      */
 134     private static Set<String> defaultInvokers() {
 135         return Set.of("LL_L", "LL_I", "LLLL_L", "LLLL_I", "LLIL_L", "LLIL_I", "L6_L");
 136     }
 137 
 138     /**
 139      * @return the list of default DirectMethodHandle methods to generate.
 140      */
 141     private static Map<String, Set<String>> defaultDMHMethods() {
 142         return Map.of(
 143             DMH_INVOKE_VIRTUAL, Set.of("L_L", "LL_L", "LLI_I", "L3_V"),
 144             DMH_INVOKE_SPECIAL, Set.of("LL_I", "LL_L", "LLF_L", "LLD_L", "L3_L",
 145                 "L4_L", "L5_L", "L6_L", "L7_L", "L8_L", "LLI_I", "LLI_L",
 146                 "LLIL_I", "LLII_I", "LLII_L", "L3I_L", "L3I_I", "LLILI_I",
 147                 "LLIIL_L", "LLIILL_L", "LLIILL_I", "LLIIL_I", "LLILIL_I",
 148                 "LLILILL_I", "LLILII_I", "LLI3_I", "LLI3L_I", "LLI3LL_I",
 149                 "LLI3_L", "LLI4_I"),
 150             DMH_INVOKE_STATIC, Set.of("LII_I", "LIL_I", "LILIL_I", "LILII_I",
 151                 "L_I", "L_L", "L_V", "LD_L", "LF_L", "LI_I", "LII_L", "LLI_L",
 152                 "LL_V", "LL_L", "L3_L", "L4_L", "L5_L", "L6_L", "L7_L",
 153                 "L8_L", "L9_L", "L10_L", "L10I_L", "L10II_L", "L10IIL_L",
 154                 "L11_L", "L12_L", "L13_L", "L14_L", "L14I_L", "L14II_L"),
 155             DMH_NEW_INVOKE_SPECIAL, Set.of("L_L", "LL_L")


 196                         new BufferedReader(
 197                             new InputStreamReader(traceFile)).lines());
 198                 }
 199             } catch (Exception e) {
 200                 throw new PluginException("Couldn't read " + DEFAULT_TRACE_FILE, e);
 201             }
 202         } else {
 203             File file = new File(mainArgument.substring(1));
 204             if (file.exists()) {
 205                 readTraceConfig(fileLines(file));
 206             }
 207         }
 208     }
 209 
 210     private void readTraceConfig(Stream<String> lines) {
 211         // Use TreeSet/TreeMap to keep things sorted in a deterministic
 212         // order to avoid scrambling the layout on small changes and to
 213         // ease finding methods in the generated code
 214         speciesTypes = new TreeSet<>(speciesTypes);
 215         invokerTypes = new TreeSet<>(invokerTypes);
 216         callSiteTypes = new TreeSet<>(callSiteTypes);
 217 
 218         TreeMap<String, Set<String>> newDMHMethods = new TreeMap<>();
 219         for (Map.Entry<String, Set<String>> entry : dmhMethods.entrySet()) {
 220             newDMHMethods.put(entry.getKey(), new TreeSet<>(entry.getValue()));
 221         }
 222         dmhMethods = newDMHMethods;
 223         lines.map(line -> line.split(" "))
 224              .forEach(parts -> {
 225                 switch (parts[0]) {
 226                     case "[SPECIES_RESOLVE]":
 227                         // Allow for new types of species data classes being resolved here
 228                         if (parts.length == 3 && parts[1].startsWith("java.lang.invoke.BoundMethodHandle$Species_")) {
 229                             String species = parts[1].substring("java.lang.invoke.BoundMethodHandle$Species_".length());
 230                             if (!"L".equals(species)) {
 231                                 speciesTypes.add(expandSignature(species));
 232                             }
 233                         }
 234                         break;
 235                     case "[LF_RESOLVE]":
 236                         String methodType = parts[3];
 237                         validateMethodType(methodType);
 238                         if (parts[1].equals(INVOKERS_HOLDER_NAME)) {
 239                             if ("linkToTargetMethod".equals(parts[2]) ||
 240                                     "linkToCallSite".equals(parts[2])) {
 241                                 callSiteTypes.add(methodType);
 242                             } else {
 243                                 invokerTypes.add(methodType);
 244                             }
 245                         } else if (parts[1].contains("DirectMethodHandle")) {
 246                             String dmh = parts[2];
 247                             // ignore getObject etc for now (generated
 248                             // by default)
 249                             if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) {
 250                                 addDMHMethodType(dmh, methodType);
 251                             }
 252                         }
 253                         break;
 254                     default: break; // ignore
 255                 }
 256             });
 257     }
 258 
 259     private void addDMHMethodType(String dmh, String methodType) {
 260         validateMethodType(methodType);
 261         Set<String> methodTypes = dmhMethods.get(dmh);
 262         if (methodTypes == null) {
 263             methodTypes = new TreeSet<>();
 264             dmhMethods.put(dmh, methodTypes);


 288             throw new PluginException(
 289                     "Method type signature must be of form [LJIFD]*_[LJIFDV]");
 290         }
 291         // expand and check arguments (first part)
 292         expandSignature(typeParts[0]);
 293     }
 294 
 295     private static void requireBasicType(char c) {
 296         if ("LIJFD".indexOf(c) < 0) {
 297             throw new PluginException(
 298                     "Character " + c + " must correspond to a basic field type: LIJFD");
 299         }
 300     }
 301 
 302     @Override
 303     public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
 304         initialize(in);
 305         // Copy all but DMH_ENTRY to out
 306         in.transformAndCopy(entry -> {
 307                 // filter out placeholder entries
 308                 String path = entry.path();
 309                 if (path.equals(DIRECT_METHOD_HOLDER_ENTRY) ||
 310                     path.equals(DELEGATING_METHOD_HOLDER_ENTRY) ||
 311                     path.equals(INVOKERS_HOLDER_ENTRY) ||
 312                     path.equals(BASIC_FORMS_HOLDER_ENTRY)) {
 313                     return null;
 314                 } else {
 315                     return entry;
 316                 }
 317             }, out);
 318 
 319         // Generate BMH Species classes
 320         speciesTypes.forEach(types -> generateBMHClass(types, out));
 321 
 322         // Generate LambdaForm Holder classes
 323         generateHolderClasses(out);
 324 
 325         // Let it go
 326         speciesTypes = null;
 327         invokerTypes = null;
 328         dmhMethods = null;
 329 
 330         return out.build();
 331     }
 332 


 356         }
 357         MethodType[] directMethodTypes = new MethodType[count];
 358         int[] dmhTypes = new int[count];
 359         int index = 0;
 360         for (Map.Entry<String, Set<String>> entry : dmhMethods.entrySet()) {
 361             String dmhType = entry.getKey();
 362             for (String type : entry.getValue()) {
 363                 // The DMH type to actually ask for is retrieved by removing
 364                 // the first argument, which needs to be of Object.class
 365                 MethodType mt = asMethodType(type);
 366                 if (mt.parameterCount() < 1 ||
 367                     mt.parameterType(0) != Object.class) {
 368                     throw new PluginException(
 369                             "DMH type parameter must start with L");
 370                 }
 371                 directMethodTypes[index] = mt.dropParameterTypes(0, 1);
 372                 dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType);
 373                 index++;
 374             }
 375         }
 376 
 377         // The invoker type to ask for is retrieved by removing the first
 378         // and the last argument, which needs to be of Object.class
 379         MethodType[] invokerMethodTypes = new MethodType[this.invokerTypes.size()];
 380         int i = 0;
 381         for (String invokerType : invokerTypes) {


 382             MethodType mt = asMethodType(invokerType);
 383             final int lastParam = mt.parameterCount() - 1;
 384             if (mt.parameterCount() < 2 ||
 385                     mt.parameterType(0) != Object.class ||
 386                     mt.parameterType(lastParam) != Object.class) {
 387                 throw new PluginException(
 388                         "Invoker type parameter must start and end with Object: " + invokerType);
 389             }
 390             mt = mt.dropParameterTypes(lastParam, lastParam + 1);
 391             invokerMethodTypes[i] = mt.dropParameterTypes(0, 1);
 392             i++;
 393         }
 394 
 395         // The callSite type to ask for is retrieved by removing the last
 396         // argument, which needs to be of Object.class
 397         MethodType[] callSiteMethodTypes = new MethodType[this.callSiteTypes.size()];
 398         i = 0;
 399         for (String callSiteType : callSiteTypes) {
 400             MethodType mt = asMethodType(callSiteType);
 401             final int lastParam = mt.parameterCount() - 1;
 402             if (mt.parameterCount() < 1 ||
 403                     mt.parameterType(lastParam) != Object.class) {
 404                 throw new PluginException(
 405                         "CallSite type parameter must end with Object: " + callSiteType);
 406             }
 407             callSiteMethodTypes[i] = mt.dropParameterTypes(lastParam, lastParam + 1);
 408             i++;
 409         }
 410         try {
 411             byte[] bytes = JLIA.generateDirectMethodHandleHolderClassBytes(
 412                     DIRECT_HOLDER, directMethodTypes, dmhTypes);
 413             ResourcePoolEntry ndata = ResourcePoolEntry
 414                     .create(DIRECT_METHOD_HOLDER_ENTRY, bytes);
 415             out.add(ndata);
 416 
 417             bytes = JLIA.generateDelegatingMethodHandleHolderClassBytes(
 418                     DELEGATING_HOLDER, directMethodTypes);
 419             ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HOLDER_ENTRY, bytes);
 420             out.add(ndata);
 421 
 422             bytes = JLIA.generateInvokersHolderClassBytes(INVOKERS_HOLDER_INTERNAL_NAME,
 423                     invokerMethodTypes, callSiteMethodTypes);
 424             ndata = ResourcePoolEntry.create(INVOKERS_HOLDER_ENTRY, bytes);
 425             out.add(ndata);
 426 
 427             bytes = JLIA.generateBasicFormsClassBytes(BASIC_FORMS_HOLDER);
 428             ndata = ResourcePoolEntry.create(BASIC_FORMS_HOLDER_ENTRY, bytes);
 429             out.add(ndata);
 430         } catch (Exception ex) {
 431             throw new PluginException(ex);
 432         }
 433     }
 434     private static final String DIRECT_METHOD_HOLDER_ENTRY =
 435             "/java.base/" + DIRECT_HOLDER + ".class";
 436     private static final String DELEGATING_METHOD_HOLDER_ENTRY =
 437             "/java.base/" + DELEGATING_HOLDER + ".class";
 438     private static final String BASIC_FORMS_HOLDER_ENTRY =
 439             "/java.base/" + BASIC_FORMS_HOLDER + ".class";
 440     private static final String INVOKERS_HOLDER_ENTRY =
 441             "/java.base/" + INVOKERS_HOLDER_INTERNAL_NAME + ".class";
 442 
 443     // Convert LL -> LL, L3 -> LLL
 444     public static String expandSignature(String signature) {
 445         StringBuilder sb = new StringBuilder();
 446         char last = 'X';
 447         int count = 0;
 448         for (int i = 0; i < signature.length(); i++) {
 449             char c = signature.charAt(i);
 450             if (c >= '0' && c <= '9') {
 451                 count *= 10;
 452                 count += (c - '0');
 453             } else {
 454                 requireBasicType(c);
 455                 for (int j = 1; j < count; j++) {
 456                     sb.append(last);
 457                 }
 458                 sb.append(c);
 459                 last = c;
 460                 count = 0;
 461             }


< prev index next >