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
49 * generate classes ahead of time.
50 */
51 class GenerateJLIClassesHelper {
52 // Map from DirectMethodHandle method type name to index to LambdaForms
53 static final Map<String, Integer> DMH_METHOD_TYPE_MAP =
54 Map.of(
412 MethodType[] methodTypes, int[] types) {
413 ArrayList<LambdaForm> forms = new ArrayList<>();
414 ArrayList<String> names = new ArrayList<>();
415 for (int i = 0; i < methodTypes.length; i++) {
416 // invokeVirtual and invokeInterface must have a leading Object
417 // parameter, i.e., the receiver
418 if (types[i] == LF_INVVIRTUAL || types[i] == LF_INVINTERFACE) {
419 if (methodTypes[i].parameterCount() < 1 ||
420 methodTypes[i].parameterType(0) != Object.class) {
421 throw new InternalError("Invalid method type for " +
422 (types[i] == LF_INVVIRTUAL ? "invokeVirtual" : "invokeInterface") +
423 " DMH, needs at least two leading reference arguments: " +
424 methodTypes[i]);
425 }
426 }
427
428 LambdaForm form = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], types[i]);
429 forms.add(form);
430 names.add(form.kind.defaultLambdaName);
431 }
432 for (Wrapper wrapper : Wrapper.values()) {
433 int ftype = wrapper == Wrapper.VOID ? DirectMethodHandle.FT_CHECKED_REF : DirectMethodHandle.ftypeKind(wrapper.primitiveType());
434 for (byte b = DirectMethodHandle.AF_GETFIELD; b < DirectMethodHandle.AF_LIMIT; b++) {
435 LambdaForm form = DirectMethodHandle
436 .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
437 if (form.kind == GENERIC)
438 throw new InternalError(b + " non-volatile " + ftype);
439 forms.add(form);
440 names.add(form.kind.defaultLambdaName);
441 // volatile
442 form = DirectMethodHandle
443 .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
444 if (form.kind == GENERIC)
445 throw new InternalError(b + " volatile " + ftype);
446 forms.add(form);
447 names.add(form.kind.defaultLambdaName);
448 }
449 }
450 return generateCodeBytesForLFs(className,
451 names.toArray(new String[0]),
452 forms.toArray(new LambdaForm[0]));
453 }
454
455 /**
456 * Returns a {@code byte[]} representation of a class implementing
457 * DelegatingMethodHandles of each {@code MethodType} kind in the
458 * {@code methodTypes} argument.
459 */
460 static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
461 MethodType[] methodTypes) {
462
463 HashSet<MethodType> dedupSet = new HashSet<>();
464 ArrayList<LambdaForm> forms = new ArrayList<>();
465 ArrayList<String> names = new ArrayList<>();
466 for (int i = 0; i < methodTypes.length; i++) {
467 // generate methods representing the DelegatingMethodHandle
468 if (dedupSet.add(methodTypes[i])) {
469 // reinvokers are variant with the associated SpeciesData
|
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.List;
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
50 * generate classes ahead of time.
51 */
52 class GenerateJLIClassesHelper {
53 // Map from DirectMethodHandle method type name to index to LambdaForms
54 static final Map<String, Integer> DMH_METHOD_TYPE_MAP =
55 Map.of(
413 MethodType[] methodTypes, int[] types) {
414 ArrayList<LambdaForm> forms = new ArrayList<>();
415 ArrayList<String> names = new ArrayList<>();
416 for (int i = 0; i < methodTypes.length; i++) {
417 // invokeVirtual and invokeInterface must have a leading Object
418 // parameter, i.e., the receiver
419 if (types[i] == LF_INVVIRTUAL || types[i] == LF_INVINTERFACE) {
420 if (methodTypes[i].parameterCount() < 1 ||
421 methodTypes[i].parameterType(0) != Object.class) {
422 throw new InternalError("Invalid method type for " +
423 (types[i] == LF_INVVIRTUAL ? "invokeVirtual" : "invokeInterface") +
424 " DMH, needs at least two leading reference arguments: " +
425 methodTypes[i]);
426 }
427 }
428
429 LambdaForm form = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], types[i]);
430 forms.add(form);
431 names.add(form.kind.defaultLambdaName);
432 }
433 record FieldLfToken(byte formOp, int ftypeKind) {}
434 List<FieldLfToken> tokens = new ArrayList<>();
435 for (int i = 0; i <= DirectMethodHandle.FT_CHECKED_REF; i++) {
436 for (byte formOp = DirectMethodHandle.AF_GETFIELD; formOp < DirectMethodHandle.AF_LIMIT; formOp++) {
437 tokens.add(new FieldLfToken(formOp, i));
438 }
439 }
440 for (int i : new int[] {DirectMethodHandle.FT_UNCHECKED_NR_REF, DirectMethodHandle.FT_CHECKED_NR_REF}) {
441 for (byte formOp = DirectMethodHandle.AF_GETFIELD; formOp < DirectMethodHandle.AF_LIMIT; formOp++) {
442 boolean isGetter = (formOp & 1) == (DirectMethodHandle.AF_GETFIELD & 1);
443 if (!isGetter) {
444 tokens.add(new FieldLfToken(formOp, i));
445 }
446 }
447 }
448 // Only legal flat combinations; no static
449 tokens.add(new FieldLfToken(DirectMethodHandle.AF_GETFIELD, DirectMethodHandle.FT_NULLABLE_FLAT));
450 tokens.add(new FieldLfToken(DirectMethodHandle.AF_PUTFIELD, DirectMethodHandle.FT_NULLABLE_FLAT));
451 tokens.add(new FieldLfToken(DirectMethodHandle.AF_PUTFIELD, DirectMethodHandle.FT_NR_FLAT));
452 // Compile
453 for (var token : tokens) {
454 byte b = token.formOp;
455 int ftype = token.ftypeKind;
456 LambdaForm form = DirectMethodHandle
457 .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
458 if (form.kind == GENERIC)
459 throw new InternalError(b + " non-volatile " + ftype);
460 forms.add(form);
461 names.add(form.kind.defaultLambdaName);
462 // volatile
463 form = DirectMethodHandle
464 .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
465 if (form.kind == GENERIC)
466 throw new InternalError(b + " volatile " + ftype);
467 forms.add(form);
468 names.add(form.kind.defaultLambdaName);
469 }
470 return generateCodeBytesForLFs(className,
471 names.toArray(new String[0]),
472 forms.toArray(new LambdaForm[0]));
473 }
474
475 /**
476 * Returns a {@code byte[]} representation of a class implementing
477 * DelegatingMethodHandles of each {@code MethodType} kind in the
478 * {@code methodTypes} argument.
479 */
480 static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
481 MethodType[] methodTypes) {
482
483 HashSet<MethodType> dedupSet = new HashSet<>();
484 ArrayList<LambdaForm> forms = new ArrayList<>();
485 ArrayList<String> names = new ArrayList<>();
486 for (int i = 0; i < methodTypes.length; i++) {
487 // generate methods representing the DelegatingMethodHandle
488 if (dedupSet.add(methodTypes[i])) {
489 // reinvokers are variant with the associated SpeciesData
|