Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8268124: Update java.lang to use switch expressions #4312

Closed
wants to merge 7 commits into from
26 changes: 9 additions & 17 deletions src/java.base/share/classes/java/lang/CharacterData.java
Expand Up @@ -72,23 +72,15 @@ static final CharacterData of(int ch) {
if (ch >>> 8 == 0) { // fast-path
return CharacterDataLatin1.instance;
} else {
switch(ch >>> 16) { //plane 00-16
case(0):
return CharacterData00.instance;
case(1):
return CharacterData01.instance;
case(2):
return CharacterData02.instance;
case(3):
return CharacterData03.instance;
case(14):
return CharacterData0E.instance;
case(15): // Private Use
case(16): // Private Use
return CharacterDataPrivateUse.instance;
default:
return CharacterDataUndefined.instance;
}
return switch (ch >>> 16) { //plane 00-16
case 0 -> CharacterData00.instance;
case 1 -> CharacterData01.instance;
case 2 -> CharacterData02.instance;
case 3 -> CharacterData03.instance;
case 14 -> CharacterData0E.instance;
case 15, 16 -> CharacterDataPrivateUse.instance; // Both cases Private Use
default -> CharacterDataUndefined.instance;
};
}
}
}
Expand Up @@ -170,25 +170,14 @@ private static char[] lookUpTable(String src, int index, Locale locale, boolean
}

private static boolean isConditionMet(String src, int index, Locale locale, int condition) {
switch (condition) {
case FINAL_CASED:
return isFinalCased(src, index, locale);

case AFTER_SOFT_DOTTED:
return isAfterSoftDotted(src, index);

case MORE_ABOVE:
return isMoreAbove(src, index);

case AFTER_I:
return isAfterI(src, index);

case NOT_BEFORE_DOT:
return !isBeforeDot(src, index);

default:
return true;
}
return switch (condition) {
case FINAL_CASED -> isFinalCased(src, index, locale);
case AFTER_SOFT_DOTTED -> isAfterSoftDotted(src, index);
case MORE_ABOVE -> isMoreAbove(src, index);
case AFTER_I -> isAfterI(src, index);
case NOT_BEFORE_DOT -> !isBeforeDot(src, index);
default -> true;
};
}

/**
Expand Down
53 changes: 21 additions & 32 deletions src/java.base/share/classes/java/lang/Long.java
Expand Up @@ -213,38 +213,27 @@ public static String toUnsignedString(long i, int radix) {
if (i >= 0)
return toString(i, radix);
else {
switch (radix) {
case 2:
return toBinaryString(i);

case 4:
return toUnsignedString0(i, 2);

case 8:
return toOctalString(i);

case 10:
/*
* We can get the effect of an unsigned division by 10
* on a long value by first shifting right, yielding a
* positive value, and then dividing by 5. This
* allows the last digit and preceding digits to be
* isolated more quickly than by an initial conversion
* to BigInteger.
*/
long quot = (i >>> 1) / 5;
long rem = i - quot * 10;
return toString(quot) + rem;

case 16:
return toHexString(i);

case 32:
return toUnsignedString0(i, 5);

default:
return toUnsignedBigInteger(i).toString(radix);
}
return switch (radix) {
case 2 -> toBinaryString(i);
case 4 -> toUnsignedString0(i, 2);
case 8 -> toOctalString(i);
case 10 -> {
/*
* We can get the effect of an unsigned division by 10
* on a long value by first shifting right, yielding a
* positive value, and then dividing by 5. This
* allows the last digit and preceding digits to be
* isolated more quickly than by an initial conversion
* to BigInteger.
*/
long quot = (i >>> 1) / 5;
long rem = i - quot * 10;
yield toString(quot) + rem;
}
case 16 -> toHexString(i);
case 32 -> toUnsignedString0(i, 5);
default -> toUnsignedBigInteger(i).toString(radix);
};
}
}

