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 jdk.internal.vm.annotation.AOTSafeClassInitializer;
29 import sun.invoke.util.Wrapper;
30
31 import java.lang.classfile.Annotation;
32 import java.lang.classfile.ClassFile;
33 import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
34 import java.lang.classfile.attribute.SourceFileAttribute;
35 import java.lang.constant.ClassDesc;
36 import java.util.ArrayList;
37 import java.util.HashSet;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.Set;
41 import java.util.TreeMap;
42 import java.util.TreeSet;
43 import java.util.stream.Stream;
44
45 import static java.lang.classfile.ClassFile.*;
46 import static java.lang.invoke.LambdaForm.BasicType.*;
47 import static java.lang.invoke.LambdaForm.Kind.*;
48 import static java.lang.invoke.MethodTypeForm.*;
49
50 /// Generates bound method handle species classes, and classes with methods that
51 /// hold compiled lambda form bytecode ahead of time, so certain lambda forms
52 /// no longer need to spin classes because they can find existing bytecode.
53 /// Bytecode pre-generation reduces static initialization costs, footprint costs,
54 /// and circular dependencies that may arise if a class is generated per
55 /// LambdaForm by [InvokerBytecodeGenerator].
56 ///
57 /// Since lambda forms and bound method handle species are closely tied to
487 MethodType[] methodTypes, int[] types) {
488 ArrayList<LambdaForm> forms = new ArrayList<>();
489 ArrayList<String> names = new ArrayList<>();
490 for (int i = 0; i < methodTypes.length; i++) {
491 // invokeVirtual and invokeInterface must have a leading Object
492 // parameter, i.e., the receiver
493 if (types[i] == LF_INVVIRTUAL || types[i] == LF_INVINTERFACE) {
494 if (methodTypes[i].parameterCount() < 1 ||
495 methodTypes[i].parameterType(0) != Object.class) {
496 throw new InternalError("Invalid method type for " +
497 (types[i] == LF_INVVIRTUAL ? "invokeVirtual" : "invokeInterface") +
498 " DMH, needs at least two leading reference arguments: " +
499 methodTypes[i]);
500 }
501 }
502
503 LambdaForm form = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], types[i]);
504 forms.add(form);
505 names.add(form.kind.defaultLambdaName);
506 }
507 for (Wrapper wrapper : Wrapper.values()) {
508 int ftype = wrapper == Wrapper.VOID ? DirectMethodHandle.FT_CHECKED_REF : DirectMethodHandle.ftypeKind(wrapper.primitiveType());
509 for (byte b = DirectMethodHandle.AF_GETFIELD; b < DirectMethodHandle.AF_LIMIT; b++) {
510 LambdaForm form = DirectMethodHandle
511 .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
512 if (form.kind == GENERIC)
513 throw new InternalError(b + " non-volatile " + ftype);
514 forms.add(form);
515 names.add(form.kind.defaultLambdaName);
516 // volatile
517 form = DirectMethodHandle
518 .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
519 if (form.kind == GENERIC)
520 throw new InternalError(b + " volatile " + ftype);
521 forms.add(form);
522 names.add(form.kind.defaultLambdaName);
523 }
524 }
525 return generateCodeBytesForLFs(className,
526 names.toArray(new String[0]),
527 forms.toArray(new LambdaForm[0]));
528 }
529
530 /**
531 * Returns a {@code byte[]} representation of a class implementing
532 * DelegatingMethodHandles of each {@code MethodType} kind in the
533 * {@code methodTypes} argument.
534 */
535 static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
536 MethodType[] methodTypes) {
537
538 HashSet<MethodType> dedupSet = new HashSet<>();
539 ArrayList<LambdaForm> forms = new ArrayList<>();
540 ArrayList<String> names = new ArrayList<>();
541 for (int i = 0; i < methodTypes.length; i++) {
542 // generate methods representing the DelegatingMethodHandle
543 if (dedupSet.add(methodTypes[i])) {
544 // reinvokers are variant with the associated SpeciesData
|
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 jdk.internal.vm.annotation.AOTSafeClassInitializer;
29 import sun.invoke.util.Wrapper;
30
31 import java.lang.classfile.Annotation;
32 import java.lang.classfile.ClassFile;
33 import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
34 import java.lang.classfile.attribute.SourceFileAttribute;
35 import java.lang.constant.ClassDesc;
36 import java.util.ArrayList;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Objects;
41 import java.util.Set;
42 import java.util.TreeMap;
43 import java.util.TreeSet;
44 import java.util.stream.Stream;
45
46 import static java.lang.classfile.ClassFile.*;
47 import static java.lang.invoke.LambdaForm.BasicType.*;
48 import static java.lang.invoke.LambdaForm.Kind.*;
49 import static java.lang.invoke.MethodTypeForm.*;
50
51 /// Generates bound method handle species classes, and classes with methods that
52 /// hold compiled lambda form bytecode ahead of time, so certain lambda forms
53 /// no longer need to spin classes because they can find existing bytecode.
54 /// Bytecode pre-generation reduces static initialization costs, footprint costs,
55 /// and circular dependencies that may arise if a class is generated per
56 /// LambdaForm by [InvokerBytecodeGenerator].
57 ///
58 /// Since lambda forms and bound method handle species are closely tied to
488 MethodType[] methodTypes, int[] types) {
489 ArrayList<LambdaForm> forms = new ArrayList<>();
490 ArrayList<String> names = new ArrayList<>();
491 for (int i = 0; i < methodTypes.length; i++) {
492 // invokeVirtual and invokeInterface must have a leading Object
493 // parameter, i.e., the receiver
494 if (types[i] == LF_INVVIRTUAL || types[i] == LF_INVINTERFACE) {
495 if (methodTypes[i].parameterCount() < 1 ||
496 methodTypes[i].parameterType(0) != Object.class) {
497 throw new InternalError("Invalid method type for " +
498 (types[i] == LF_INVVIRTUAL ? "invokeVirtual" : "invokeInterface") +
499 " DMH, needs at least two leading reference arguments: " +
500 methodTypes[i]);
501 }
502 }
503
504 LambdaForm form = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], types[i]);
505 forms.add(form);
506 names.add(form.kind.defaultLambdaName);
507 }
508 record FieldLfToken(byte formOp, int ftypeKind) {}
509 List<FieldLfToken> tokens = new ArrayList<>();
510 for (int i = 0; i <= DirectMethodHandle.FT_CHECKED_REF; i++) {
511 for (byte formOp = DirectMethodHandle.AF_GETFIELD; formOp < DirectMethodHandle.AF_LIMIT; formOp++) {
512 tokens.add(new FieldLfToken(formOp, i));
513 }
514 }
515 for (int i : new int[] {DirectMethodHandle.FT_UNCHECKED_NR_REF, DirectMethodHandle.FT_CHECKED_NR_REF}) {
516 for (byte formOp = DirectMethodHandle.AF_GETFIELD; formOp < DirectMethodHandle.AF_LIMIT; formOp++) {
517 boolean isGetter = (formOp & 1) == (DirectMethodHandle.AF_GETFIELD & 1);
518 if (!isGetter) {
519 tokens.add(new FieldLfToken(formOp, i));
520 }
521 }
522 }
523 // Only legal flat combinations; no static
524 tokens.add(new FieldLfToken(DirectMethodHandle.AF_GETFIELD, DirectMethodHandle.FT_NULLABLE_FLAT));
525 tokens.add(new FieldLfToken(DirectMethodHandle.AF_PUTFIELD, DirectMethodHandle.FT_NULLABLE_FLAT));
526 tokens.add(new FieldLfToken(DirectMethodHandle.AF_PUTFIELD, DirectMethodHandle.FT_NR_FLAT));
527 // Compile
528 for (var token : tokens) {
529 byte b = token.formOp;
530 int ftype = token.ftypeKind;
531 LambdaForm form = DirectMethodHandle
532 .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
533 if (form.kind == GENERIC)
534 throw new InternalError(b + " non-volatile " + ftype);
535 forms.add(form);
536 names.add(form.kind.defaultLambdaName);
537 // volatile
538 form = DirectMethodHandle
539 .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
540 if (form.kind == GENERIC)
541 throw new InternalError(b + " volatile " + ftype);
542 forms.add(form);
543 names.add(form.kind.defaultLambdaName);
544 }
545 return generateCodeBytesForLFs(className,
546 names.toArray(new String[0]),
547 forms.toArray(new LambdaForm[0]));
548 }
549
550 /**
551 * Returns a {@code byte[]} representation of a class implementing
552 * DelegatingMethodHandles of each {@code MethodType} kind in the
553 * {@code methodTypes} argument.
554 */
555 static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
556 MethodType[] methodTypes) {
557
558 HashSet<MethodType> dedupSet = new HashSet<>();
559 ArrayList<LambdaForm> forms = new ArrayList<>();
560 ArrayList<String> names = new ArrayList<>();
561 for (int i = 0; i < methodTypes.length; i++) {
562 // generate methods representing the DelegatingMethodHandle
563 if (dedupSet.add(methodTypes[i])) {
564 // reinvokers are variant with the associated SpeciesData
|