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..f4d8259584221 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,11 @@ 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() && + (selectorWrapper.isStrictSubRangeOf(targetWrapper) && + !((selectorType.equals(byte.class) && targetType.equals(char.class)) || + (selectorType.equals(int.class) && targetType.equals(float.class)) || + (selectorType.equals(long.class) && (targetType.equals(double.class) || targetType.equals(float.class))))))) return true; return false; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index 1bc1e078c1a97..417b54ca50c93 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -5085,16 +5085,12 @@ public boolean isUnconditionallyExact(Type source, Type target) { * @param targetType Target type */ public boolean isUnconditionallyExactPrimitives(Type selectorType, Type targetType) { - if (isSameType(selectorType, targetType)) { - return true; - } - - return (selectorType.isPrimitive() && targetType.isPrimitive()) && - ((selectorType.hasTag(BYTE) && !targetType.hasTag(CHAR)) || - (selectorType.hasTag(SHORT) && (selectorType.getTag().isStrictSubRangeOf(targetType.getTag()))) || - (selectorType.hasTag(CHAR) && (selectorType.getTag().isStrictSubRangeOf(targetType.getTag()))) || - (selectorType.hasTag(INT) && (targetType.hasTag(DOUBLE) || targetType.hasTag(LONG))) || - (selectorType.hasTag(FLOAT) && (selectorType.getTag().isStrictSubRangeOf(targetType.getTag())))); + return isSameType(selectorType, targetType) || + (selectorType.isPrimitive() && targetType.isPrimitive()) && + ((selectorType.getTag().isStrictSubRangeOf(targetType.getTag())) && + !((selectorType.hasTag(BYTE) && targetType.hasTag(CHAR)) || + (selectorType.hasTag(INT) && targetType.hasTag(FLOAT)) || + (selectorType.hasTag(LONG) && (targetType.hasTag(DOUBLE) || targetType.hasTag(FLOAT))))); } // diff --git a/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java b/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java index b21c16c4ba043..a231501894f4f 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,18 @@ 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); + testPrimitiveType(true, boolean.class,0, 1, String.class, boolean.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);