719 .with(StackMapTableAttribute.of(stackMapFrames));
720 DirectCodeBuilder.withMaxs(cb, 3, locals.size()); // enum labels use 3 stack, others use 2
721 };
722 }
723
724 private static boolean isNotValidPair(Class<?> selectorType, Object caseLabel) {
725 return (selectorType == boolean.class && caseLabel != boolean.class && caseLabel != Boolean.class) ||
726 (selectorType != boolean.class && selectorType.isPrimitive() && (caseLabel == boolean.class || caseLabel == Boolean.class));
727 }
728
729 /*
730 * Construct the method handle that represents the method int typeSwitch(Object, int, BiPredicate, List)
731 */
732 private static MethodHandle generateTypeSwitch(MethodHandles.Lookup caller, Class<?> selectorType, Object[] labelConstants) {
733 boolean addExtraInfo = needsExtraInfo(selectorType, labelConstants);
734 List<EnumDesc<?>> enumDescs = addExtraInfo ? new ArrayList<>() : null;
735 List<Class<?>> extraClassLabels = addExtraInfo ? new ArrayList<>() : null;
736
737 byte[] classBytes = ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS).build(ConstantUtils.binaryNameToDesc(typeSwitchClassName(caller.lookupClass())),
738 clb -> {
739 clb.withFlags(AccessFlag.FINAL, AccessFlag.SUPER, AccessFlag.SYNTHETIC)
740 .withMethodBody("typeSwitch",
741 addExtraInfo ? MTD_TYPE_SWITCH_EXTRA : MTD_TYPE_SWITCH,
742 ClassFile.ACC_FINAL | ClassFile.ACC_PUBLIC | ClassFile.ACC_STATIC,
743 generateTypeSwitchSkeleton(selectorType, labelConstants, enumDescs, extraClassLabels));
744 });
745
746 try {
747 // this class is linked at the indy callsite; so define a hidden nestmate
748 MethodHandles.Lookup lookup;
749 lookup = caller.defineHiddenClass(classBytes, true, NESTMATE, STRONG);
750 MethodHandle typeSwitch = lookup.findStatic(lookup.lookupClass(),
751 "typeSwitch",
752 addExtraInfo ? MT_TYPE_SWITCH_EXTRA : MT_TYPE_SWITCH);
753 if (addExtraInfo) {
754 typeSwitch = MethodHandles.insertArguments(typeSwitch, 2, new ResolvedEnumLabels(caller, enumDescs.toArray(new EnumDesc<?>[0])),
755 List.copyOf(extraClassLabels));
756 }
757 return typeSwitch;
758 } catch (Throwable t) {
759 throw new IllegalArgumentException(t);
|
719 .with(StackMapTableAttribute.of(stackMapFrames));
720 DirectCodeBuilder.withMaxs(cb, 3, locals.size()); // enum labels use 3 stack, others use 2
721 };
722 }
723
724 private static boolean isNotValidPair(Class<?> selectorType, Object caseLabel) {
725 return (selectorType == boolean.class && caseLabel != boolean.class && caseLabel != Boolean.class) ||
726 (selectorType != boolean.class && selectorType.isPrimitive() && (caseLabel == boolean.class || caseLabel == Boolean.class));
727 }
728
729 /*
730 * Construct the method handle that represents the method int typeSwitch(Object, int, BiPredicate, List)
731 */
732 private static MethodHandle generateTypeSwitch(MethodHandles.Lookup caller, Class<?> selectorType, Object[] labelConstants) {
733 boolean addExtraInfo = needsExtraInfo(selectorType, labelConstants);
734 List<EnumDesc<?>> enumDescs = addExtraInfo ? new ArrayList<>() : null;
735 List<Class<?>> extraClassLabels = addExtraInfo ? new ArrayList<>() : null;
736
737 byte[] classBytes = ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS).build(ConstantUtils.binaryNameToDesc(typeSwitchClassName(caller.lookupClass())),
738 clb -> {
739 clb.withFlags(AccessFlag.FINAL, (PreviewFeatures.isEnabled()) ? AccessFlag.IDENTITY : AccessFlag.SUPER, AccessFlag.SYNTHETIC)
740 .withMethodBody("typeSwitch",
741 addExtraInfo ? MTD_TYPE_SWITCH_EXTRA : MTD_TYPE_SWITCH,
742 ClassFile.ACC_FINAL | ClassFile.ACC_PUBLIC | ClassFile.ACC_STATIC,
743 generateTypeSwitchSkeleton(selectorType, labelConstants, enumDescs, extraClassLabels));
744 });
745
746 try {
747 // this class is linked at the indy callsite; so define a hidden nestmate
748 MethodHandles.Lookup lookup;
749 lookup = caller.defineHiddenClass(classBytes, true, NESTMATE, STRONG);
750 MethodHandle typeSwitch = lookup.findStatic(lookup.lookupClass(),
751 "typeSwitch",
752 addExtraInfo ? MT_TYPE_SWITCH_EXTRA : MT_TYPE_SWITCH);
753 if (addExtraInfo) {
754 typeSwitch = MethodHandles.insertArguments(typeSwitch, 2, new ResolvedEnumLabels(caller, enumDescs.toArray(new EnumDesc<?>[0])),
755 List.copyOf(extraClassLabels));
756 }
757 return typeSwitch;
758 } catch (Throwable t) {
759 throw new IllegalArgumentException(t);
|