Expand Down
77 changes: 35 additions & 42 deletions src/java.base/share/classes/java/lang/Math.java
Expand Up @@ -1929,29 +1929,25 @@ public static float fma(float a, float b, float c) {
public static double ulp(double d) {
int exp = getExponent(d);

switch(exp) {
case Double.MAX_EXPONENT + 1: // NaN or infinity
return Math.abs(d);

case Double.MIN_EXPONENT - 1: // zero or subnormal
return Double.MIN_VALUE;

default:
assert exp <= Double.MAX_EXPONENT && exp >= Double.MIN_EXPONENT;

// ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
exp = exp - (DoubleConsts.SIGNIFICAND_WIDTH-1);
if (exp >= Double.MIN_EXPONENT) {
return powerOfTwoD(exp);
}
else {
// return a subnormal result; left shift integer
// representation of Double.MIN_VALUE appropriate
// number of positions
return Double.longBitsToDouble(1L <<
(exp - (Double.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) ));
return switch(exp) {
case Double.MAX_EXPONENT + 1 -> Math.abs(d); // NaN or infinity
case Double.MIN_EXPONENT - 1 -> Double.MIN_VALUE; // zero or subnormal
default -> {
assert exp <= Double.MAX_EXPONENT && exp >= Double.MIN_EXPONENT;

// ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
exp = exp - (DoubleConsts.SIGNIFICAND_WIDTH - 1);
if (exp >= Double.MIN_EXPONENT) {
yield powerOfTwoD(exp);
} else {
// return a subnormal result; left shift integer
// representation of Double.MIN_VALUE appropriate
// number of positions
yield Double.longBitsToDouble(1L <<
(exp - (Double.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH - 1))));
}
}
}
};
}

/**
Expand Down Expand Up @@ -1980,28 +1976,25 @@ public static double ulp(double d) {
public static float ulp(float f) {
int exp = getExponent(f);

switch(exp) {
case Float.MAX_EXPONENT+1: // NaN or infinity
return Math.abs(f);
return switch(exp) {
case Float.MAX_EXPONENT + 1 -> Math.abs(f); // NaN or infinity
case Float.MIN_EXPONENT - 1 -> Float.MIN_VALUE; // zero or subnormal
default -> {
assert exp <= Float.MAX_EXPONENT && exp >= Float.MIN_EXPONENT;

case Float.MIN_EXPONENT-1: // zero or subnormal
return Float.MIN_VALUE;

default:
assert exp <= Float.MAX_EXPONENT && exp >= Float.MIN_EXPONENT;

// ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
exp = exp - (FloatConsts.SIGNIFICAND_WIDTH-1);
if (exp >= Float.MIN_EXPONENT) {
return powerOfTwoF(exp);
} else {
// return a subnormal result; left shift integer
// representation of FloatConsts.MIN_VALUE appropriate
// number of positions
return Float.intBitsToFloat(1 <<
(exp - (Float.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) ));
// ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
exp = exp - (FloatConsts.SIGNIFICAND_WIDTH - 1);
if (exp >= Float.MIN_EXPONENT) {
yield powerOfTwoF(exp);
} else {
// return a subnormal result; left shift integer
// representation of FloatConsts.MIN_VALUE appropriate
// number of positions
yield Float.intBitsToFloat(1 <<
(exp - (Float.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH - 1))));
}
}
}
};
}

/**
Expand Down
Expand Up @@ -72,11 +72,11 @@ final class DirectMethodHandleDescImpl implements DirectMethodHandleDesc {
requireNonNull(type);

switch (kind) {
case CONSTRUCTOR: validateConstructor(type); break;
case GETTER: validateFieldType(type, false, true); break;
case SETTER: validateFieldType(type, true, true); break;
case STATIC_GETTER: validateFieldType(type, false, false); break;
case STATIC_SETTER: validateFieldType(type, true, false); break;
case CONSTRUCTOR -> validateConstructor(type);
case GETTER -> validateFieldType(type, false, true);
case SETTER -> validateFieldType(type, true, true);
case STATIC_GETTER -> validateFieldType(type, false, false);
case STATIC_SETTER -> validateFieldType(type, true, false);
}

this.kind = kind;
Expand Down Expand Up @@ -134,57 +134,34 @@ public MethodTypeDesc invocationType() {

@Override
public String lookupDescriptor() {
switch (kind) {
case VIRTUAL:
case SPECIAL:
case INTERFACE_VIRTUAL:
case INTERFACE_SPECIAL:
return invocationType.dropParameterTypes(0, 1).descriptorString();
case STATIC:
case INTERFACE_STATIC:
return invocationType.descriptorString();
case CONSTRUCTOR:
return invocationType.changeReturnType(CD_void).descriptorString();
case GETTER:
case STATIC_GETTER:
return invocationType.returnType().descriptorString();
case SETTER:
return invocationType.parameterType(1).descriptorString();
case STATIC_SETTER:
return invocationType.parameterType(0).descriptorString();
default:
throw new IllegalStateException(kind.toString());
}
return switch (kind) {
case VIRTUAL, SPECIAL,
pconcannon marked this conversation as resolved.
Show resolved Hide resolved
INTERFACE_VIRTUAL,
INTERFACE_SPECIAL -> invocationType.dropParameterTypes(0, 1).descriptorString();
case STATIC, INTERFACE_STATIC -> invocationType.descriptorString();
case CONSTRUCTOR -> invocationType.changeReturnType(CD_void).descriptorString();
case GETTER, STATIC_GETTER -> invocationType.returnType().descriptorString();
case SETTER -> invocationType.parameterType(1).descriptorString();
case STATIC_SETTER -> invocationType.parameterType(0).descriptorString();
default -> throw new IllegalStateException(kind.toString());
};
}

public MethodHandle resolveConstantDesc(MethodHandles.Lookup lookup)
throws ReflectiveOperationException {
Class<?> resolvedOwner = (Class<?>) owner.resolveConstantDesc(lookup);
MethodType invocationType = (MethodType) this.invocationType().resolveConstantDesc(lookup);
switch (kind) {
case STATIC:
case INTERFACE_STATIC:
return lookup.findStatic(resolvedOwner, name, invocationType);
case INTERFACE_VIRTUAL:
case VIRTUAL:
return lookup.findVirtual(resolvedOwner, name, invocationType.dropParameterTypes(0, 1));
case SPECIAL:
case INTERFACE_SPECIAL:
return lookup.findSpecial(resolvedOwner, name, invocationType.dropParameterTypes(0, 1),
lookup.lookupClass());
case CONSTRUCTOR:
return lookup.findConstructor(resolvedOwner, invocationType.changeReturnType(void.class));
case GETTER:
return lookup.findGetter(resolvedOwner, name, invocationType.returnType());
case STATIC_GETTER:
return lookup.findStaticGetter(resolvedOwner, name, invocationType.returnType());
case SETTER:
return lookup.findSetter(resolvedOwner, name, invocationType.parameterType(1));
case STATIC_SETTER:
return lookup.findStaticSetter(resolvedOwner, name, invocationType.parameterType(0));
default:
throw new IllegalStateException(kind.name());
}
return switch (kind) {
case STATIC, INTERFACE_STATIC -> lookup.findStatic(resolvedOwner, name, invocationType);
case INTERFACE_VIRTUAL, VIRTUAL -> lookup.findVirtual(resolvedOwner, name, invocationType.dropParameterTypes(0, 1));
case SPECIAL, INTERFACE_SPECIAL -> lookup.findSpecial(resolvedOwner, name, invocationType.dropParameterTypes(0, 1), lookup.lookupClass());
case CONSTRUCTOR -> lookup.findConstructor(resolvedOwner, invocationType.changeReturnType(void.class));
case GETTER -> lookup.findGetter(resolvedOwner, name, invocationType.returnType());
case STATIC_GETTER -> lookup.findStaticGetter(resolvedOwner, name, invocationType.returnType());
case SETTER -> lookup.findSetter(resolvedOwner, name, invocationType.parameterType(1));
case STATIC_SETTER -> lookup.findStaticSetter(resolvedOwner, name, invocationType.parameterType(0));
default -> throw new IllegalStateException(kind.name());
};
}

/**
Expand Down
Expand Up @@ -156,15 +156,13 @@ static DirectMethodHandleDesc ofField(DirectMethodHandleDesc.Kind kind,
ClassDesc owner,
String fieldName,
ClassDesc fieldType) {
MethodTypeDesc mtr;
switch (kind) {
case GETTER: mtr = MethodTypeDesc.of(fieldType, owner); break;
case SETTER: mtr = MethodTypeDesc.of(CD_void, owner, fieldType); break;
case STATIC_GETTER: mtr = MethodTypeDesc.of(fieldType); break;
case STATIC_SETTER: mtr = MethodTypeDesc.of(CD_void, fieldType); break;
default:
throw new IllegalArgumentException(kind.toString());
}
MethodTypeDesc mtr = switch (kind) {
case GETTER -> MethodTypeDesc.of(fieldType, owner);
case SETTER -> MethodTypeDesc.of(CD_void, owner, fieldType);
case STATIC_GETTER -> MethodTypeDesc.of(fieldType);
case STATIC_SETTER -> MethodTypeDesc.of(CD_void, fieldType);
default -> throw new IllegalArgumentException(kind.toString());
};
return new DirectMethodHandleDescImpl(kind, owner, fieldName, mtr);
}

Expand Down
Expand Up @@ -64,19 +64,14 @@ abstract class BoundMethodHandle extends MethodHandle {
static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
// for some type signatures, there exist pre-defined concrete BMH classes
try {
switch (xtype) {
case L_TYPE:
return bindSingle(type, form, x); // Use known fast path.
case I_TYPE:
return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(I_TYPE_NUM).factory().invokeBasic(type, form, ValueConversions.widenSubword(x));
case J_TYPE:
return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(J_TYPE_NUM).factory().invokeBasic(type, form, (long) x);
case F_TYPE:
return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(F_TYPE_NUM).factory().invokeBasic(type, form, (float) x);
case D_TYPE:
return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(D_TYPE_NUM).factory().invokeBasic(type, form, (double) x);
default : throw newInternalError("unexpected xtype: " + xtype);
}
return switch (xtype) {
case L_TYPE -> bindSingle(type, form, x); // Use known fast path.
case I_TYPE -> (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(I_TYPE_NUM).factory().invokeBasic(type, form, ValueConversions.widenSubword(x));
case J_TYPE -> (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(J_TYPE_NUM).factory().invokeBasic(type, form, (long) x);
case F_TYPE -> (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(F_TYPE_NUM).factory().invokeBasic(type, form, (float) x);
case D_TYPE -> (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(D_TYPE_NUM).factory().invokeBasic(type, form, (double) x);
default -> throw newInternalError("unexpected xtype: " + xtype);
};
} catch (Throwable t) {
throw uncaughtException(t);
}
Expand Down
Expand Up @@ -853,14 +853,14 @@ public void emitFieldInsn(int asmop, MethodVisitor mv) {
}

private int typeLoadOp(char t) {
switch (t) {
case 'L': return ALOAD;
case 'I': return ILOAD;
case 'J': return LLOAD;
case 'F': return FLOAD;
case 'D': return DLOAD;
default : throw newInternalError("unrecognized type " + t);
}
return switch (t) {
case 'L' -> ALOAD;
case 'I' -> ILOAD;
case 'J' -> LLOAD;
case 'F' -> FLOAD;
case 'D' -> DLOAD;
default -> throw newInternalError("unrecognized type " + t);
};
}

private void emitIntConstant(int con, MethodVisitor mv) {
Expand Down