9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import sun.invoke.util.Wrapper;
29
30 import java.lang.classfile.ClassFile;
31 import java.lang.classfile.attribute.SourceFileAttribute;
32 import java.lang.constant.ClassDesc;
33 import java.util.ArrayList;
34 import java.util.HashSet;
35 import java.util.Map;
36 import java.util.Objects;
37 import java.util.Set;
38 import java.util.TreeMap;
39 import java.util.TreeSet;
40 import java.util.stream.Stream;
41
42 import static java.lang.classfile.ClassFile.*;
43 import static java.lang.invoke.LambdaForm.BasicType.*;
44 import static java.lang.invoke.LambdaForm.Kind.*;
45 import static java.lang.invoke.MethodTypeForm.*;
46
47 /**
48 * Helper class to assist the GenerateJLIClassesPlugin to get access to
56 DIRECT_INVOKE_STATIC.methodName, LF_INVSTATIC,
57 DIRECT_INVOKE_SPECIAL.methodName, LF_INVSPECIAL,
58 DIRECT_NEW_INVOKE_SPECIAL.methodName, LF_NEWINVSPECIAL,
59 DIRECT_INVOKE_INTERFACE.methodName, LF_INVINTERFACE,
60 DIRECT_INVOKE_STATIC_INIT.methodName, LF_INVSTATIC_INIT,
61 DIRECT_INVOKE_SPECIAL_IFC.methodName, LF_INVSPECIAL_IFC
62 );
63
64 static final String DIRECT_HOLDER = "java/lang/invoke/DirectMethodHandle$Holder";
65 static final String DELEGATING_HOLDER = "java/lang/invoke/DelegatingMethodHandle$Holder";
66 static final String BASIC_FORMS_HOLDER = "java/lang/invoke/LambdaForm$Holder";
67 static final String INVOKERS_HOLDER = "java/lang/invoke/Invokers$Holder";
68 static final String INVOKERS_HOLDER_CLASS_NAME = INVOKERS_HOLDER.replace('/', '.');
69 static final String BMH_SPECIES_PREFIX = "java.lang.invoke.BoundMethodHandle$Species_";
70
71 static class HolderClassBuilder {
72
73
74 private final TreeSet<String> speciesTypes = new TreeSet<>();
75 private final TreeSet<String> invokerTypes = new TreeSet<>();
76 private final TreeSet<String> linkerTypes = new TreeSet<>();
77 private final TreeSet<String> callSiteTypes = new TreeSet<>();
78 private final Map<String, Set<String>> dmhMethods = new TreeMap<>();
79
80 HolderClassBuilder addSpeciesType(String type) {
81 speciesTypes.add(expandSignature(type));
82 return this;
83 }
84
85 HolderClassBuilder addInvokerType(String methodType) {
86 validateMethodType(methodType);
87 invokerTypes.add(methodType);
88 return this;
89 }
90
91 HolderClassBuilder addLinkerType(String methodType) {
92 validateMethodType(methodType);
93 linkerTypes.add(methodType);
94 return this;
95 }
96
97 HolderClassBuilder addCallSiteType(String csType) {
98 validateMethodType(csType);
99 callSiteTypes.add(csType);
100 return this;
101 }
102
103 Map<String, byte[]> build() {
104 int count = 0;
105 for (Set<String> entry : dmhMethods.values()) {
106 count += entry.size();
107 }
108 MethodType[] directMethodTypes = new MethodType[count];
109 int[] dmhTypes = new int[count];
110 int index = 0;
111 for (Map.Entry<String, Set<String>> entry : dmhMethods.entrySet()) {
112 String dmhType = entry.getKey();
113 for (String type : entry.getValue()) {
114 // The DMH type to actually ask for is retrieved by removing
115 // the first argument, which needs to be of Object.class
116 MethodType mt = asMethodType(type);
117 if (mt.parameterCount() < 1 ||
118 mt.parameterType(0) != Object.class) {
119 throw new RuntimeException(
120 "DMH type parameter must start with L: " + dmhType + " " + type);
121 }
122
123 // Adapt the method type of the LF to retrieve
124 directMethodTypes[index] = mt.dropParameterTypes(0, 1);
125
126 // invokeVirtual and invokeInterface must have a leading Object
127 // parameter, i.e., the receiver
128 dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType);
129 if (dmhTypes[index] == LF_INVINTERFACE || dmhTypes[index] == LF_INVVIRTUAL) {
130 if (mt.parameterCount() < 2 ||
131 mt.parameterType(1) != Object.class) {
132 throw new RuntimeException(
133 "DMH type parameter must start with LL: " + dmhType + " " + type);
134 }
135 }
136 index++;
137 }
138 }
139
140 // The linker type to ask for is retrieved by removing the first
141 // and the last argument, which needs to be of Object.class
142 MethodType[] linkerMethodTypes = new MethodType[linkerTypes.size()];
143 index = 0;
144 for (String linkerType : linkerTypes) {
145 MethodType mt = asMethodType(linkerType);
146 final int lastParam = mt.parameterCount() - 1;
147 if (!checkLinkerTypeParams(mt)) {
148 throw new RuntimeException(
149 "Linker type parameter must start and end with Object: " + linkerType);
150 }
151 mt = mt.dropParameterTypes(lastParam, lastParam + 1);
152 linkerMethodTypes[index] = mt.dropParameterTypes(0, 1);
153 index++;
154 }
155
156 // The invoker type to ask for is retrieved by removing the first
157 // argument, which needs to be of Object.class
158 MethodType[] invokerMethodTypes = new MethodType[invokerTypes.size()];
159 index = 0;
160 for (String invokerType : invokerTypes) {
161 MethodType mt = asMethodType(invokerType);
162 if (!checkInvokerTypeParams(mt)) {
163 throw new RuntimeException(
164 "Invoker type parameter must start with 2 Objects: " + invokerType);
165 }
166 invokerMethodTypes[index] = mt.dropParameterTypes(0, 2);
167 index++;
168 }
169
170 // The callSite type to ask for is retrieved by removing the last
171 // argument, which needs to be of Object.class
172 MethodType[] callSiteMethodTypes = new MethodType[callSiteTypes.size()];
173 index = 0;
174 for (String callSiteType : callSiteTypes) {
175 MethodType mt = asMethodType(callSiteType);
176 final int lastParam = mt.parameterCount() - 1;
177 if (mt.parameterCount() < 1 ||
178 mt.parameterType(lastParam) != Object.class) {
179 throw new RuntimeException(
180 "CallSite type parameter must end with Object: " + callSiteType);
181 }
182 callSiteMethodTypes[index] = mt.dropParameterTypes(lastParam, lastParam + 1);
183 index++;
184 }
185
186 Map<String, byte[]> result = new TreeMap<>();
187 result.put(DIRECT_HOLDER,
188 generateDirectMethodHandleHolderClassBytes(
189 DIRECT_HOLDER, directMethodTypes, dmhTypes));
190 result.put(DELEGATING_HOLDER,
191 generateDelegatingMethodHandleHolderClassBytes(
192 DELEGATING_HOLDER, directMethodTypes));
193 result.put(INVOKERS_HOLDER,
194 generateInvokersHolderClassBytes(INVOKERS_HOLDER,
195 linkerMethodTypes, invokerMethodTypes, callSiteMethodTypes));
196 result.put(BASIC_FORMS_HOLDER,
197 generateBasicFormsClassBytes(BASIC_FORMS_HOLDER));
198
199 speciesTypes.forEach(types -> {
200 Map.Entry<String, byte[]> entry = generateConcreteBMHClassBytes(types);
201 result.put(entry.getKey(), entry.getValue());
202 });
203
204 // clear builder
205 speciesTypes.clear();
206 invokerTypes.clear();
207 callSiteTypes.clear();
208 dmhMethods.clear();
209
210 return result;
211 }
212
213 public static MethodType asMethodType(String basicSignatureString) {
214 String[] parts = basicSignatureString.split("_");
215 assert (parts.length == 2);
216 assert (parts[1].length() == 1);
217 String parameters = expandSignature(parts[0]);
218 Class<?> rtype = simpleType(parts[1].charAt(0));
219 if (parameters.isEmpty()) {
220 return MethodType.methodType(rtype);
221 } else {
222 Class<?>[] ptypes = new Class<?>[parameters.length()];
223 for (int i = 0; i < ptypes.length; i++) {
224 ptypes[i] = simpleType(parameters.charAt(i));
225 }
226 return MethodType.methodType(rtype, ptypes);
227 }
228 }
229
230 public static boolean checkInvokerTypeParams(MethodType mt) {
231 return (mt.parameterCount() >= 2 &&
232 mt.parameterType(0) == Object.class &&
233 mt.parameterType(1) == Object.class);
234 }
235
236 public static boolean checkLinkerTypeParams(MethodType mt) {
237 final int lastParam = mt.parameterCount() - 1;
238 return (mt.parameterCount() >= 2 &&
239 mt.parameterType(0) == Object.class &&
240 mt.parameterType(lastParam) == Object.class);
241 }
242
243 private void addDMHMethodType(String dmh, String methodType) {
244 validateMethodType(methodType);
245 Set<String> methodTypes = dmhMethods.get(dmh);
246 if (methodTypes == null) {
247 methodTypes = new TreeSet<>();
248 dmhMethods.put(dmh, methodTypes);
249 }
250 methodTypes.add(methodType);
251 }
252
253 private static void validateMethodType(String type) {
254 String[] typeParts = type.split("_");
255 // check return type (second part)
256 if (typeParts.length != 2 || typeParts[1].length() != 1
330 traces.map(line -> line.split(" "))
331 .forEach(parts -> {
332 switch (parts[0]) {
333 case "[SPECIES_RESOLVE]":
334 // Allow for new types of species data classes being resolved here
335 assert parts.length >= 2;
336 if (parts[1].startsWith(BMH_SPECIES_PREFIX)) {
337 String species = parts[1].substring(BMH_SPECIES_PREFIX.length());
338 if (!"L".equals(species)) {
339 builder.addSpeciesType(species);
340 }
341 }
342 break;
343 case "[LF_RESOLVE]":
344 assert parts.length > 3;
345 String methodType = parts[3];
346 if (parts[1].equals(INVOKERS_HOLDER_CLASS_NAME)) {
347 if ("linkToTargetMethod".equals(parts[2]) ||
348 "linkToCallSite".equals(parts[2])) {
349 builder.addCallSiteType(methodType);
350 } else if (parts[2].endsWith("nvoker")) {
351 // MH.exactInvoker exactInvoker MH.invoker invoker
352 builder.addInvokerType(methodType);
353 } else {
354 builder.addLinkerType(methodType);
355 }
356 } else if (parts[1].contains("DirectMethodHandle")) {
357 String dmh = parts[2];
358 // ignore getObject etc for now (generated by default)
359 if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) {
360 builder.addDMHMethodType(dmh, methodType);
361 }
362 }
363 break;
364 default:
365 break; // ignore
366 }
367 });
368
369 return builder.build();
370 }
371
372 /**
373 * Returns a {@code byte[]} representation of a class implementing
374 * the zero and identity forms of all {@code LambdaForm.BasicType}s.
471 // may want to consider pregenerating more of these, which will
472 // require an even more complex naming scheme
473 LambdaForm reinvoker = makeReinvokerFor(methodTypes[i]);
474 forms.add(reinvoker);
475 String speciesSig = BoundMethodHandle.speciesDataFor(reinvoker).key();
476 assert(speciesSig.equals("L"));
477 names.add(reinvoker.kind.defaultLambdaName + "_" + speciesSig);
478
479 LambdaForm delegate = makeDelegateFor(methodTypes[i]);
480 forms.add(delegate);
481 names.add(delegate.kind.defaultLambdaName);
482 }
483 }
484 return generateCodeBytesForLFs(className,
485 names.toArray(new String[0]),
486 forms.toArray(new LambdaForm[0]));
487 }
488
489 /**
490 * Returns a {@code byte[]} representation of a class implementing
491 * the invoker forms for the set of supplied {@code linkerMethodTypes}
492 * {@code invokerMethodTypes}, and {@code callSiteMethodTypes}.
493 */
494 static byte[] generateInvokersHolderClassBytes(String className,
495 MethodType[] linkerMethodTypes, MethodType[] invokerMethodTypes,
496 MethodType[] callSiteMethodTypes) {
497
498 HashSet<MethodType> dedupSet = new HashSet<>();
499 ArrayList<LambdaForm> forms = new ArrayList<>();
500 ArrayList<String> names = new ArrayList<>();
501
502 int[] invokerTypes = {
503 MethodTypeForm.LF_EX_INVOKER,
504 MethodTypeForm.LF_GEN_INVOKER,
505 };
506
507 for (MethodType methodType : invokerMethodTypes) {
508 // generate methods representing invokers of the specified type
509 if (dedupSet.add(methodType)) {
510 for (int type : invokerTypes) {
511 LambdaForm invokerForm = Invokers.invokeHandleForm(methodType,
512 /*customized*/false, type);
513 forms.add(invokerForm);
514 names.add(invokerForm.kind.defaultLambdaName);
515 }
516 }
517 }
518
519 int[] linkerTypes = {
520 MethodTypeForm.LF_EX_LINKER,
521 MethodTypeForm.LF_GEN_LINKER,
522 };
523
524 dedupSet = new HashSet<>();
525 for (MethodType methodType : linkerMethodTypes) {
526 // generate methods representing linkers of the specified type
527 if (dedupSet.add(methodType)) {
528 for (int type : linkerTypes) {
529 LambdaForm linkerForm = Invokers.invokeHandleForm(methodType,
530 /*customized*/false, type);
531 forms.add(linkerForm);
532 names.add(linkerForm.kind.defaultLambdaName);
533 }
534 }
535 }
536
537 dedupSet = new HashSet<>();
538 for (int i = 0; i < callSiteMethodTypes.length; i++) {
539 // generate methods representing invokers of the specified type
540 if (dedupSet.add(callSiteMethodTypes[i])) {
541 LambdaForm callSiteForm = Invokers.callSiteForm(callSiteMethodTypes[i], true);
542 forms.add(callSiteForm);
543 names.add(callSiteForm.kind.defaultLambdaName);
544
545 LambdaForm methodHandleForm = Invokers.callSiteForm(callSiteMethodTypes[i], false);
546 forms.add(methodHandleForm);
547 names.add(methodHandleForm.kind.defaultLambdaName);
548 }
549 }
550
551 return generateCodeBytesForLFs(className,
552 names.toArray(new String[0]),
553 forms.toArray(new LambdaForm[0]));
554 }
555
556 /*
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import sun.invoke.util.Wrapper;
29 import sun.util.logging.PlatformLogger;
30
31 import java.lang.classfile.ClassFile;
32 import java.lang.classfile.attribute.SourceFileAttribute;
33 import java.lang.constant.ClassDesc;
34 import java.util.ArrayList;
35 import java.util.HashSet;
36 import java.util.Map;
37 import java.util.Objects;
38 import java.util.Set;
39 import java.util.TreeMap;
40 import java.util.TreeSet;
41 import java.util.stream.Stream;
42
43 import static java.lang.classfile.ClassFile.*;
44 import static java.lang.invoke.LambdaForm.BasicType.*;
45 import static java.lang.invoke.LambdaForm.Kind.*;
46 import static java.lang.invoke.MethodTypeForm.*;
47
48 /**
49 * Helper class to assist the GenerateJLIClassesPlugin to get access to
57 DIRECT_INVOKE_STATIC.methodName, LF_INVSTATIC,
58 DIRECT_INVOKE_SPECIAL.methodName, LF_INVSPECIAL,
59 DIRECT_NEW_INVOKE_SPECIAL.methodName, LF_NEWINVSPECIAL,
60 DIRECT_INVOKE_INTERFACE.methodName, LF_INVINTERFACE,
61 DIRECT_INVOKE_STATIC_INIT.methodName, LF_INVSTATIC_INIT,
62 DIRECT_INVOKE_SPECIAL_IFC.methodName, LF_INVSPECIAL_IFC
63 );
64
65 static final String DIRECT_HOLDER = "java/lang/invoke/DirectMethodHandle$Holder";
66 static final String DELEGATING_HOLDER = "java/lang/invoke/DelegatingMethodHandle$Holder";
67 static final String BASIC_FORMS_HOLDER = "java/lang/invoke/LambdaForm$Holder";
68 static final String INVOKERS_HOLDER = "java/lang/invoke/Invokers$Holder";
69 static final String INVOKERS_HOLDER_CLASS_NAME = INVOKERS_HOLDER.replace('/', '.');
70 static final String BMH_SPECIES_PREFIX = "java.lang.invoke.BoundMethodHandle$Species_";
71
72 static class HolderClassBuilder {
73
74
75 private final TreeSet<String> speciesTypes = new TreeSet<>();
76 private final TreeSet<String> invokerTypes = new TreeSet<>();
77 private final TreeSet<String> callSiteTypes = new TreeSet<>();
78 private final Map<String, Set<String>> dmhMethods = new TreeMap<>();
79
80 HolderClassBuilder addSpeciesType(String type) {
81 speciesTypes.add(expandSignature(type));
82 return this;
83 }
84
85 HolderClassBuilder addInvokerType(String methodType) {
86 validateMethodType(methodType);
87 invokerTypes.add(methodType);
88 return this;
89 }
90
91 HolderClassBuilder addCallSiteType(String csType) {
92 validateMethodType(csType);
93 callSiteTypes.add(csType);
94 return this;
95 }
96
97 Map<String, byte[]> build() {
98 int count = 0;
99 for (Set<String> entry : dmhMethods.values()) {
100 count += entry.size();
101 }
102 MethodType[] directMethodTypes = new MethodType[count];
103 int[] dmhTypes = new int[count];
104 int index = 0;
105 for (Map.Entry<String, Set<String>> entry : dmhMethods.entrySet()) {
106 String dmhType = entry.getKey();
107 for (String type : entry.getValue()) {
108 // The DMH type to actually ask for is retrieved by removing
109 // the first argument, which needs to be of Object.class
110 MethodType mt = asMethodType(type);
111 if (mt.parameterCount() < 1 ||
112 mt.parameterType(0) != Object.class) {
113 throw new RuntimeException(
114 "DMH type parameter must start with L: " + dmhType + " " + type);
115 }
116 // Adapt the method type of the LF to retrieve
117 directMethodTypes[index] = mt.dropParameterTypes(0, 1);
118 // invokeVirtual and invokeInterface must have a leading Object
119 // parameter, i.e., the receiver
120 dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType);
121 if (dmhTypes[index] == LF_INVINTERFACE || dmhTypes[index] == LF_INVVIRTUAL) {
122 if (mt.parameterCount() < 2 ||
123 mt.parameterType(1) != Object.class) {
124 throw new RuntimeException(
125 "DMH type parameter must start with LL: " + dmhType + " " + type);
126 }
127 }
128 index++;
129 }
130 }
131
132 // The invoker type to ask for is retrieved by removing the first
133 // and the last argument, which needs to be of Object.class
134 MethodType[] invokerMethodTypes = new MethodType[invokerTypes.size()];
135 index = 0;
136 for (String invokerType : invokerTypes) {
137 MethodType mt = asMethodType(invokerType);
138 final int lastParam = mt.parameterCount() - 1;
139 if (!checkInvokerTypeParams(mt)) {
140 throw new RuntimeException(
141 "Invoker type parameter must start and end with Object: " + invokerType);
142 }
143 mt = mt.dropParameterTypes(lastParam, lastParam + 1);
144 invokerMethodTypes[index] = mt.dropParameterTypes(0, 1);
145 index++;
146 }
147
148 // The callSite type to ask for is retrieved by removing the last
149 // argument, which needs to be of Object.class
150 MethodType[] callSiteMethodTypes = new MethodType[callSiteTypes.size()];
151 index = 0;
152 for (String callSiteType : callSiteTypes) {
153 MethodType mt = asMethodType(callSiteType);
154 final int lastParam = mt.parameterCount() - 1;
155 if (mt.parameterCount() < 1 ||
156 mt.parameterType(lastParam) != Object.class) {
157 throw new RuntimeException(
158 "CallSite type parameter must end with Object: " + callSiteType);
159 }
160 callSiteMethodTypes[index] = mt.dropParameterTypes(lastParam, lastParam + 1);
161 index++;
162 }
163 Map<String, byte[]> result = new TreeMap<>();
164 result.put(DIRECT_HOLDER,
165 generateDirectMethodHandleHolderClassBytes(
166 DIRECT_HOLDER, directMethodTypes, dmhTypes));
167 result.put(DELEGATING_HOLDER,
168 generateDelegatingMethodHandleHolderClassBytes(
169 DELEGATING_HOLDER, directMethodTypes));
170 result.put(INVOKERS_HOLDER,
171 generateInvokersHolderClassBytes(INVOKERS_HOLDER,
172 invokerMethodTypes, callSiteMethodTypes));
173 result.put(BASIC_FORMS_HOLDER,
174 generateBasicFormsClassBytes(BASIC_FORMS_HOLDER));
175
176 speciesTypes.forEach(types -> {
177 Map.Entry<String, byte[]> entry = generateConcreteBMHClassBytes(types);
178 result.put(entry.getKey(), entry.getValue());
179 });
180 // clear builder
181 speciesTypes.clear();
182 invokerTypes.clear();
183 callSiteTypes.clear();
184 dmhMethods.clear();
185 return result;
186 }
187
188 public static MethodType asMethodType(String basicSignatureString) {
189 String[] parts = basicSignatureString.split("_");
190 assert (parts.length == 2);
191 assert (parts[1].length() == 1);
192 String parameters = expandSignature(parts[0]);
193 Class<?> rtype = simpleType(parts[1].charAt(0));
194 if (parameters.isEmpty()) {
195 return MethodType.methodType(rtype);
196 } else {
197 Class<?>[] ptypes = new Class<?>[parameters.length()];
198 for (int i = 0; i < ptypes.length; i++) {
199 ptypes[i] = simpleType(parameters.charAt(i));
200 }
201 return MethodType.methodType(rtype, ptypes);
202 }
203 }
204
205 public static boolean checkInvokerTypeParams(MethodType mt) {
206 final int lastParam = mt.parameterCount() - 1;
207 return (mt.parameterCount() >= 2 &&
208 mt.parameterType(0) == Object.class &&
209 mt.parameterType(lastParam) == Object.class);
210 }
211
212 private void addDMHMethodType(String dmh, String methodType) {
213 validateMethodType(methodType);
214 Set<String> methodTypes = dmhMethods.get(dmh);
215 if (methodTypes == null) {
216 methodTypes = new TreeSet<>();
217 dmhMethods.put(dmh, methodTypes);
218 }
219 methodTypes.add(methodType);
220 }
221
222 private static void validateMethodType(String type) {
223 String[] typeParts = type.split("_");
224 // check return type (second part)
225 if (typeParts.length != 2 || typeParts[1].length() != 1
299 traces.map(line -> line.split(" "))
300 .forEach(parts -> {
301 switch (parts[0]) {
302 case "[SPECIES_RESOLVE]":
303 // Allow for new types of species data classes being resolved here
304 assert parts.length >= 2;
305 if (parts[1].startsWith(BMH_SPECIES_PREFIX)) {
306 String species = parts[1].substring(BMH_SPECIES_PREFIX.length());
307 if (!"L".equals(species)) {
308 builder.addSpeciesType(species);
309 }
310 }
311 break;
312 case "[LF_RESOLVE]":
313 assert parts.length > 3;
314 String methodType = parts[3];
315 if (parts[1].equals(INVOKERS_HOLDER_CLASS_NAME)) {
316 if ("linkToTargetMethod".equals(parts[2]) ||
317 "linkToCallSite".equals(parts[2])) {
318 builder.addCallSiteType(methodType);
319 } else {
320 MethodType mt = HolderClassBuilder.asMethodType(methodType);
321 // Work around JDK-8327499
322 if (HolderClassBuilder.checkInvokerTypeParams(mt)) {
323 builder.addInvokerType(methodType);
324 } else {
325 PlatformLogger.getLogger("java.lang.invoke")
326 .warning("Invalid LF_RESOLVE " + parts[1] + " " + parts[2] + " " + parts[3]);
327 }
328 }
329 } else if (parts[1].contains("DirectMethodHandle")) {
330 String dmh = parts[2];
331 // ignore getObject etc for now (generated by default)
332 if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) {
333 builder.addDMHMethodType(dmh, methodType);
334 }
335 }
336 break;
337 default:
338 break; // ignore
339 }
340 });
341
342 return builder.build();
343 }
344
345 /**
346 * Returns a {@code byte[]} representation of a class implementing
347 * the zero and identity forms of all {@code LambdaForm.BasicType}s.
444 // may want to consider pregenerating more of these, which will
445 // require an even more complex naming scheme
446 LambdaForm reinvoker = makeReinvokerFor(methodTypes[i]);
447 forms.add(reinvoker);
448 String speciesSig = BoundMethodHandle.speciesDataFor(reinvoker).key();
449 assert(speciesSig.equals("L"));
450 names.add(reinvoker.kind.defaultLambdaName + "_" + speciesSig);
451
452 LambdaForm delegate = makeDelegateFor(methodTypes[i]);
453 forms.add(delegate);
454 names.add(delegate.kind.defaultLambdaName);
455 }
456 }
457 return generateCodeBytesForLFs(className,
458 names.toArray(new String[0]),
459 forms.toArray(new LambdaForm[0]));
460 }
461
462 /**
463 * Returns a {@code byte[]} representation of a class implementing
464 * the invoker forms for the set of supplied {@code invokerMethodTypes}
465 * and {@code callSiteMethodTypes}.
466 */
467 static byte[] generateInvokersHolderClassBytes(String className,
468 MethodType[] invokerMethodTypes, MethodType[] callSiteMethodTypes) {
469
470 HashSet<MethodType> dedupSet = new HashSet<>();
471 ArrayList<LambdaForm> forms = new ArrayList<>();
472 ArrayList<String> names = new ArrayList<>();
473 int[] types = {
474 MethodTypeForm.LF_EX_LINKER,
475 MethodTypeForm.LF_EX_INVOKER,
476 MethodTypeForm.LF_GEN_LINKER,
477 MethodTypeForm.LF_GEN_INVOKER
478 };
479
480 for (int i = 0; i < invokerMethodTypes.length; i++) {
481 // generate methods representing invokers of the specified type
482 if (dedupSet.add(invokerMethodTypes[i])) {
483 for (int type : types) {
484 LambdaForm invokerForm = Invokers.invokeHandleForm(invokerMethodTypes[i],
485 /*customized*/false, type);
486 forms.add(invokerForm);
487 names.add(invokerForm.kind.defaultLambdaName);
488 }
489 }
490 }
491
492 dedupSet = new HashSet<>();
493 for (int i = 0; i < callSiteMethodTypes.length; i++) {
494 // generate methods representing invokers of the specified type
495 if (dedupSet.add(callSiteMethodTypes[i])) {
496 LambdaForm callSiteForm = Invokers.callSiteForm(callSiteMethodTypes[i], true);
497 forms.add(callSiteForm);
498 names.add(callSiteForm.kind.defaultLambdaName);
499
500 LambdaForm methodHandleForm = Invokers.callSiteForm(callSiteMethodTypes[i], false);
501 forms.add(methodHandleForm);
502 names.add(methodHandleForm.kind.defaultLambdaName);
503 }
504 }
505
506 return generateCodeBytesForLFs(className,
507 names.toArray(new String[0]),
508 forms.toArray(new LambdaForm[0]));
509 }
510
511 /*
|