31 import java.lang.constant.ConstantDesc;
32 import java.lang.constant.MethodTypeDesc;
33 import java.lang.invoke.CallSite;
34 import java.lang.invoke.ConstantCallSite;
35 import java.lang.invoke.MethodHandle;
36 import java.lang.invoke.MethodHandles;
37 import java.lang.invoke.MethodType;
38 import java.lang.reflect.AccessFlag;
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.Optional;
43 import java.util.function.BiPredicate;
44 import java.util.function.Consumer;
45
46 import jdk.internal.access.SharedSecrets;
47 import java.lang.classfile.ClassFile;
48 import java.lang.classfile.Label;
49 import java.lang.classfile.instruction.SwitchCase;
50
51 import jdk.internal.constant.ConstantUtils;
52 import jdk.internal.constant.MethodTypeDescImpl;
53 import jdk.internal.constant.ReferenceClassDescImpl;
54 import jdk.internal.misc.PreviewFeatures;
55 import jdk.internal.vm.annotation.Stable;
56
57 import static java.lang.constant.ConstantDescs.*;
58 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
59 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
60 import java.util.Arrays;
61 import java.util.HashMap;
62 import java.util.Map;
63 import static java.util.Objects.requireNonNull;
64 import static jdk.internal.constant.ConstantUtils.classDesc;
65 import static jdk.internal.constant.ConstantUtils.referenceClassDesc;
66
67 import sun.invoke.util.Wrapper;
68
69 /**
70 * Bootstrap methods for linking {@code invokedynamic} call sites that implement
71 * the selection functionality of the {@code switch} statement. The bootstraps
72 * take additional static arguments corresponding to the {@code case} labels
73 * of the {@code switch}, implicitly numbered sequentially from {@code [0..N)}.
687 }
688 cb.loadConstant(idx)
689 .ireturn();
690 }
691 cb.labelBinding(dflt)
692 .loadConstant(labelConstants.length)
693 .ireturn();
694 };
695 }
696
697 /*
698 * Construct the method handle that represents the method int typeSwitch(Object, int, BiPredicate, List)
699 */
700 private static MethodHandle generateTypeSwitch(MethodHandles.Lookup caller, Class<?> selectorType, Object[] labelConstants) {
701 boolean addExtraInfo = needsExtraInfo(selectorType, labelConstants);
702 List<EnumDesc<?>> enumDescs = addExtraInfo ? new ArrayList<>() : null;
703 List<Class<?>> extraClassLabels = addExtraInfo ? new ArrayList<>() : null;
704
705 byte[] classBytes = ClassFile.of().build(ConstantUtils.binaryNameToDesc(typeSwitchClassName(caller.lookupClass())),
706 clb -> {
707 clb.withFlags(AccessFlag.FINAL, AccessFlag.SUPER, AccessFlag.SYNTHETIC)
708 .withMethodBody("typeSwitch",
709 addExtraInfo ? MTD_TYPE_SWITCH_EXTRA : MTD_TYPE_SWITCH,
710 ClassFile.ACC_FINAL | ClassFile.ACC_PUBLIC | ClassFile.ACC_STATIC,
711 generateTypeSwitchSkeleton(selectorType, labelConstants, enumDescs, extraClassLabels));
712 });
713
714 try {
715 // this class is linked at the indy callsite; so define a hidden nestmate
716 MethodHandles.Lookup lookup;
717 lookup = caller.defineHiddenClass(classBytes, true, NESTMATE, STRONG);
718 MethodHandle typeSwitch = lookup.findStatic(lookup.lookupClass(),
719 "typeSwitch",
720 addExtraInfo ? MT_TYPE_SWITCH_EXTRA : MT_TYPE_SWITCH);
721 if (addExtraInfo) {
722 typeSwitch = MethodHandles.insertArguments(typeSwitch, 2, new ResolvedEnumLabels(caller, enumDescs.toArray(new EnumDesc<?>[0])),
723 List.copyOf(extraClassLabels));
724 }
725 return typeSwitch;
726 } catch (Throwable t) {
727 throw new IllegalArgumentException(t);
|
31 import java.lang.constant.ConstantDesc;
32 import java.lang.constant.MethodTypeDesc;
33 import java.lang.invoke.CallSite;
34 import java.lang.invoke.ConstantCallSite;
35 import java.lang.invoke.MethodHandle;
36 import java.lang.invoke.MethodHandles;
37 import java.lang.invoke.MethodType;
38 import java.lang.reflect.AccessFlag;
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.Optional;
43 import java.util.function.BiPredicate;
44 import java.util.function.Consumer;
45
46 import jdk.internal.access.SharedSecrets;
47 import java.lang.classfile.ClassFile;
48 import java.lang.classfile.Label;
49 import java.lang.classfile.instruction.SwitchCase;
50
51 import jdk.internal.constant.MethodTypeDescImpl;
52 import jdk.internal.constant.ReferenceClassDescImpl;
53 import jdk.internal.constant.ConstantUtils;
54 import jdk.internal.misc.PreviewFeatures;
55 import jdk.internal.vm.annotation.Stable;
56
57 import static java.lang.constant.ConstantDescs.*;
58 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
59 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
60 import java.util.Arrays;
61 import java.util.HashMap;
62 import java.util.Map;
63 import static java.util.Objects.requireNonNull;
64 import static jdk.internal.constant.ConstantUtils.classDesc;
65 import static jdk.internal.constant.ConstantUtils.referenceClassDesc;
66
67 import sun.invoke.util.Wrapper;
68
69 /**
70 * Bootstrap methods for linking {@code invokedynamic} call sites that implement
71 * the selection functionality of the {@code switch} statement. The bootstraps
72 * take additional static arguments corresponding to the {@code case} labels
73 * of the {@code switch}, implicitly numbered sequentially from {@code [0..N)}.
687 }
688 cb.loadConstant(idx)
689 .ireturn();
690 }
691 cb.labelBinding(dflt)
692 .loadConstant(labelConstants.length)
693 .ireturn();
694 };
695 }
696
697 /*
698 * Construct the method handle that represents the method int typeSwitch(Object, int, BiPredicate, List)
699 */
700 private static MethodHandle generateTypeSwitch(MethodHandles.Lookup caller, Class<?> selectorType, Object[] labelConstants) {
701 boolean addExtraInfo = needsExtraInfo(selectorType, labelConstants);
702 List<EnumDesc<?>> enumDescs = addExtraInfo ? new ArrayList<>() : null;
703 List<Class<?>> extraClassLabels = addExtraInfo ? new ArrayList<>() : null;
704
705 byte[] classBytes = ClassFile.of().build(ConstantUtils.binaryNameToDesc(typeSwitchClassName(caller.lookupClass())),
706 clb -> {
707 clb.withFlags(AccessFlag.FINAL, (PreviewFeatures.isEnabled()) ? AccessFlag.IDENTITY : AccessFlag.SUPER, AccessFlag.SYNTHETIC)
708 .withMethodBody("typeSwitch",
709 addExtraInfo ? MTD_TYPE_SWITCH_EXTRA : MTD_TYPE_SWITCH,
710 ClassFile.ACC_FINAL | ClassFile.ACC_PUBLIC | ClassFile.ACC_STATIC,
711 generateTypeSwitchSkeleton(selectorType, labelConstants, enumDescs, extraClassLabels));
712 });
713
714 try {
715 // this class is linked at the indy callsite; so define a hidden nestmate
716 MethodHandles.Lookup lookup;
717 lookup = caller.defineHiddenClass(classBytes, true, NESTMATE, STRONG);
718 MethodHandle typeSwitch = lookup.findStatic(lookup.lookupClass(),
719 "typeSwitch",
720 addExtraInfo ? MT_TYPE_SWITCH_EXTRA : MT_TYPE_SWITCH);
721 if (addExtraInfo) {
722 typeSwitch = MethodHandles.insertArguments(typeSwitch, 2, new ResolvedEnumLabels(caller, enumDescs.toArray(new EnumDesc<?>[0])),
723 List.copyOf(extraClassLabels));
724 }
725 return typeSwitch;
726 } catch (Throwable t) {
727 throw new IllegalArgumentException(t);
|