diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index f724d7355b005..e256604357922 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -546,7 +546,11 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto Object caseLabel = caseLabels[idx]; cb.labelBinding(caseTargets[idx]); if (caseLabel instanceof Class classLabel) { - if (unconditionalExactnessCheck(selectorType, classLabel)) { + if (isNotValidPair(selectorType, caseLabel)){ + cb.goto_(next); + continue; + } + else if (unconditionalExactnessCheck(selectorType, classLabel)) { //nothing - unconditionally use this case } else if (classLabel.isPrimitive()) { if (!selectorType.isPrimitive() && !Wrapper.isWrapperNumericOrBooleanType(selectorType)) { @@ -717,6 +721,11 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto }; } + private static boolean isNotValidPair(Class selectorType, Object caseLabel) { + return (selectorType == boolean.class && caseLabel != boolean.class && caseLabel != Boolean.class) || + (selectorType != boolean.class && selectorType.isPrimitive() && (caseLabel == boolean.class || caseLabel == Boolean.class)); + } + /* * Construct the method handle that represents the method int typeSwitch(Object, int, BiPredicate, List) */ @@ -769,11 +778,12 @@ private static boolean unconditionalExactnessCheck(Class selectorType, Class< return true; } else if (selectorType.equals(targetType) || - ((selectorType.equals(byte.class) && !targetType.equals(char.class)) || - (selectorType.equals(short.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))) || - (selectorType.equals(char.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))) || - (selectorType.equals(int.class) && (targetType.equals(double.class) || targetType.equals(long.class))) || - (selectorType.equals(float.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))))) return true; + (targetType.isPrimitive() && selectorType.isPrimitive() && + ((selectorType.equals(byte.class) && !targetType.equals(char.class)) || + (selectorType.equals(short.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))) || + (selectorType.equals(char.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))) || + (selectorType.equals(int.class) && (targetType.equals(double.class) || targetType.equals(long.class))) || + (selectorType.equals(float.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper)))))) return true; return false; } diff --git a/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java b/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java index b21c16c4ba043..acb2665c0f572 100644 --- a/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java +++ b/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java @@ -74,6 +74,12 @@ private void testType(Object target, int start, int result, Object... labels) th assertEquals(-1, (int) indy.invoke(null, start)); } + private void testPrimitiveType(Object target, Class targetType, int start, int result, Object... labels) throws Throwable { + MethodType switchType = MethodType.methodType(int.class, targetType, int.class); + MethodHandle indy = ((CallSite) BSM_TYPE_SWITCH.invoke(MethodHandles.lookup(), "", switchType, labels)).dynamicInvoker(); + assertEquals((int) indy.invoke(target, start), result); + } + private void testEnum(Enum target, int start, int result, Object... labels) throws Throwable { testEnum(target.getClass(), target, start, result, labels); } @@ -132,6 +138,17 @@ public boolean equals(Object obj) { }, 0, 1, 1L); } + public void testPrimitiveTypes() throws Throwable { + testPrimitiveType((short) 1, short.class, 0, 1, String.class); + testPrimitiveType((byte) 1, byte.class,0, 1, String.class, byte.class); + testPrimitiveType(true, boolean.class,0, 1, false, boolean.class); + testPrimitiveType(1, int.class,0, 1, String.class); + testPrimitiveType(1, int.class,0, 1, true); + testPrimitiveType(true, boolean.class,0, 1, false); + testPrimitiveType((byte) 1, byte.class,0, 1, boolean.class, byte.class); + testPrimitiveType((byte) 1, byte.class,0, 1, Boolean.class, byte.class); + } + public void testEnums() throws Throwable { testEnum(E1.A, 0, 2, "B", "C", "A", E1.class); testEnum(E1.B, 0, 0, "B", "C", "A", E1.class);