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