< prev index next >

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

Print this page
rev 16713 : 8175026: Capture build-time parameters to --generate-jli-classes
Reviewed-by: mchung

*** 22,39 **** * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.tools.jlink.internal.plugins; import java.io.File; import java.io.IOException; import java.lang.invoke.MethodType; import java.nio.file.Files; - import java.util.ArrayList; import java.util.EnumSet; - import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.stream.Collectors; import java.util.stream.Stream; --- 22,43 ---- * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.tools.jlink.internal.plugins; + import java.io.BufferedReader; import java.io.File; import java.io.IOException; + import java.io.InputStream; + import java.io.InputStreamReader; import java.lang.invoke.MethodType; + import java.lang.module.ModuleDescriptor; + import java.lang.module.ModuleFinder; import java.nio.file.Files; import java.util.EnumSet; import java.util.Map; + import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.stream.Collectors; import java.util.stream.Stream;
*** 52,61 **** --- 56,67 ---- private static final String NAME = "generate-jli-classes"; private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME); + private static final String DEFAULT_TRACE_FILE = "default_jli_trace.txt"; + private static final String DIRECT_HOLDER = "java/lang/invoke/DirectMethodHandle$Holder"; private static final String DMH_INVOKE_VIRTUAL = "invokeVirtual"; private static final String DMH_INVOKE_STATIC = "invokeStatic"; private static final String DMH_INVOKE_SPECIAL = "invokeSpecial"; private static final String DMH_NEW_INVOKE_SPECIAL = "newInvokeSpecial";
*** 67,81 **** private static final String INVOKERS_HOLDER = "java/lang/invoke/Invokers$Holder"; private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess(); ! Set<String> speciesTypes; ! Set<String> invokerTypes; ! Map<String, Set<String>> dmhMethods; public GenerateJLIClassesPlugin() { } @Override --- 73,89 ---- private static final String INVOKERS_HOLDER = "java/lang/invoke/Invokers$Holder"; private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess(); ! Set<String> speciesTypes = Set.of(); ! ! Set<String> invokerTypes = Set.of(); ! Map<String, Set<String>> dmhMethods = Map.of(); ! String mainArgument; public GenerateJLIClassesPlugin() { } @Override
*** 155,201 **** DMH_INVOKE_STATIC_INIT, 5 ); @Override public void configure(Map<String, String> config) { ! String mainArgument = config.get(NAME); // Start with the default configuration ! Set<String> defaultBMHSpecies = defaultSpecies(); ! // Expand BMH species signatures ! defaultBMHSpecies = defaultBMHSpecies.stream() .map(type -> expandSignature(type)) .collect(Collectors.toSet()); ! Set<String> defaultInvokerTypes = defaultInvokers(); ! validateMethodTypes(defaultInvokerTypes); ! Map<String, Set<String>> defaultDmhMethods = defaultDMHMethods(); ! for (Set<String> dmhMethodTypes : defaultDmhMethods.values()) { validateMethodTypes(dmhMethodTypes); } // Extend the default configuration with the contents in the supplied ! // input file if (mainArgument == null || !mainArgument.startsWith("@")) { ! speciesTypes = defaultBMHSpecies; ! invokerTypes = defaultInvokerTypes; ! dmhMethods = defaultDmhMethods; } else { File file = new File(mainArgument.substring(1)); if (file.exists()) { // Use TreeSet/TreeMap to keep things sorted in a deterministic // order to avoid scrambling the layout on small changes and to // ease finding methods in the generated code ! speciesTypes = new TreeSet<>(defaultBMHSpecies); ! invokerTypes = new TreeSet<>(defaultInvokerTypes); ! dmhMethods = new TreeMap<>(); ! for (Map.Entry<String, Set<String>> entry : defaultDmhMethods.entrySet()) { ! dmhMethods.put(entry.getKey(), new TreeSet<>(entry.getValue())); } ! fileLines(file) ! .map(line -> line.split(" ")) .forEach(parts -> { switch (parts[0]) { case "[BMH_RESOLVE]": speciesTypes.add(expandSignature(parts[1])); break; --- 163,246 ---- DMH_INVOKE_STATIC_INIT, 5 ); @Override public void configure(Map<String, String> config) { ! mainArgument = config.get(NAME); ! } ! ! public void initialize(ResourcePool in) { ! ModuleDescriptor.Version baseVersion = ! ModuleFinder.ofSystem() ! .find("java.base") ! .get() ! .descriptor() ! .version() ! .orElse(null); ! ModuleDescriptor.Version linkedVersion = ! in.moduleView() ! .findModule("java.base") ! .get() ! .descriptor() ! .version() ! .orElse(null); ! // When baseVersion is null, we are likely operating on a exploded image ! // during build and can assume the linked version is compatible - ! // otherwise check that the linked version is the same ! if (baseVersion != null && !baseVersion.equals(linkedVersion)) { ! throw new IllegalStateException("WARNING: Pre-generation of JLI " ! + "classes is only supported when linking the same version " ! + "of java.base (" + linkedVersion + ") as the VM tool " ! + "running jlink (" + baseVersion + ")"); ! } // Start with the default configuration ! speciesTypes = defaultSpecies().stream() .map(type -> expandSignature(type)) .collect(Collectors.toSet()); ! invokerTypes = defaultInvokers(); ! validateMethodTypes(invokerTypes); ! dmhMethods = defaultDMHMethods(); ! for (Set<String> dmhMethodTypes : dmhMethods.values()) { validateMethodTypes(dmhMethodTypes); } // Extend the default configuration with the contents in the supplied ! // input file - if none was supplied we look for the default file if (mainArgument == null || !mainArgument.startsWith("@")) { ! try (InputStream traceFile = ! this.getClass().getResourceAsStream(DEFAULT_TRACE_FILE)) { ! if (traceFile != null) { ! readTraceConfig( ! new BufferedReader( ! new InputStreamReader(traceFile)).lines()); ! } ! } catch (Exception e) { ! throw new PluginException("Couldn't read " + DEFAULT_TRACE_FILE, e); ! } } else { File file = new File(mainArgument.substring(1)); if (file.exists()) { + readTraceConfig(fileLines(file)); + } + } + } + + private void readTraceConfig(Stream<String> lines) { // Use TreeSet/TreeMap to keep things sorted in a deterministic // order to avoid scrambling the layout on small changes and to // ease finding methods in the generated code ! speciesTypes = new TreeSet<>(speciesTypes); ! invokerTypes = new TreeSet<>(invokerTypes); ! TreeMap<String, Set<String>> newDMHMethods = new TreeMap<>(); ! for (Map.Entry<String, Set<String>> entry : dmhMethods.entrySet()) { ! newDMHMethods.put(entry.getKey(), new TreeSet<>(entry.getValue())); } ! dmhMethods = newDMHMethods; ! lines.map(line -> line.split(" ")) .forEach(parts -> { switch (parts[0]) { case "[BMH_RESOLVE]": speciesTypes.add(expandSignature(parts[1])); break;
*** 215,226 **** break; default: break; // ignore } }); } - } - } private void addDMHMethodType(String dmh, String methodType) { validateMethodType(methodType); Set<String> methodTypes = dmhMethods.get(dmh); if (methodTypes == null) { --- 260,269 ----
*** 263,272 **** --- 306,323 ---- } } @Override public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { + try { + initialize(in); + } catch (IllegalStateException e) { + // The linked images is not compatible, log and shortcut + System.out.println(e.getMessage()); + in.transformAndCopy(entry -> entry, out); + return out.build(); + } // Copy all but DMH_ENTRY to out in.transformAndCopy(entry -> { // filter out placeholder entries if (entry.path().equals(DIRECT_METHOD_HOLDER_ENTRY) || entry.path().equals(DELEGATING_METHOD_HOLDER_ENTRY) ||
*** 275,286 **** --- 326,347 ---- return null; } else { return entry; } }, out); + + // Generate BMH Species classes speciesTypes.forEach(types -> generateBMHClass(types, out)); + + // Generate LambdaForm Holder classes generateHolderClasses(out); + + // Let it go + speciesTypes = null; + invokerTypes = null; + dmhMethods = null; + return out.build(); } @SuppressWarnings("unchecked") private void generateBMHClass(String types, ResourcePoolBuilder out) {
< prev index next >