A user left a comment under the Preview 2 PR about the use of SwitchBootstraps.typeSwitch.
https://github.com/openjdk/jdk/pull/15638#pullrequestreview-2745106923
Pasting here:
===================================================
In src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java:
> @@ -541,4 +664,61 @@ private static String typeSwitchClassName(Class<?> targetClass) {
}
return name + "$$TypeSwitch";
}
+
+ // this method should be in sync with com.sun.tools.javac.code.Types.checkUnconditionallyExactPrimitives
+ private static boolean unconditionalExactnessCheck(Class<?> selectorType, Class<?> targetType) {
+ Wrapper selectorWrapper = Wrapper.forBasicType(selectorType);
+ Wrapper targetWrapper = Wrapper.forBasicType(targetType);
+ if (selectorType.isPrimitive() && targetType.equals(selectorWrapper.wrapperType())) {
+ return true;
+ }
+ else if (selectorType.equals(targetType) ||
+ ((selectorType.equals(byte.class) && !targetType.equals(char.class)) ||
⬇️ Suggested change
- ((selectorType.equals(byte.class) && !targetType.equals(char.class)) ||
+ ((selectorType.equals(byte.class) && targetType.isPrimitve() && !targetType.equals(boolean.class) && !targetType.equals(char.class)) ||
Otherwise, SwitchBootstraps.typeSwitch produces wrong results for byte:
var l = MethodHandles.lookup();
var shortType = MethodType.methodType(int.class, short.class, int.class);
var byteType = MethodType.methodType(int.class, byte.class, int.class);
CallSite shortSwitch = SwitchBootstraps.typeSwitch(l, "", shortType, String.class);
CallSite byteSwitch = SwitchBootstraps.typeSwitch(l, "", byteType, String.class);
int shortIndex = (int) shortSwitch.getTarget().invokeExact((short) 1, 0);
int byteIndex = (int) byteSwitch.getTarget().invokeExact((byte) 1, 0);
System.out.println(shortIndex == 1); // true
System.out.println(byteIndex == 1); // false
System.out.println(byteIndex); // 0
This would cause this code to misbehave (if it would compile, which it doesn't):
byte b = 1;
switch (b) {
case String s -> System.out.println("How did we get here? byte is " + s.getClass());
}
So it isn't really a problem with javac but could cause problems for other users of SwitchBootstraps.
===================================================
https://github.com/openjdk/jdk/pull/15638#pullrequestreview-2745106923
Pasting here:
===================================================
In src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java:
> @@ -541,4 +664,61 @@ private static String typeSwitchClassName(Class<?> targetClass) {
}
return name + "$$TypeSwitch";
}
+
+ // this method should be in sync with com.sun.tools.javac.code.Types.checkUnconditionallyExactPrimitives
+ private static boolean unconditionalExactnessCheck(Class<?> selectorType, Class<?> targetType) {
+ Wrapper selectorWrapper = Wrapper.forBasicType(selectorType);
+ Wrapper targetWrapper = Wrapper.forBasicType(targetType);
+ if (selectorType.isPrimitive() && targetType.equals(selectorWrapper.wrapperType())) {
+ return true;
+ }
+ else if (selectorType.equals(targetType) ||
+ ((selectorType.equals(byte.class) && !targetType.equals(char.class)) ||
⬇️ Suggested change
- ((selectorType.equals(byte.class) && !targetType.equals(char.class)) ||
+ ((selectorType.equals(byte.class) && targetType.isPrimitve() && !targetType.equals(boolean.class) && !targetType.equals(char.class)) ||
Otherwise, SwitchBootstraps.typeSwitch produces wrong results for byte:
var l = MethodHandles.lookup();
var shortType = MethodType.methodType(int.class, short.class, int.class);
var byteType = MethodType.methodType(int.class, byte.class, int.class);
CallSite shortSwitch = SwitchBootstraps.typeSwitch(l, "", shortType, String.class);
CallSite byteSwitch = SwitchBootstraps.typeSwitch(l, "", byteType, String.class);
int shortIndex = (int) shortSwitch.getTarget().invokeExact((short) 1, 0);
int byteIndex = (int) byteSwitch.getTarget().invokeExact((byte) 1, 0);
System.out.println(shortIndex == 1); // true
System.out.println(byteIndex == 1); // false
System.out.println(byteIndex); // 0
This would cause this code to misbehave (if it would compile, which it doesn't):
byte b = 1;
switch (b) {
case String s -> System.out.println("How did we get here? byte is " + s.getClass());
}
So it isn't really a problem with javac but could cause problems for other users of SwitchBootstraps.
===================================================