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.misc.CDS;
29 import jdk.internal.org.objectweb.asm.*;
30 import sun.invoke.util.BytecodeDescriptor;
31 import sun.invoke.util.VerifyAccess;
32 import sun.security.action.GetPropertyAction;
33 import sun.security.action.GetBooleanAction;
34
35 import java.io.FilePermission;
36 import java.io.Serializable;
37 import java.lang.constant.ConstantDescs;
38 import java.lang.invoke.MethodHandles.Lookup;
39 import java.lang.reflect.Modifier;
40 import java.security.AccessController;
41 import java.security.PrivilegedAction;
42 import java.util.LinkedHashSet;
43 import java.util.concurrent.atomic.AtomicInteger;
44 import java.util.PropertyPermission;
45 import java.util.Set;
46
47 import static java.lang.invoke.MethodHandleStatics.CLASSFILE_VERSION;
48 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
49 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
50 import static java.lang.invoke.MethodType.methodType;
51 import static jdk.internal.org.objectweb.asm.Opcodes.*;
52
53 /**
54 * Lambda metafactory implementation which dynamically creates an
55 * inner-class-like class per lambda callsite.
56 *
57 * @see LambdaMetafactory
58 */
59 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
60 private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
61 private static final String JAVA_LANG_OBJECT = "java/lang/Object";
340
341 // Forward the SAM method
342 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
343 interfaceMethodType.toMethodDescriptorString(), null, null);
344 new ForwardingMethodGenerator(mv).generate(interfaceMethodType);
345
346 // Forward the altMethods
347 if (altMethods != null) {
348 for (MethodType mt : altMethods) {
349 mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
350 mt.toMethodDescriptorString(), null, null);
351 new ForwardingMethodGenerator(mv).generate(mt);
352 }
353 }
354
355 if (isSerializable)
356 generateSerializationFriendlyMethods();
357 else if (accidentallySerializable)
358 generateSerializationHostileMethods();
359
360 cw.visitEnd();
361
362 // Define the generated class in this VM.
363
364 final byte[] classBytes = cw.toByteArray();
365 // If requested, dump out to a file for debugging purposes
366 if (dumper != null) {
367 AccessController.doPrivileged(new PrivilegedAction<>() {
368 @Override
369 public Void run() {
370 dumper.dumpClass(lambdaClassName, classBytes);
371 return null;
372 }
373 }, null,
374 new FilePermission("<<ALL FILES>>", "read, write"),
375 // createDirectories may need it
376 new PropertyPermission("user.dir", "read"));
377 }
378 try {
379 // this class is linked at the indy callsite; so define a hidden nestmate
573 for (int i = 0; i < samParametersLength; i++) {
574 Class<?> argType = samType.parameterType(i);
575 visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
576 lvIndex += getParameterSize(argType);
577 convertType(argType, implMethodType.parameterType(captureArity + i), dynamicMethodType.parameterType(i));
578 }
579 }
580
581 private int invocationOpcode() throws InternalError {
582 return switch (implKind) {
583 case MethodHandleInfo.REF_invokeStatic -> INVOKESTATIC;
584 case MethodHandleInfo.REF_newInvokeSpecial -> INVOKESPECIAL;
585 case MethodHandleInfo.REF_invokeVirtual -> INVOKEVIRTUAL;
586 case MethodHandleInfo.REF_invokeInterface -> INVOKEINTERFACE;
587 case MethodHandleInfo.REF_invokeSpecial -> INVOKESPECIAL;
588 default -> throw new InternalError("Unexpected invocation kind: " + implKind);
589 };
590 }
591 }
592
593 static int getParameterSize(Class<?> c) {
594 if (c == Void.TYPE) {
595 return 0;
596 } else if (c == Long.TYPE || c == Double.TYPE) {
597 return 2;
598 }
599 return 1;
600 }
601
602 static int getLoadOpcode(Class<?> c) {
603 if(c == Void.TYPE) {
604 throw new InternalError("Unexpected void type of load opcode");
605 }
606 return ILOAD + getOpcodeOffset(c);
607 }
608
609 static int getReturnOpcode(Class<?> c) {
610 if(c == Void.TYPE) {
611 return RETURN;
612 }
|
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.misc.CDS;
29 import jdk.internal.org.objectweb.asm.*;
30 import sun.invoke.util.BytecodeDescriptor;
31 import sun.invoke.util.VerifyAccess;
32 import sun.security.action.GetPropertyAction;
33 import sun.security.action.GetBooleanAction;
34
35 import java.io.FilePermission;
36 import java.io.Serializable;
37 import java.lang.constant.ConstantDescs;
38 import java.lang.invoke.MethodHandles.Lookup;
39 import java.lang.reflect.Modifier;
40 import java.security.AccessController;
41 import java.security.PrivilegedAction;
42 import java.util.HashSet;
43 import java.util.LinkedHashSet;
44 import java.util.concurrent.atomic.AtomicInteger;
45 import java.util.PropertyPermission;
46 import java.util.Set;
47
48 import static java.lang.invoke.MethodHandleStatics.CLASSFILE_VERSION;
49 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
50 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
51 import static java.lang.invoke.MethodType.methodType;
52 import static jdk.internal.org.objectweb.asm.Opcodes.*;
53
54 /**
55 * Lambda metafactory implementation which dynamically creates an
56 * inner-class-like class per lambda callsite.
57 *
58 * @see LambdaMetafactory
59 */
60 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
61 private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
62 private static final String JAVA_LANG_OBJECT = "java/lang/Object";
341
342 // Forward the SAM method
343 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
344 interfaceMethodType.toMethodDescriptorString(), null, null);
345 new ForwardingMethodGenerator(mv).generate(interfaceMethodType);
346
347 // Forward the altMethods
348 if (altMethods != null) {
349 for (MethodType mt : altMethods) {
350 mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
351 mt.toMethodDescriptorString(), null, null);
352 new ForwardingMethodGenerator(mv).generate(mt);
353 }
354 }
355
356 if (isSerializable)
357 generateSerializationFriendlyMethods();
358 else if (accidentallySerializable)
359 generateSerializationHostileMethods();
360
361 // generate Preload attribute if it references any value class
362 PreloadAttributeBuilder builder = new PreloadAttributeBuilder(targetClass);
363 builder.add(factoryType)
364 .add(interfaceMethodType)
365 .add(implMethodType)
366 .add(dynamicMethodType)
367 .add(altMethods);
368 if (!builder.isEmpty())
369 cw.visitAttribute(builder.build());
370
371 cw.visitEnd();
372
373 // Define the generated class in this VM.
374
375 final byte[] classBytes = cw.toByteArray();
376 // If requested, dump out to a file for debugging purposes
377 if (dumper != null) {
378 AccessController.doPrivileged(new PrivilegedAction<>() {
379 @Override
380 public Void run() {
381 dumper.dumpClass(lambdaClassName, classBytes);
382 return null;
383 }
384 }, null,
385 new FilePermission("<<ALL FILES>>", "read, write"),
386 // createDirectories may need it
387 new PropertyPermission("user.dir", "read"));
388 }
389 try {
390 // this class is linked at the indy callsite; so define a hidden nestmate
584 for (int i = 0; i < samParametersLength; i++) {
585 Class<?> argType = samType.parameterType(i);
586 visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
587 lvIndex += getParameterSize(argType);
588 convertType(argType, implMethodType.parameterType(captureArity + i), dynamicMethodType.parameterType(i));
589 }
590 }
591
592 private int invocationOpcode() throws InternalError {
593 return switch (implKind) {
594 case MethodHandleInfo.REF_invokeStatic -> INVOKESTATIC;
595 case MethodHandleInfo.REF_newInvokeSpecial -> INVOKESPECIAL;
596 case MethodHandleInfo.REF_invokeVirtual -> INVOKEVIRTUAL;
597 case MethodHandleInfo.REF_invokeInterface -> INVOKEINTERFACE;
598 case MethodHandleInfo.REF_invokeSpecial -> INVOKESPECIAL;
599 default -> throw new InternalError("Unexpected invocation kind: " + implKind);
600 };
601 }
602 }
603
604 /*
605 * Preload attribute builder
606 */
607 static class PreloadAttributeBuilder {
608 private final Set<Class<?>> preloadClasses = new HashSet<>();
609 PreloadAttributeBuilder(Class<?> targetClass) {
610 if (requiresPreload(targetClass)) {
611 preloadClasses.add(targetClass);
612 }
613 }
614
615 /*
616 * Add the value types referenced in the given MethodType.
617 */
618 PreloadAttributeBuilder add(MethodType mt) {
619 // parameter types
620 for (Class<?> paramType : mt.ptypes()) {
621 if (requiresPreload(paramType)) {
622 preloadClasses.add(paramType);
623 }
624 }
625 // return type
626 if (requiresPreload(mt.returnType())) {
627 preloadClasses.add(mt.returnType());
628 }
629 return this;
630 }
631
632 PreloadAttributeBuilder add(MethodType... mtypes) {
633 for (MethodType mt : mtypes) {
634 add(mt);
635 }
636 return this;
637 }
638
639 boolean requiresPreload(Class<?> cls) {
640 Class<?> c = cls;
641 while (c.isArray()) {
642 c = c.getComponentType();
643 }
644 return (c.isValue() && !c.isPrimitiveClass()) || c.isPrimitiveValueType();
645 }
646
647 boolean isEmpty() {
648 return preloadClasses.isEmpty();
649 }
650
651 Attribute build() {
652 return new Attribute("Preload") {
653 @Override
654 protected ByteVector write(ClassWriter cw,
655 byte[] code,
656 int len,
657 int maxStack,
658 int maxLocals) {
659 ByteVector attr = new ByteVector();
660 attr.putShort(preloadClasses.size());
661 for (Class<?> c : preloadClasses) {
662 attr.putShort(cw.newClass(Type.getInternalName(c)));
663 }
664 return attr;
665 }
666 };
667 }
668 }
669
670 static int getParameterSize(Class<?> c) {
671 if (c == Void.TYPE) {
672 return 0;
673 } else if (c == Long.TYPE || c == Double.TYPE) {
674 return 2;
675 }
676 return 1;
677 }
678
679 static int getLoadOpcode(Class<?> c) {
680 if(c == Void.TYPE) {
681 throw new InternalError("Unexpected void type of load opcode");
682 }
683 return ILOAD + getOpcodeOffset(c);
684 }
685
686 static int getReturnOpcode(Class<?> c) {
687 if(c == Void.TYPE) {
688 return RETURN;
689 }
|