8268124: Update java.lang to use switch expressions
Reviewed-by: naoto, darcy, mchung, iris, lancea, dfuchs
This commit is contained in:
parent
a187fcc3ec
commit
d43c8a74b3
@ -72,23 +72,15 @@ abstract class CharacterData {
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,25 +170,14 @@ final class ConditionalSpecialCasing {
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,38 +213,27 @@ public final class Long extends Number
|
||||
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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1926,29 +1926,25 @@ public final class Math {
|
||||
public static double ulp(double d) {
|
||||
int exp = getExponent(d);
|
||||
|
||||
switch(exp) {
|
||||
case Double.MAX_EXPONENT + 1: // NaN or infinity
|
||||
return Math.abs(d);
|
||||
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;
|
||||
|
||||
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);
|
||||
// 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))));
|
||||
}
|
||||
}
|
||||
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)) ));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1977,28 +1973,25 @@ public final class Math {
|
||||
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))));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
@ -134,57 +134,40 @@ final class DirectMethodHandleDescImpl implements DirectMethodHandleDesc {
|
||||
|
||||
@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,
|
||||
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 VIRTUAL,
|
||||
INTERFACE_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());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,15 +156,13 @@ public sealed interface MethodHandleDesc
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -853,14 +853,14 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -163,11 +163,11 @@ abstract class DelegatingMethodHandle extends MethodHandle {
|
||||
}
|
||||
|
||||
private static Kind whichKind(int whichCache) {
|
||||
switch(whichCache) {
|
||||
case MethodTypeForm.LF_REBIND: return BOUND_REINVOKER;
|
||||
case MethodTypeForm.LF_DELEGATE: return DELEGATE;
|
||||
default: return REINVOKER;
|
||||
}
|
||||
return switch (whichCache) {
|
||||
case MethodTypeForm.LF_REBIND -> BOUND_REINVOKER;
|
||||
case MethodTypeForm.LF_DELEGATE -> DELEGATE;
|
||||
default -> REINVOKER;
|
||||
};
|
||||
}
|
||||
|
||||
static final NamedFunction NF_getTarget;
|
||||
|
@ -86,8 +86,8 @@ class DirectMethodHandle extends MethodHandle {
|
||||
if (!member.isField()) {
|
||||
// refKind reflects the original type of lookup via findSpecial or
|
||||
// findVirtual etc.
|
||||
switch (refKind) {
|
||||
case REF_invokeSpecial: {
|
||||
return switch (refKind) {
|
||||
case REF_invokeSpecial -> {
|
||||
member = member.asSpecial();
|
||||
// if caller is an interface we need to adapt to get the
|
||||
// receiver check inserted
|
||||
@ -95,20 +95,20 @@ class DirectMethodHandle extends MethodHandle {
|
||||
throw new InternalError("callerClass must not be null for REF_invokeSpecial");
|
||||
}
|
||||
LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
|
||||
return new Special(mtype, lform, member, true, callerClass);
|
||||
yield new Special(mtype, lform, member, true, callerClass);
|
||||
}
|
||||
case REF_invokeInterface: {
|
||||
case REF_invokeInterface -> {
|
||||
// for interfaces we always need the receiver typecheck,
|
||||
// so we always pass 'true' to ensure we adapt if needed
|
||||
// to include the REF_invokeSpecial case
|
||||
LambdaForm lform = preparedLambdaForm(member, true);
|
||||
return new Interface(mtype, lform, member, true, refc);
|
||||
yield new Interface(mtype, lform, member, true, refc);
|
||||
}
|
||||
default: {
|
||||
default -> {
|
||||
LambdaForm lform = preparedLambdaForm(member);
|
||||
return new DirectMethodHandle(mtype, lform, member, true);
|
||||
yield new DirectMethodHandle(mtype, lform, member, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
LambdaForm lform = preparedFieldLambdaForm(member);
|
||||
if (member.isStatic()) {
|
||||
@ -194,20 +194,19 @@ class DirectMethodHandle extends MethodHandle {
|
||||
assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead
|
||||
MethodType mtype = m.getInvocationType().basicType();
|
||||
assert(!m.isMethodHandleInvoke()) : m;
|
||||
int which;
|
||||
// MemberName.getReferenceKind represents the JVM optimized form of the call
|
||||
// as distinct from the "kind" passed to DMH.make which represents the original
|
||||
// bytecode-equivalent request. Specifically private/final methods that use a direct
|
||||
// call have getReferenceKind adapted to REF_invokeSpecial, even though the actual
|
||||
// invocation mode may be invokevirtual or invokeinterface.
|
||||
switch (m.getReferenceKind()) {
|
||||
case REF_invokeVirtual: which = LF_INVVIRTUAL; break;
|
||||
case REF_invokeStatic: which = LF_INVSTATIC; break;
|
||||
case REF_invokeSpecial: which = LF_INVSPECIAL; break;
|
||||
case REF_invokeInterface: which = LF_INVINTERFACE; break;
|
||||
case REF_newInvokeSpecial: which = LF_NEWINVSPECIAL; break;
|
||||
default: throw new InternalError(m.toString());
|
||||
}
|
||||
int which = switch (m.getReferenceKind()) {
|
||||
case REF_invokeVirtual -> LF_INVVIRTUAL;
|
||||
case REF_invokeStatic -> LF_INVSTATIC;
|
||||
case REF_invokeSpecial -> LF_INVSPECIAL;
|
||||
case REF_invokeInterface -> LF_INVINTERFACE;
|
||||
case REF_newInvokeSpecial -> LF_NEWINVSPECIAL;
|
||||
default -> throw new InternalError(m.toString());
|
||||
};
|
||||
if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
|
||||
// precompute the barrier-free version:
|
||||
preparedLambdaForm(mtype, which);
|
||||
@ -664,14 +663,13 @@ class DirectMethodHandle extends MethodHandle {
|
||||
private static LambdaForm preparedFieldLambdaForm(MemberName m) {
|
||||
Class<?> ftype = m.getFieldType();
|
||||
boolean isVolatile = m.isVolatile();
|
||||
byte formOp;
|
||||
switch (m.getReferenceKind()) {
|
||||
case REF_getField: formOp = AF_GETFIELD; break;
|
||||
case REF_putField: formOp = AF_PUTFIELD; break;
|
||||
case REF_getStatic: formOp = AF_GETSTATIC; break;
|
||||
case REF_putStatic: formOp = AF_PUTSTATIC; break;
|
||||
default: throw new InternalError(m.toString());
|
||||
}
|
||||
byte formOp = switch (m.getReferenceKind()) {
|
||||
case REF_getField -> AF_GETFIELD;
|
||||
case REF_putField -> AF_PUTFIELD;
|
||||
case REF_getStatic -> AF_GETSTATIC;
|
||||
case REF_putStatic -> AF_PUTSTATIC;
|
||||
default -> throw new InternalError(m.toString());
|
||||
};
|
||||
if (shouldBeInitialized(m)) {
|
||||
// precompute the barrier-free version:
|
||||
preparedFieldLambdaForm(formOp, isVolatile, ftype);
|
||||
|
@ -598,20 +598,14 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
}
|
||||
|
||||
private int invocationOpcode() throws InternalError {
|
||||
switch (implKind) {
|
||||
case MethodHandleInfo.REF_invokeStatic:
|
||||
return INVOKESTATIC;
|
||||
case MethodHandleInfo.REF_newInvokeSpecial:
|
||||
return INVOKESPECIAL;
|
||||
case MethodHandleInfo.REF_invokeVirtual:
|
||||
return INVOKEVIRTUAL;
|
||||
case MethodHandleInfo.REF_invokeInterface:
|
||||
return INVOKEINTERFACE;
|
||||
case MethodHandleInfo.REF_invokeSpecial:
|
||||
return INVOKESPECIAL;
|
||||
default:
|
||||
throw new InternalError("Unexpected invocation kind: " + implKind);
|
||||
}
|
||||
return switch (implKind) {
|
||||
case MethodHandleInfo.REF_invokeStatic -> INVOKESTATIC;
|
||||
case MethodHandleInfo.REF_newInvokeSpecial -> INVOKESPECIAL;
|
||||
case MethodHandleInfo.REF_invokeVirtual -> INVOKEVIRTUAL;
|
||||
case MethodHandleInfo.REF_invokeInterface -> INVOKEINTERFACE;
|
||||
case MethodHandleInfo.REF_invokeSpecial -> INVOKESPECIAL;
|
||||
default -> throw new InternalError("Unexpected invocation kind: " + implKind);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,15 +492,14 @@ class InvokerBytecodeGenerator {
|
||||
}
|
||||
|
||||
private int loadInsnOpcode(BasicType type) throws InternalError {
|
||||
switch (type) {
|
||||
case I_TYPE: return Opcodes.ILOAD;
|
||||
case J_TYPE: return Opcodes.LLOAD;
|
||||
case F_TYPE: return Opcodes.FLOAD;
|
||||
case D_TYPE: return Opcodes.DLOAD;
|
||||
case L_TYPE: return Opcodes.ALOAD;
|
||||
default:
|
||||
throw new InternalError("unknown type: " + type);
|
||||
}
|
||||
return switch (type) {
|
||||
case I_TYPE -> Opcodes.ILOAD;
|
||||
case J_TYPE -> Opcodes.LLOAD;
|
||||
case F_TYPE -> Opcodes.FLOAD;
|
||||
case D_TYPE -> Opcodes.DLOAD;
|
||||
case L_TYPE -> Opcodes.ALOAD;
|
||||
default -> throw new InternalError("unknown type: " + type);
|
||||
};
|
||||
}
|
||||
private void emitAloadInsn(int index) {
|
||||
emitLoadInsn(L_TYPE, index);
|
||||
@ -512,50 +511,48 @@ class InvokerBytecodeGenerator {
|
||||
}
|
||||
|
||||
private int storeInsnOpcode(BasicType type) throws InternalError {
|
||||
switch (type) {
|
||||
case I_TYPE: return Opcodes.ISTORE;
|
||||
case J_TYPE: return Opcodes.LSTORE;
|
||||
case F_TYPE: return Opcodes.FSTORE;
|
||||
case D_TYPE: return Opcodes.DSTORE;
|
||||
case L_TYPE: return Opcodes.ASTORE;
|
||||
default:
|
||||
throw new InternalError("unknown type: " + type);
|
||||
}
|
||||
return switch (type) {
|
||||
case I_TYPE -> Opcodes.ISTORE;
|
||||
case J_TYPE -> Opcodes.LSTORE;
|
||||
case F_TYPE -> Opcodes.FSTORE;
|
||||
case D_TYPE -> Opcodes.DSTORE;
|
||||
case L_TYPE -> Opcodes.ASTORE;
|
||||
default -> throw new InternalError("unknown type: " + type);
|
||||
};
|
||||
}
|
||||
private void emitAstoreInsn(int index) {
|
||||
emitStoreInsn(L_TYPE, index);
|
||||
}
|
||||
|
||||
private byte arrayTypeCode(Wrapper elementType) {
|
||||
switch (elementType) {
|
||||
case BOOLEAN: return Opcodes.T_BOOLEAN;
|
||||
case BYTE: return Opcodes.T_BYTE;
|
||||
case CHAR: return Opcodes.T_CHAR;
|
||||
case SHORT: return Opcodes.T_SHORT;
|
||||
case INT: return Opcodes.T_INT;
|
||||
case LONG: return Opcodes.T_LONG;
|
||||
case FLOAT: return Opcodes.T_FLOAT;
|
||||
case DOUBLE: return Opcodes.T_DOUBLE;
|
||||
case OBJECT: return 0; // in place of Opcodes.T_OBJECT
|
||||
default: throw new InternalError();
|
||||
}
|
||||
return (byte) switch (elementType) {
|
||||
case BOOLEAN -> Opcodes.T_BOOLEAN;
|
||||
case BYTE -> Opcodes.T_BYTE;
|
||||
case CHAR -> Opcodes.T_CHAR;
|
||||
case SHORT -> Opcodes.T_SHORT;
|
||||
case INT -> Opcodes.T_INT;
|
||||
case LONG -> Opcodes.T_LONG;
|
||||
case FLOAT -> Opcodes.T_FLOAT;
|
||||
case DOUBLE -> Opcodes.T_DOUBLE;
|
||||
case OBJECT -> 0; // in place of Opcodes.T_OBJECT
|
||||
default -> throw new InternalError();
|
||||
};
|
||||
}
|
||||
|
||||
private int arrayInsnOpcode(byte tcode, int aaop) throws InternalError {
|
||||
assert(aaop == Opcodes.AASTORE || aaop == Opcodes.AALOAD);
|
||||
int xas;
|
||||
switch (tcode) {
|
||||
case Opcodes.T_BOOLEAN: xas = Opcodes.BASTORE; break;
|
||||
case Opcodes.T_BYTE: xas = Opcodes.BASTORE; break;
|
||||
case Opcodes.T_CHAR: xas = Opcodes.CASTORE; break;
|
||||
case Opcodes.T_SHORT: xas = Opcodes.SASTORE; break;
|
||||
case Opcodes.T_INT: xas = Opcodes.IASTORE; break;
|
||||
case Opcodes.T_LONG: xas = Opcodes.LASTORE; break;
|
||||
case Opcodes.T_FLOAT: xas = Opcodes.FASTORE; break;
|
||||
case Opcodes.T_DOUBLE: xas = Opcodes.DASTORE; break;
|
||||
case 0: xas = Opcodes.AASTORE; break;
|
||||
default: throw new InternalError();
|
||||
}
|
||||
int xas = switch (tcode) {
|
||||
case Opcodes.T_BOOLEAN -> Opcodes.BASTORE;
|
||||
case Opcodes.T_BYTE -> Opcodes.BASTORE;
|
||||
case Opcodes.T_CHAR -> Opcodes.CASTORE;
|
||||
case Opcodes.T_SHORT -> Opcodes.SASTORE;
|
||||
case Opcodes.T_INT -> Opcodes.IASTORE;
|
||||
case Opcodes.T_LONG -> Opcodes.LASTORE;
|
||||
case Opcodes.T_FLOAT -> Opcodes.FASTORE;
|
||||
case Opcodes.T_DOUBLE -> Opcodes.DASTORE;
|
||||
case 0 -> Opcodes.AASTORE;
|
||||
default -> throw new InternalError();
|
||||
};
|
||||
return xas - Opcodes.AASTORE + aaop;
|
||||
}
|
||||
|
||||
@ -1383,17 +1380,11 @@ class InvokerBytecodeGenerator {
|
||||
}
|
||||
|
||||
private static int popInsnOpcode(BasicType type) {
|
||||
switch (type) {
|
||||
case I_TYPE:
|
||||
case F_TYPE:
|
||||
case L_TYPE:
|
||||
return Opcodes.POP;
|
||||
case J_TYPE:
|
||||
case D_TYPE:
|
||||
return Opcodes.POP2;
|
||||
default:
|
||||
throw new InternalError("unknown type: " + type);
|
||||
}
|
||||
return switch (type) {
|
||||
case I_TYPE, F_TYPE, L_TYPE -> Opcodes.POP;
|
||||
case J_TYPE, D_TYPE -> Opcodes.POP2;
|
||||
default -> throw new InternalError("unknown type: " + type);
|
||||
};
|
||||
}
|
||||
|
||||
private Name emitTableSwitch(int pos, int numCases) {
|
||||
@ -1663,14 +1654,14 @@ class InvokerBytecodeGenerator {
|
||||
}
|
||||
|
||||
private void emitZero(BasicType type) {
|
||||
switch (type) {
|
||||
case I_TYPE: mv.visitInsn(Opcodes.ICONST_0); break;
|
||||
case J_TYPE: mv.visitInsn(Opcodes.LCONST_0); break;
|
||||
case F_TYPE: mv.visitInsn(Opcodes.FCONST_0); break;
|
||||
case D_TYPE: mv.visitInsn(Opcodes.DCONST_0); break;
|
||||
case L_TYPE: mv.visitInsn(Opcodes.ACONST_NULL); break;
|
||||
default: throw new InternalError("unknown type: " + type);
|
||||
}
|
||||
mv.visitInsn(switch (type) {
|
||||
case I_TYPE -> Opcodes.ICONST_0;
|
||||
case J_TYPE -> Opcodes.LCONST_0;
|
||||
case F_TYPE -> Opcodes.FCONST_0;
|
||||
case D_TYPE -> Opcodes.DCONST_0;
|
||||
case L_TYPE -> Opcodes.ACONST_NULL;
|
||||
default -> throw new InternalError("unknown type: " + type);
|
||||
});
|
||||
}
|
||||
|
||||
private void emitPushArguments(Name args, int start) {
|
||||
@ -1778,30 +1769,28 @@ class InvokerBytecodeGenerator {
|
||||
// cast to {long,float,double} - this is verbose
|
||||
boolean error = false;
|
||||
switch (from) {
|
||||
case LONG:
|
||||
switch (to) {
|
||||
case FLOAT: mv.visitInsn(Opcodes.L2F); break;
|
||||
case DOUBLE: mv.visitInsn(Opcodes.L2D); break;
|
||||
default: error = true; break;
|
||||
case LONG -> {
|
||||
switch (to) {
|
||||
case FLOAT -> mv.visitInsn(Opcodes.L2F);
|
||||
case DOUBLE -> mv.visitInsn(Opcodes.L2D);
|
||||
default -> error = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FLOAT:
|
||||
switch (to) {
|
||||
case LONG : mv.visitInsn(Opcodes.F2L); break;
|
||||
case DOUBLE: mv.visitInsn(Opcodes.F2D); break;
|
||||
default: error = true; break;
|
||||
case FLOAT -> {
|
||||
switch (to) {
|
||||
case LONG -> mv.visitInsn(Opcodes.F2L);
|
||||
case DOUBLE -> mv.visitInsn(Opcodes.F2D);
|
||||
default -> error = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DOUBLE:
|
||||
switch (to) {
|
||||
case LONG : mv.visitInsn(Opcodes.D2L); break;
|
||||
case FLOAT: mv.visitInsn(Opcodes.D2F); break;
|
||||
default: error = true; break;
|
||||
case DOUBLE -> {
|
||||
switch (to) {
|
||||
case LONG -> mv.visitInsn(Opcodes.D2L);
|
||||
case FLOAT -> mv.visitInsn(Opcodes.D2F);
|
||||
default -> error = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
break;
|
||||
default -> error = true;
|
||||
}
|
||||
if (error) {
|
||||
throw new IllegalStateException("unhandled prim cast: " + from + "2" + to);
|
||||
|
@ -254,12 +254,11 @@ class Invokers {
|
||||
static MemberName methodHandleInvokeLinkerMethod(String name,
|
||||
MethodType mtype,
|
||||
Object[] appendixResult) {
|
||||
int which;
|
||||
switch (name) {
|
||||
case "invokeExact": which = MethodTypeForm.LF_EX_LINKER; break;
|
||||
case "invoke": which = MethodTypeForm.LF_GEN_LINKER; break;
|
||||
default: throw new InternalError("not invoker: "+name);
|
||||
}
|
||||
int which = switch (name) {
|
||||
case "invokeExact" -> MethodTypeForm.LF_EX_LINKER;
|
||||
case "invoke" -> MethodTypeForm.LF_GEN_LINKER;
|
||||
default -> throw new InternalError("not invoker: " + name);
|
||||
};
|
||||
LambdaForm lform;
|
||||
if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
|
||||
lform = invokeHandleForm(mtype, false, which);
|
||||
@ -660,24 +659,16 @@ class Invokers {
|
||||
|
||||
private static NamedFunction createFunction(byte func) {
|
||||
try {
|
||||
switch (func) {
|
||||
case NF_checkExactType:
|
||||
return getNamedFunction("checkExactType", MethodType.methodType(void.class, MethodHandle.class, MethodType.class));
|
||||
case NF_checkGenericType:
|
||||
return getNamedFunction("checkGenericType", MethodType.methodType(MethodHandle.class, MethodHandle.class, MethodType.class));
|
||||
case NF_getCallSiteTarget:
|
||||
return getNamedFunction("getCallSiteTarget", MethodType.methodType(MethodHandle.class, CallSite.class));
|
||||
case NF_checkCustomized:
|
||||
return getNamedFunction("checkCustomized", MethodType.methodType(void.class, MethodHandle.class));
|
||||
case NF_checkVarHandleGenericType:
|
||||
return getNamedFunction("checkVarHandleGenericType", MethodType.methodType(MethodHandle.class, VarHandle.class, VarHandle.AccessDescriptor.class));
|
||||
case NF_checkVarHandleExactType:
|
||||
return getNamedFunction("checkVarHandleExactType", MethodType.methodType(MethodHandle.class, VarHandle.class, VarHandle.AccessDescriptor.class));
|
||||
case NF_directVarHandleTarget:
|
||||
return getNamedFunction("directVarHandleTarget", MethodType.methodType(VarHandle.class, VarHandle.class));
|
||||
default:
|
||||
throw newInternalError("Unknown function: " + func);
|
||||
}
|
||||
return switch (func) {
|
||||
case NF_checkExactType -> getNamedFunction("checkExactType", MethodType.methodType(void.class, MethodHandle.class, MethodType.class));
|
||||
case NF_checkGenericType -> getNamedFunction("checkGenericType", MethodType.methodType(MethodHandle.class, MethodHandle.class, MethodType.class));
|
||||
case NF_getCallSiteTarget -> getNamedFunction("getCallSiteTarget", MethodType.methodType(MethodHandle.class, CallSite.class));
|
||||
case NF_checkCustomized -> getNamedFunction("checkCustomized", MethodType.methodType(void.class, MethodHandle.class));
|
||||
case NF_checkVarHandleGenericType -> getNamedFunction("checkVarHandleGenericType", MethodType.methodType(MethodHandle.class, VarHandle.class, VarHandle.AccessDescriptor.class));
|
||||
case NF_checkVarHandleExactType -> getNamedFunction("checkVarHandleExactType", MethodType.methodType(MethodHandle.class, VarHandle.class, VarHandle.AccessDescriptor.class));
|
||||
case NF_directVarHandleTarget -> getNamedFunction("directVarHandleTarget", MethodType.methodType(VarHandle.class, VarHandle.class));
|
||||
default -> throw newInternalError("Unknown function: " + func);
|
||||
};
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw newInternalError(ex);
|
||||
}
|
||||
|
@ -187,22 +187,17 @@ class LambdaForm {
|
||||
return ALL_TYPES[type];
|
||||
}
|
||||
static BasicType basicType(char type) {
|
||||
switch (type) {
|
||||
case 'L': return L_TYPE;
|
||||
case 'I': return I_TYPE;
|
||||
case 'J': return J_TYPE;
|
||||
case 'F': return F_TYPE;
|
||||
case 'D': return D_TYPE;
|
||||
case 'V': return V_TYPE;
|
||||
return switch (type) {
|
||||
case 'L' -> L_TYPE;
|
||||
case 'I' -> I_TYPE;
|
||||
case 'J' -> J_TYPE;
|
||||
case 'F' -> F_TYPE;
|
||||
case 'D' -> D_TYPE;
|
||||
case 'V' -> V_TYPE;
|
||||
// all subword types are represented as ints
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'C':
|
||||
return I_TYPE;
|
||||
default:
|
||||
throw newInternalError("Unknown type char: '"+type+"'");
|
||||
}
|
||||
case 'Z', 'B', 'S', 'C' -> I_TYPE;
|
||||
default -> throw newInternalError("Unknown type char: '" + type + "'");
|
||||
};
|
||||
}
|
||||
static BasicType basicType(Wrapper type) {
|
||||
char c = type.basicTypeChar();
|
||||
|
@ -313,20 +313,22 @@ final class MemberName implements Member, Cloneable {
|
||||
/*non-public*/
|
||||
boolean referenceKindIsConsistentWith(int originalRefKind) {
|
||||
int refKind = getReferenceKind();
|
||||
if (refKind == originalRefKind) return true;
|
||||
switch (originalRefKind) {
|
||||
case REF_invokeInterface:
|
||||
// Looking up an interface method, can get (e.g.) Object.hashCode
|
||||
assert(refKind == REF_invokeVirtual ||
|
||||
refKind == REF_invokeSpecial) : this;
|
||||
return true;
|
||||
case REF_invokeVirtual:
|
||||
case REF_newInvokeSpecial:
|
||||
// Looked up a virtual, can get (e.g.) final String.hashCode.
|
||||
assert(refKind == REF_invokeSpecial) : this;
|
||||
return true;
|
||||
if (refKind == originalRefKind) return true;
|
||||
if (getClass().desiredAssertionStatus()) {
|
||||
switch (originalRefKind) {
|
||||
case REF_invokeInterface -> {
|
||||
// Looking up an interface method, can get (e.g.) Object.hashCode
|
||||
assert (refKind == REF_invokeVirtual || refKind == REF_invokeSpecial) : this;
|
||||
}
|
||||
case REF_invokeVirtual, REF_newInvokeSpecial -> {
|
||||
// Looked up a virtual, can get (e.g.) final String.hashCode.
|
||||
assert (refKind == REF_invokeSpecial) : this;
|
||||
}
|
||||
default -> {
|
||||
assert (false) : this + " != " + MethodHandleNatives.refKindName((byte) originalRefKind);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind);
|
||||
return true;
|
||||
}
|
||||
private boolean staticIsConsistent() {
|
||||
|
@ -1558,32 +1558,22 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
switch (info.getReferenceKind()) {
|
||||
case REF_getField:
|
||||
return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.GETTER, owner, name, type.returnType()));
|
||||
case REF_putField:
|
||||
return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.SETTER, owner, name, type.parameterType(0)));
|
||||
case REF_getStatic:
|
||||
return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.STATIC_GETTER, owner, name, type.returnType()));
|
||||
case REF_putStatic:
|
||||
return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.STATIC_SETTER, owner, name, type.parameterType(0)));
|
||||
case REF_invokeVirtual:
|
||||
return Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.VIRTUAL, owner, name, type));
|
||||
case REF_invokeStatic:
|
||||
return isInterface ?
|
||||
Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, owner, name, type)) :
|
||||
Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, owner, name, type));
|
||||
case REF_invokeSpecial:
|
||||
return isInterface ?
|
||||
Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_SPECIAL, owner, name, type)) :
|
||||
Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.SPECIAL, owner, name, type));
|
||||
case REF_invokeInterface:
|
||||
return Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, owner, name, type));
|
||||
case REF_newInvokeSpecial:
|
||||
return Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.CONSTRUCTOR, owner, name, type));
|
||||
default:
|
||||
return Optional.empty();
|
||||
}
|
||||
return switch (info.getReferenceKind()) {
|
||||
case REF_getField -> Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.GETTER, owner, name, type.returnType()));
|
||||
case REF_putField -> Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.SETTER, owner, name, type.parameterType(0)));
|
||||
case REF_getStatic -> Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.STATIC_GETTER, owner, name, type.returnType()));
|
||||
case REF_putStatic -> Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.STATIC_SETTER, owner, name, type.parameterType(0)));
|
||||
case REF_invokeVirtual -> Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.VIRTUAL, owner, name, type));
|
||||
case REF_invokeStatic -> isInterface ?
|
||||
Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, owner, name, type)) :
|
||||
Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, owner, name, type));
|
||||
case REF_invokeSpecial -> isInterface ?
|
||||
Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_SPECIAL, owner, name, type)) :
|
||||
Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.SPECIAL, owner, name, type));
|
||||
case REF_invokeInterface -> Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, owner, name, type));
|
||||
case REF_newInvokeSpecial -> Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.CONSTRUCTOR, owner, name, type));
|
||||
default -> Optional.empty();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,39 +109,39 @@ abstract class MethodHandleImpl {
|
||||
// final fields.
|
||||
|
||||
static String opName(ArrayAccess a) {
|
||||
switch (a) {
|
||||
case GET: return "getElement";
|
||||
case SET: return "setElement";
|
||||
case LENGTH: return "length";
|
||||
}
|
||||
throw unmatchedArrayAccess(a);
|
||||
return switch (a) {
|
||||
case GET -> "getElement";
|
||||
case SET -> "setElement";
|
||||
case LENGTH -> "length";
|
||||
default -> throw unmatchedArrayAccess(a);
|
||||
};
|
||||
}
|
||||
|
||||
static MethodHandle objectAccessor(ArrayAccess a) {
|
||||
switch (a) {
|
||||
case GET: return ArrayAccessor.OBJECT_ARRAY_GETTER;
|
||||
case SET: return ArrayAccessor.OBJECT_ARRAY_SETTER;
|
||||
case LENGTH: return ArrayAccessor.OBJECT_ARRAY_LENGTH;
|
||||
}
|
||||
throw unmatchedArrayAccess(a);
|
||||
return switch (a) {
|
||||
case GET -> ArrayAccessor.OBJECT_ARRAY_GETTER;
|
||||
case SET -> ArrayAccessor.OBJECT_ARRAY_SETTER;
|
||||
case LENGTH -> ArrayAccessor.OBJECT_ARRAY_LENGTH;
|
||||
default -> throw unmatchedArrayAccess(a);
|
||||
};
|
||||
}
|
||||
|
||||
static int cacheIndex(ArrayAccess a) {
|
||||
switch (a) {
|
||||
case GET: return ArrayAccessor.GETTER_INDEX;
|
||||
case SET: return ArrayAccessor.SETTER_INDEX;
|
||||
case LENGTH: return ArrayAccessor.LENGTH_INDEX;
|
||||
}
|
||||
throw unmatchedArrayAccess(a);
|
||||
return switch (a) {
|
||||
case GET -> ArrayAccessor.GETTER_INDEX;
|
||||
case SET -> ArrayAccessor.SETTER_INDEX;
|
||||
case LENGTH -> ArrayAccessor.LENGTH_INDEX;
|
||||
default -> throw unmatchedArrayAccess(a);
|
||||
};
|
||||
}
|
||||
|
||||
static Intrinsic intrinsic(ArrayAccess a) {
|
||||
switch (a) {
|
||||
case GET: return Intrinsic.ARRAY_LOAD;
|
||||
case SET: return Intrinsic.ARRAY_STORE;
|
||||
case LENGTH: return Intrinsic.ARRAY_LENGTH;
|
||||
}
|
||||
throw unmatchedArrayAccess(a);
|
||||
return switch (a) {
|
||||
case GET -> Intrinsic.ARRAY_LOAD;
|
||||
case SET -> Intrinsic.ARRAY_STORE;
|
||||
case LENGTH -> Intrinsic.ARRAY_LENGTH;
|
||||
default -> throw unmatchedArrayAccess(a);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,21 +213,21 @@ abstract class MethodHandleImpl {
|
||||
arrayArgClass = Object[].class;
|
||||
elemClass = Object.class;
|
||||
}
|
||||
switch (access) {
|
||||
case GET: return MethodType.methodType(elemClass, arrayArgClass, int.class);
|
||||
case SET: return MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
|
||||
case LENGTH: return MethodType.methodType(int.class, arrayArgClass);
|
||||
}
|
||||
throw unmatchedArrayAccess(access);
|
||||
return switch (access) {
|
||||
case GET -> MethodType.methodType(elemClass, arrayArgClass, int.class);
|
||||
case SET -> MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
|
||||
case LENGTH -> MethodType.methodType(int.class, arrayArgClass);
|
||||
default -> throw unmatchedArrayAccess(access);
|
||||
};
|
||||
}
|
||||
static MethodType correctType(Class<?> arrayClass, ArrayAccess access) {
|
||||
Class<?> elemClass = arrayClass.getComponentType();
|
||||
switch (access) {
|
||||
case GET: return MethodType.methodType(elemClass, arrayClass, int.class);
|
||||
case SET: return MethodType.methodType(void.class, arrayClass, int.class, elemClass);
|
||||
case LENGTH: return MethodType.methodType(int.class, arrayClass);
|
||||
}
|
||||
throw unmatchedArrayAccess(access);
|
||||
return switch (access) {
|
||||
case GET -> MethodType.methodType(elemClass, arrayClass, int.class);
|
||||
case SET -> MethodType.methodType(void.class, arrayClass, int.class, elemClass);
|
||||
case LENGTH -> MethodType.methodType(int.class, arrayClass);
|
||||
default -> throw unmatchedArrayAccess(access);
|
||||
};
|
||||
}
|
||||
static MethodHandle getAccessor(Class<?> arrayClass, ArrayAccess access) {
|
||||
String name = name(arrayClass, access);
|
||||
@ -980,13 +980,12 @@ abstract class MethodHandleImpl {
|
||||
|
||||
static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
|
||||
static MethodHandle fakeMethodHandleInvoke(MemberName method) {
|
||||
int idx;
|
||||
assert(method.isMethodHandleInvoke());
|
||||
switch (method.getName()) {
|
||||
case "invoke": idx = 0; break;
|
||||
case "invokeExact": idx = 1; break;
|
||||
default: throw new InternalError(method.getName());
|
||||
}
|
||||
int idx = switch (method.getName()) {
|
||||
case "invoke" -> 0;
|
||||
case "invokeExact" -> 1;
|
||||
default -> throw new InternalError(method.getName());
|
||||
};
|
||||
MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
|
||||
if (mh != null) return mh;
|
||||
MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
|
||||
@ -1395,32 +1394,24 @@ abstract class MethodHandleImpl {
|
||||
|
||||
private static NamedFunction createFunction(byte func) {
|
||||
try {
|
||||
switch (func) {
|
||||
case NF_checkSpreadArgument:
|
||||
return new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
|
||||
case NF_guardWithCatch:
|
||||
return new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
|
||||
MethodHandle.class, Object[].class));
|
||||
case NF_tryFinally:
|
||||
return new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("tryFinally", MethodHandle.class, MethodHandle.class, Object[].class));
|
||||
case NF_loop:
|
||||
return new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("loop", BasicType[].class, LoopClauses.class, Object[].class));
|
||||
case NF_throwException:
|
||||
return new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("throwException", Throwable.class));
|
||||
case NF_profileBoolean:
|
||||
return new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("profileBoolean", boolean.class, int[].class));
|
||||
case NF_tableSwitch:
|
||||
return new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("tableSwitch", int.class, MethodHandle.class, CasesHolder.class, Object[].class));
|
||||
default:
|
||||
throw new InternalError("Undefined function: " + func);
|
||||
}
|
||||
return switch (func) {
|
||||
case NF_checkSpreadArgument -> new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
|
||||
case NF_guardWithCatch -> new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
|
||||
MethodHandle.class, Object[].class));
|
||||
case NF_tryFinally -> new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("tryFinally", MethodHandle.class, MethodHandle.class, Object[].class));
|
||||
case NF_loop -> new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("loop", BasicType[].class, LoopClauses.class, Object[].class));
|
||||
case NF_throwException -> new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("throwException", Throwable.class));
|
||||
case NF_profileBoolean -> new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("profileBoolean", boolean.class, int[].class));
|
||||
case NF_tableSwitch -> new NamedFunction(MethodHandleImpl.class
|
||||
.getDeclaredMethod("tableSwitch", int.class, MethodHandle.class, CasesHolder.class, Object[].class));
|
||||
default -> throw new InternalError("Undefined function: " + func);
|
||||
};
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw newInternalError(ex);
|
||||
}
|
||||
|
@ -206,18 +206,18 @@ class MethodHandleNatives {
|
||||
}
|
||||
static String refKindName(byte refKind) {
|
||||
assert(refKindIsValid(refKind));
|
||||
switch (refKind) {
|
||||
case REF_getField: return "getField";
|
||||
case REF_getStatic: return "getStatic";
|
||||
case REF_putField: return "putField";
|
||||
case REF_putStatic: return "putStatic";
|
||||
case REF_invokeVirtual: return "invokeVirtual";
|
||||
case REF_invokeStatic: return "invokeStatic";
|
||||
case REF_invokeSpecial: return "invokeSpecial";
|
||||
case REF_newInvokeSpecial: return "newInvokeSpecial";
|
||||
case REF_invokeInterface: return "invokeInterface";
|
||||
default: return "REF_???";
|
||||
}
|
||||
return switch (refKind) {
|
||||
case REF_getField -> "getField";
|
||||
case REF_getStatic -> "getStatic";
|
||||
case REF_putField -> "putField";
|
||||
case REF_putStatic -> "putStatic";
|
||||
case REF_invokeVirtual -> "invokeVirtual";
|
||||
case REF_invokeStatic -> "invokeStatic";
|
||||
case REF_invokeSpecial -> "invokeSpecial";
|
||||
case REF_newInvokeSpecial -> "newInvokeSpecial";
|
||||
case REF_invokeInterface -> "invokeInterface";
|
||||
default -> "REF_???";
|
||||
};
|
||||
}
|
||||
|
||||
private static native int getNamedCon(int which, Object[] name);
|
||||
|
@ -274,32 +274,26 @@ public class MethodHandleProxies {
|
||||
}
|
||||
|
||||
private static boolean isObjectMethod(Method m) {
|
||||
switch (m.getName()) {
|
||||
case "toString":
|
||||
return (m.getReturnType() == String.class
|
||||
&& m.getParameterCount() == 0);
|
||||
case "hashCode":
|
||||
return (m.getReturnType() == int.class
|
||||
&& m.getParameterCount() == 0);
|
||||
case "equals":
|
||||
return (m.getReturnType() == boolean.class
|
||||
&& m.getParameterCount() == 1
|
||||
&& m.getParameterTypes()[0] == Object.class);
|
||||
}
|
||||
return false;
|
||||
return switch (m.getName()) {
|
||||
case "toString" -> m.getReturnType() == String.class
|
||||
&& m.getParameterCount() == 0;
|
||||
case "hashCode" -> m.getReturnType() == int.class
|
||||
&& m.getParameterCount() == 0;
|
||||
case "equals" -> m.getReturnType() == boolean.class
|
||||
&& m.getParameterCount() == 1
|
||||
&& m.getParameterTypes()[0] == Object.class;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static Object callObjectMethod(Object self, Method m, Object[] args) {
|
||||
assert(isObjectMethod(m)) : m;
|
||||
switch (m.getName()) {
|
||||
case "toString":
|
||||
return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
|
||||
case "hashCode":
|
||||
return System.identityHashCode(self);
|
||||
case "equals":
|
||||
return (self == args[0]);
|
||||
}
|
||||
return null;
|
||||
return switch (m.getName()) {
|
||||
case "toString" -> self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
|
||||
case "hashCode" -> System.identityHashCode(self);
|
||||
case "equals" -> (self == args[0]);
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private static Method[] getSingleNameMethods(Class<?> intfc) {
|
||||
|
@ -5175,13 +5175,13 @@ assert((int)twice.invokeExact(21) == 42);
|
||||
Wrapper w = Wrapper.forPrimitiveType(ptype);
|
||||
// perform unboxing and/or primitive conversion
|
||||
value = w.convert(value, ptype);
|
||||
switch (w) {
|
||||
case INT: return result.bindArgumentI(pos, (int)value);
|
||||
case LONG: return result.bindArgumentJ(pos, (long)value);
|
||||
case FLOAT: return result.bindArgumentF(pos, (float)value);
|
||||
case DOUBLE: return result.bindArgumentD(pos, (double)value);
|
||||
default: return result.bindArgumentI(pos, ValueConversions.widenSubword(value));
|
||||
}
|
||||
return switch (w) {
|
||||
case INT -> result.bindArgumentI(pos, (int) value);
|
||||
case LONG -> result.bindArgumentJ(pos, (long) value);
|
||||
case FLOAT -> result.bindArgumentF(pos, (float) value);
|
||||
case DOUBLE -> result.bindArgumentD(pos, (double) value);
|
||||
default -> result.bindArgumentI(pos, ValueConversions.widenSubword(value));
|
||||
};
|
||||
}
|
||||
|
||||
private static Class<?>[] insertArgumentsChecks(MethodHandle target, int insCount, int pos) throws RuntimeException {
|
||||
|
@ -2282,15 +2282,11 @@ public abstract class VarHandle implements Constable {
|
||||
}
|
||||
|
||||
ConstantDesc[] toBSMArgs(ClassDesc declaringClass, ClassDesc varType) {
|
||||
switch (this) {
|
||||
case FIELD:
|
||||
case STATIC_FIELD:
|
||||
return new ConstantDesc[] {declaringClass, varType };
|
||||
case ARRAY:
|
||||
return new ConstantDesc[] {declaringClass };
|
||||
default:
|
||||
throw new InternalError("Cannot reach here");
|
||||
}
|
||||
return switch (this) {
|
||||
case FIELD, STATIC_FIELD -> new ConstantDesc[]{declaringClass, varType};
|
||||
case ARRAY -> new ConstantDesc[]{declaringClass};
|
||||
default -> throw new InternalError("Cannot reach here");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -2385,20 +2381,16 @@ public abstract class VarHandle implements Constable {
|
||||
@Override
|
||||
public VarHandle resolveConstantDesc(MethodHandles.Lookup lookup)
|
||||
throws ReflectiveOperationException {
|
||||
switch (kind) {
|
||||
case FIELD:
|
||||
return lookup.findVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup),
|
||||
constantName(),
|
||||
(Class<?>) varType.resolveConstantDesc(lookup));
|
||||
case STATIC_FIELD:
|
||||
return lookup.findStaticVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup),
|
||||
constantName(),
|
||||
(Class<?>) varType.resolveConstantDesc(lookup));
|
||||
case ARRAY:
|
||||
return MethodHandles.arrayElementVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup));
|
||||
default:
|
||||
throw new InternalError("Cannot reach here");
|
||||
}
|
||||
return switch (kind) {
|
||||
case FIELD -> lookup.findVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup),
|
||||
constantName(),
|
||||
(Class<?>) varType.resolveConstantDesc(lookup));
|
||||
case STATIC_FIELD -> lookup.findStaticVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup),
|
||||
constantName(),
|
||||
(Class<?>) varType.resolveConstantDesc(lookup));
|
||||
case ARRAY -> MethodHandles.arrayElementVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup));
|
||||
default -> throw new InternalError("Cannot reach here");
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2411,17 +2403,13 @@ public abstract class VarHandle implements Constable {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (kind) {
|
||||
case FIELD:
|
||||
case STATIC_FIELD:
|
||||
return String.format("VarHandleDesc[%s%s.%s:%s]",
|
||||
(kind == Kind.STATIC_FIELD) ? "static " : "",
|
||||
declaringClass.displayName(), constantName(), varType.displayName());
|
||||
case ARRAY:
|
||||
return String.format("VarHandleDesc[%s[]]", declaringClass.displayName());
|
||||
default:
|
||||
throw new InternalError("Cannot reach here");
|
||||
}
|
||||
return switch (kind) {
|
||||
case FIELD, STATIC_FIELD -> String.format("VarHandleDesc[%s%s.%s:%s]",
|
||||
(kind == Kind.STATIC_FIELD) ? "static " : "",
|
||||
declaringClass.displayName(), constantName(), varType.displayName());
|
||||
case ARRAY -> String.format("VarHandleDesc[%s[]]", declaringClass.displayName());
|
||||
default -> throw new InternalError("Cannot reach here");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,28 +339,27 @@ public class ObjectMethods {
|
||||
throw new IllegalArgumentException(type.toString());
|
||||
}
|
||||
List<MethodHandle> getterList = List.of(getters);
|
||||
MethodHandle handle;
|
||||
switch (methodName) {
|
||||
case "equals":
|
||||
MethodHandle handle = switch (methodName) {
|
||||
case "equals" -> {
|
||||
if (methodType != null && !methodType.equals(MethodType.methodType(boolean.class, recordClass, Object.class)))
|
||||
throw new IllegalArgumentException("Bad method type: " + methodType);
|
||||
handle = makeEquals(recordClass, getterList);
|
||||
return methodType != null ? new ConstantCallSite(handle) : handle;
|
||||
case "hashCode":
|
||||
yield makeEquals(recordClass, getterList);
|
||||
}
|
||||
case "hashCode" -> {
|
||||
if (methodType != null && !methodType.equals(MethodType.methodType(int.class, recordClass)))
|
||||
throw new IllegalArgumentException("Bad method type: " + methodType);
|
||||
handle = makeHashCode(recordClass, getterList);
|
||||
return methodType != null ? new ConstantCallSite(handle) : handle;
|
||||
case "toString":
|
||||
yield makeHashCode(recordClass, getterList);
|
||||
}
|
||||
case "toString" -> {
|
||||
if (methodType != null && !methodType.equals(MethodType.methodType(String.class, recordClass)))
|
||||
throw new IllegalArgumentException("Bad method type: " + methodType);
|
||||
List<String> nameList = "".equals(names) ? List.of() : List.of(names.split(";"));
|
||||
if (nameList.size() != getterList.size())
|
||||
throw new IllegalArgumentException("Name list and accessor list do not match");
|
||||
handle = makeToString(recordClass, getterList, nameList);
|
||||
return methodType != null ? new ConstantCallSite(handle) : handle;
|
||||
default:
|
||||
throw new IllegalArgumentException(methodName);
|
||||
}
|
||||
yield makeToString(recordClass, getterList, nameList);
|
||||
}
|
||||
default -> throw new IllegalArgumentException(methodName);
|
||||
};
|
||||
return methodType != null ? new ConstantCallSite(handle) : handle;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user