< prev index next >

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java

Print this page

 32 import java.lang.constant.ConstantDescs;
 33 import java.lang.constant.MethodTypeDesc;
 34 import java.lang.invoke.CallSite;
 35 import java.lang.invoke.ConstantCallSite;
 36 import java.lang.invoke.MethodHandle;
 37 import java.lang.invoke.MethodHandles;
 38 import java.lang.invoke.MethodType;
 39 import java.lang.reflect.AccessFlag;
 40 import java.util.ArrayList;
 41 import java.util.List;
 42 import java.util.Objects;
 43 import java.util.Optional;
 44 import java.util.function.BiPredicate;
 45 import java.util.function.Consumer;
 46 
 47 import jdk.internal.access.SharedSecrets;
 48 import java.lang.classfile.ClassFile;
 49 import java.lang.classfile.Label;
 50 import java.lang.classfile.instruction.SwitchCase;
 51 
 52 import jdk.internal.constant.ConstantUtils;
 53 import jdk.internal.constant.MethodTypeDescImpl;
 54 import jdk.internal.constant.ReferenceClassDescImpl;

 55 import jdk.internal.misc.PreviewFeatures;
 56 import jdk.internal.vm.annotation.Stable;
 57 
 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)}.
 74  *

687                 }
688                 cb.loadConstant(idx);
689                 cb.ireturn();
690             }
691             cb.labelBinding(dflt);
692             cb.loadConstant(labelConstants.length);
693             cb.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);

 32 import java.lang.constant.ConstantDescs;
 33 import java.lang.constant.MethodTypeDesc;
 34 import java.lang.invoke.CallSite;
 35 import java.lang.invoke.ConstantCallSite;
 36 import java.lang.invoke.MethodHandle;
 37 import java.lang.invoke.MethodHandles;
 38 import java.lang.invoke.MethodType;
 39 import java.lang.reflect.AccessFlag;
 40 import java.util.ArrayList;
 41 import java.util.List;
 42 import java.util.Objects;
 43 import java.util.Optional;
 44 import java.util.function.BiPredicate;
 45 import java.util.function.Consumer;
 46 
 47 import jdk.internal.access.SharedSecrets;
 48 import java.lang.classfile.ClassFile;
 49 import java.lang.classfile.Label;
 50 import java.lang.classfile.instruction.SwitchCase;
 51 

 52 import jdk.internal.constant.MethodTypeDescImpl;
 53 import jdk.internal.constant.ReferenceClassDescImpl;
 54 import jdk.internal.constant.ConstantUtils;
 55 import jdk.internal.misc.PreviewFeatures;
 56 import jdk.internal.vm.annotation.Stable;
 57 
 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)}.
 74  *

687                 }
688                 cb.loadConstant(idx);
689                 cb.ireturn();
690             }
691             cb.labelBinding(dflt);
692             cb.loadConstant(labelConstants.length);
693             cb.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);
< prev index next >