8260605: Various java.lang.invoke cleanups

Reviewed-by: mchung
This commit is contained in:
Claes Redestad 2021-03-18 12:47:57 +00:00
parent 9cd21b687e
commit 63eae8fac2
4 changed files with 118 additions and 246 deletions

View file

@ -84,10 +84,13 @@ final class BootstrapMethodInvoker {
// By providing static type information or even invoking
// exactly, we avoid emitting code to perform runtime
// checking.
info = maybeReBox(info);
if (info == null) {
// VM is allowed to pass up a null meaning no BSM args
result = invoke(bootstrapMethod, caller, name, type);
if (type instanceof Class<?> c) {
result = bootstrapMethod.invoke(caller, name, c);
} else {
result = bootstrapMethod.invoke(caller, name, (MethodType)type);
}
}
else if (!info.getClass().isArray()) {
// VM is allowed to pass up a single BSM arg directly
@ -99,7 +102,12 @@ final class BootstrapMethodInvoker {
.invokeExact(caller, name, (MethodType)type,
(String)info, new Object[0]);
} else {
result = invoke(bootstrapMethod, caller, name, type, info);
info = maybeReBox(info);
if (type instanceof Class<?> c) {
result = bootstrapMethod.invoke(caller, name, c, info);
} else {
result = bootstrapMethod.invoke(caller, name, (MethodType)type, info);
}
}
}
else if (info.getClass() == int[].class) {
@ -119,7 +127,6 @@ final class BootstrapMethodInvoker {
else {
// VM is allowed to pass up a full array of resolved BSM args
Object[] argv = (Object[]) info;
maybeReBoxElements(argv);
MethodType bsmType = bootstrapMethod.type();
if (isLambdaMetafactoryIndyBSM(bsmType) && argv.length == 3) {
@ -133,40 +140,36 @@ final class BootstrapMethodInvoker {
} else if (isStringConcatFactoryBSM(bsmType) && argv.length >= 1) {
String recipe = (String)argv[0];
Object[] shiftedArgs = Arrays.copyOfRange(argv, 1, argv.length);
maybeReBoxElements(shiftedArgs);
result = (CallSite)bootstrapMethod.invokeExact(caller, name, (MethodType)type, recipe, shiftedArgs);
} else if (isLambdaMetafactoryAltMetafactoryBSM(bsmType)) {
maybeReBoxElements(argv);
result = (CallSite)bootstrapMethod.invokeExact(caller, name, (MethodType)type, argv);
} else {
switch (argv.length) {
case 0:
result = invoke(bootstrapMethod, caller, name, type);
break;
case 1:
result = invoke(bootstrapMethod, caller, name, type,
argv[0]);
break;
case 2:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1]);
break;
case 3:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1], argv[2]);
break;
case 4:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1], argv[2], argv[3]);
break;
case 5:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1], argv[2], argv[3], argv[4]);
break;
case 6:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
break;
default:
result = invokeWithManyArguments(bootstrapMethod, caller, name, type, argv);
maybeReBoxElements(argv);
if (type instanceof Class<?> c) {
result = switch (argv.length) {
case 0 -> bootstrapMethod.invoke(caller, name, c);
case 1 -> bootstrapMethod.invoke(caller, name, c, argv[0]);
case 2 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1]);
case 3 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1], argv[2]);
case 4 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1], argv[2], argv[3]);
case 5 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1], argv[2], argv[3], argv[4]);
case 6 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
default -> invokeWithManyArguments(bootstrapMethod, caller, name, type, argv);
};
} else {
MethodType mt = (MethodType) type;
result = switch (argv.length) {
case 0 -> bootstrapMethod.invoke(caller, name, mt);
case 1 -> bootstrapMethod.invoke(caller, name, mt, argv[0]);
case 2 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1]);
case 3 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1], argv[2]);
case 4 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1], argv[2], argv[3]);
case 5 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1], argv[2], argv[3], argv[4]);
case 6 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
default -> invokeWithManyArguments(bootstrapMethod, caller, name, type, argv);
};
}
}
}
@ -218,76 +221,6 @@ final class BootstrapMethodInvoker {
return wrapperType.cast(result);
}
// If we don't provide static type information for type, we'll generate runtime
// checks. Let's try not to...
private static Object invoke(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type);
}
}
private static Object invoke(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type, Object arg0) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0);
}
}
private static Object invoke(MethodHandle bootstrapMethod, Lookup caller, String name,
Object type, Object arg0, Object arg1) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1);
}
}
private static Object invoke(MethodHandle bootstrapMethod, Lookup caller, String name,
Object type, Object arg0, Object arg1,
Object arg2) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1, arg2);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1, arg2);
}
}
private static Object invoke(MethodHandle bootstrapMethod, Lookup caller, String name,
Object type, Object arg0, Object arg1,
Object arg2, Object arg3) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1, arg2, arg3);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1, arg2, arg3);
}
}
private static Object invoke(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type, Object arg0, Object arg1,
Object arg2, Object arg3, Object arg4) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1, arg2, arg3, arg4);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1, arg2, arg3, arg4);
}
}
private static Object invoke(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type, Object arg0, Object arg1,
Object arg2, Object arg3, Object arg4, Object arg5) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1, arg2, arg3, arg4, arg5);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1, arg2, arg3, arg4, arg5);
}
}
private static Object invokeWithManyArguments(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type, Object[] argv) throws Throwable {
final int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type)

View file

@ -84,6 +84,7 @@ class InvokerBytecodeGenerator {
static final String INVOKER_SUPER_NAME = OBJ;
/** Name of new class */
private final String name;
private final String className;
private final LambdaForm lambdaForm;
@ -117,16 +118,17 @@ class InvokerBytecodeGenerator {
/** Main constructor; other constructors delegate to this one. */
private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize,
String className, String invokerName, MethodType invokerType) {
String name, String invokerName, MethodType invokerType) {
int p = invokerName.indexOf('.');
if (p > -1) {
className = invokerName.substring(0, p);
name = invokerName.substring(0, p);
invokerName = invokerName.substring(p + 1);
}
if (DUMP_CLASS_FILES) {
className = makeDumpableClassName(className);
name = makeDumpableClassName(name);
}
this.className = className;
this.name = name;
this.className = CLASS_PREFIX + name;
this.lambdaForm = lambdaForm;
this.invokerName = invokerName;
this.invokerType = invokerType;
@ -135,9 +137,9 @@ class InvokerBytecodeGenerator {
}
/** For generating LambdaForm interpreter entry points. */
private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) {
private InvokerBytecodeGenerator(String name, String invokerName, MethodType invokerType) {
this(null, invokerType.parameterCount(),
className, invokerName, invokerType);
name, invokerName, invokerType);
MethodType mt = invokerType.erase();
// Create an array to map name indexes to locals indexes.
localsMap[0] = 0; // localsMap has at least one element
@ -149,15 +151,15 @@ class InvokerBytecodeGenerator {
}
/** For generating customized code for a single LambdaForm. */
private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
this(className, form.lambdaName(), form, invokerType);
private InvokerBytecodeGenerator(String name, LambdaForm form, MethodType invokerType) {
this(name, form.lambdaName(), form, invokerType);
}
/** For generating customized code for a single LambdaForm. */
InvokerBytecodeGenerator(String className, String invokerName,
InvokerBytecodeGenerator(String name, String invokerName,
LambdaForm form, MethodType invokerType) {
this(form, form.names.length,
className, invokerName, invokerType);
name, invokerName, invokerType);
// Create an array to map name indexes to locals indexes.
Name[] names = form.names;
for (int i = 0, index = 0; i < localsMap.length; i++) {
@ -195,7 +197,7 @@ class InvokerBytecodeGenerator {
private void maybeDump(final byte[] classFile) {
if (DUMP_CLASS_FILES) {
maybeDump(CLASS_PREFIX + className, classFile);
maybeDump(className, classFile);
}
}
@ -231,7 +233,7 @@ class InvokerBytecodeGenerator {
}
String sfx = ctr.toString();
while (sfx.length() < 3)
sfx = "0"+sfx;
sfx = "0" + sfx;
className += sfx;
return className;
}
@ -265,23 +267,38 @@ class InvokerBytecodeGenerator {
desc = "Ljava/lang/Object;";
}
Class<?> c = arg.getClass();
while (c.isArray()) {
c = c.getComponentType();
}
// unique static variable name
String name = "_DATA_" + c.getSimpleName() + "_" + classData.size();
String name;
if (DUMP_CLASS_FILES) {
Class<?> c = arg.getClass();
while (c.isArray()) {
c = c.getComponentType();
}
name = "_DATA_" + c.getSimpleName() + "_" + classData.size();
} else {
name = "_D_" + classData.size();
}
ClassData cd = new ClassData(name, desc, arg);
classData.add(cd);
return cd.name();
return name;
}
List<Object> classDataValues() {
Object[] data = new Object[classData.size()];
for (int i = 0; i < classData.size(); i++) {
data[i] = classData.get(i).value;
}
return List.of(data);
final List<ClassData> cd = classData;
return switch(cd.size()) {
case 0 -> List.of();
case 1 -> List.of(cd.get(0).value);
case 2 -> List.of(cd.get(0).value, cd.get(1).value);
case 3 -> List.of(cd.get(0).value, cd.get(1).value, cd.get(2).value);
case 4 -> List.of(cd.get(0).value, cd.get(1).value, cd.get(2).value, cd.get(3).value);
default -> {
Object[] data = new Object[classData.size()];
for (int i = 0; i < classData.size(); i++) {
data[i] = classData.get(i).value;
}
yield List.of(data);
}
};
}
private static String debugString(Object arg) {
@ -295,26 +312,11 @@ class InvokerBytecodeGenerator {
return arg.toString();
}
/**
* Extract the number of constant pool entries from a given class file.
*
* @param classFile the bytes of the class file in question.
* @return the number of entries in the constant pool.
*/
private static int getConstantPoolSize(byte[] classFile) {
// The first few bytes:
// u4 magic;
// u2 minor_version;
// u2 major_version;
// u2 constant_pool_count;
return ((classFile[8] & 0xFF) << 8) | (classFile[9] & 0xFF);
}
/**
* Extract the MemberName of a newly-defined method.
*/
private MemberName loadMethod(byte[] classFile) {
Class<?> invokerClass = LOOKUP.makeHiddenClassDefiner(className(), classFile)
Class<?> invokerClass = LOOKUP.makeHiddenClassDefiner(className, classFile)
.defineClass(true, classDataValues());
return resolveInvokerMember(invokerClass, invokerName, invokerType);
}
@ -339,8 +341,8 @@ class InvokerBytecodeGenerator {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
setClassWriter(cw);
cw.visit(Opcodes.V1_8, NOT_ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
CLASS_PREFIX + className, null, INVOKER_SUPER_NAME, null);
cw.visitSource(SOURCE_PREFIX + className, null);
className, null, INVOKER_SUPER_NAME, null);
cw.visitSource(SOURCE_PREFIX + name, null);
return cw;
}
@ -357,14 +359,6 @@ class InvokerBytecodeGenerator {
mv.visitEnd();
}
private String className() {
return CLASS_PREFIX + className;
}
private void clinit() {
clinit(cw, className(), classData);
}
/*
* <clinit> to initialize the static final fields with the live class data
* LambdaForms can't use condy due to bootstrapping issue.
@ -647,7 +641,7 @@ class InvokerBytecodeGenerator {
String sig = getInternalName(cls);
mv.visitTypeInsn(Opcodes.CHECKCAST, sig);
} else {
mv.visitFieldInsn(Opcodes.GETSTATIC, className(), classData(cls), "Ljava/lang/Class;");
mv.visitFieldInsn(Opcodes.GETSTATIC, className, classData(cls), "Ljava/lang/Class;");
mv.visitInsn(Opcodes.SWAP);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CLS, "cast", LL_SIG, false);
if (Object[].class.isAssignableFrom(cls))
@ -665,17 +659,15 @@ class InvokerBytecodeGenerator {
* Emits an actual return instruction conforming to the given return type.
*/
private void emitReturnInsn(BasicType type) {
int opcode;
switch (type) {
case I_TYPE: opcode = Opcodes.IRETURN; break;
case J_TYPE: opcode = Opcodes.LRETURN; break;
case F_TYPE: opcode = Opcodes.FRETURN; break;
case D_TYPE: opcode = Opcodes.DRETURN; break;
case L_TYPE: opcode = Opcodes.ARETURN; break;
case V_TYPE: opcode = Opcodes.RETURN; break;
default:
throw new InternalError("unknown return type: " + type);
}
int opcode = switch (type) {
case I_TYPE -> Opcodes.IRETURN;
case J_TYPE -> Opcodes.LRETURN;
case F_TYPE -> Opcodes.FRETURN;
case D_TYPE -> Opcodes.DRETURN;
case L_TYPE -> Opcodes.ARETURN;
case V_TYPE -> Opcodes.RETURN;
default -> throw new InternalError("unknown return type: " + type);
};
mv.visitInsn(opcode);
}
@ -722,7 +714,7 @@ class InvokerBytecodeGenerator {
case LINK_TO_CALL_SITE: // fall-through
case LINK_TO_TARGET_METHOD: // fall-through
case GENERIC_INVOKER: // fall-through
case GENERIC_LINKER: return resolveFrom(name, invokerType.basicType(), Invokers.Holder.class);
case GENERIC_LINKER: return resolveFrom(name, invokerType, Invokers.Holder.class);
case GET_REFERENCE: // fall-through
case GET_BOOLEAN: // fall-through
case GET_BYTE: // fall-through
@ -803,7 +795,7 @@ class InvokerBytecodeGenerator {
private byte[] generateCustomizedCodeBytes() {
classFilePrologue();
addMethod();
clinit();
clinit(cw, className, classData);
bogusMethod(lambdaForm);
final byte[] classFile = toByteArray();
@ -838,7 +830,7 @@ class InvokerBytecodeGenerator {
// receiver MethodHandle (at slot #0) with an embedded constant and use it instead.
// It enables more efficient code generation in some situations, since embedded constants
// are compile-time constants for JIT compiler.
mv.visitFieldInsn(Opcodes.GETSTATIC, className(), classData(lambdaForm.customized), MH_SIG);
mv.visitFieldInsn(Opcodes.GETSTATIC, className, classData(lambdaForm.customized), MH_SIG);
mv.visitTypeInsn(Opcodes.CHECKCAST, MH);
assert(checkActualReceiver()); // expects MethodHandle on top of the stack
mv.visitVarInsn(Opcodes.ASTORE, localsMap[0]);
@ -971,7 +963,7 @@ class InvokerBytecodeGenerator {
// push receiver
MethodHandle target = name.function.resolvedHandle();
assert(target != null) : name.exprString();
mv.visitFieldInsn(Opcodes.GETSTATIC, className(), classData(target), MH_SIG);
mv.visitFieldInsn(Opcodes.GETSTATIC, className, classData(target), MH_SIG);
emitReferenceCast(MethodHandle.class, target);
} else {
// load receiver
@ -990,7 +982,7 @@ class InvokerBytecodeGenerator {
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false);
}
private static Class<?>[] STATICALLY_INVOCABLE_PACKAGES = {
private static final Class<?>[] STATICALLY_INVOCABLE_PACKAGES = {
// Sample classes from each package we are willing to bind to statically:
java.lang.Object.class,
java.util.Arrays.class,
@ -1134,7 +1126,7 @@ class InvokerBytecodeGenerator {
}
assert(java.lang.reflect.Array.getLength(emptyArray) == 0);
assert(emptyArray.getClass() == rtype); // exact typing
mv.visitFieldInsn(Opcodes.GETSTATIC, className(), classData(emptyArray), "Ljava/lang/Object;");
mv.visitFieldInsn(Opcodes.GETSTATIC, className, classData(emptyArray), "Ljava/lang/Object;");
emitReferenceCast(rtype, emptyArray);
return;
}
@ -1691,13 +1683,15 @@ class InvokerBytecodeGenerator {
Name n = (Name) arg;
emitLoadInsn(n.type, n.index());
emitImplicitConversion(n.type, ptype, n);
} else if ((arg == null || arg instanceof String) && bptype == L_TYPE) {
emitConst(arg);
} else if (arg == null && bptype == L_TYPE) {
mv.visitInsn(Opcodes.ACONST_NULL);
} else if (arg instanceof String && bptype == L_TYPE) {
mv.visitLdcInsn(arg);
} else {
if (Wrapper.isWrapperType(arg.getClass()) && bptype != L_TYPE) {
emitConst(arg);
} else {
mv.visitFieldInsn(Opcodes.GETSTATIC, className(), classData(arg), "Ljava/lang/Object;");
mv.visitFieldInsn(Opcodes.GETSTATIC, className, classData(arg), "Ljava/lang/Object;");
emitImplicitConversion(L_TYPE, ptype, arg);
}
}
@ -1828,10 +1822,10 @@ class InvokerBytecodeGenerator {
private void emitX2I(Wrapper type) {
switch (type) {
case LONG: mv.visitInsn(Opcodes.L2I); break;
case FLOAT: mv.visitInsn(Opcodes.F2I); break;
case DOUBLE: mv.visitInsn(Opcodes.D2I); break;
default: throw new InternalError("unknown type: " + type);
case LONG -> mv.visitInsn(Opcodes.L2I);
case FLOAT -> mv.visitInsn(Opcodes.F2I);
case DOUBLE -> mv.visitInsn(Opcodes.D2I);
default -> throw new InternalError("unknown type: " + type);
}
}
@ -1889,7 +1883,7 @@ class InvokerBytecodeGenerator {
emitReturnInsn(basicType(rtype));
methodEpilogue();
clinit();
clinit(cw, className, classData);
bogusMethod(invokerType);
final byte[] classFile = cw.toByteArray();
@ -1958,7 +1952,7 @@ class InvokerBytecodeGenerator {
emitReturnInsn(L_TYPE); // NOTE: NamedFunction invokers always return a reference value.
methodEpilogue();
clinit();
clinit(cw, className, classData);
bogusMethod(dstType);
final byte[] classFile = cw.toByteArray();

View file

@ -212,26 +212,6 @@ class LambdaForm {
if (!type.isPrimitive()) return L_TYPE;
return basicType(Wrapper.forPrimitiveType(type));
}
static BasicType[] basicTypes(String types) {
BasicType[] btypes = new BasicType[types.length()];
for (int i = 0; i < btypes.length; i++) {
btypes[i] = basicType(types.charAt(i));
}
return btypes;
}
static String basicTypeDesc(BasicType[] types) {
if (types == null) {
return null;
}
if (types.length == 0) {
return "";
}
StringBuilder sb = new StringBuilder();
for (BasicType bt : types) {
sb.append(bt.basicTypeChar());
}
return sb.toString();
}
static int[] basicTypeOrds(BasicType[] types) {
if (types == null) {
return null;
@ -388,18 +368,9 @@ class LambdaForm {
LambdaForm(int arity, Name[] names, Kind kind) {
this(arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, kind);
}
LambdaForm(int arity, Name[] names, boolean forceInline) {
this(arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC);
}
LambdaForm(int arity, Name[] names, boolean forceInline, Kind kind) {
this(arity, names, LAST_RESULT, forceInline, /*customized=*/null, kind);
}
LambdaForm(Name[] formals, Name[] temps, Name result) {
this(formals.length, buildNames(formals, temps, result), LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
}
LambdaForm(Name[] formals, Name[] temps, Name result, boolean forceInline) {
this(formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline, /*customized=*/null);
}
private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
int arity = formals.length;
@ -629,9 +600,8 @@ class LambdaForm {
/** Report the N-th argument name. */
Name parameter(int n) {
assert(n < arity);
Name param = names[n];
assert(param.isParam());
assert(n < arity && param.isParam());
return param;
}
@ -670,9 +640,6 @@ class LambdaForm {
assert(isValidSignature(sig));
return sig.indexOf('_');
}
static BasicType signatureReturn(String sig) {
return basicType(sig.charAt(signatureArity(sig) + 1));
}
static boolean isValidSignature(String sig) {
int arity = sig.indexOf('_');
if (arity < 0) return false; // must be of the form *_*
@ -687,16 +654,6 @@ class LambdaForm {
}
return true; // [LIJFD]*_[LIJFDV]
}
static MethodType signatureType(String sig) {
Class<?>[] ptypes = new Class<?>[signatureArity(sig)];
for (int i = 0; i < ptypes.length; i++)
ptypes[i] = basicType(sig.charAt(i)).btClass;
Class<?> rtype = signatureReturn(sig).btClass;
return MethodType.makeImpl(rtype, ptypes, true);
}
static MethodType basicMethodType(MethodType mt) {
return signatureType(basicTypeSignature(mt));
}
/**
* Check if i-th name is a call to MethodHandleImpl.selectAlternative.
@ -1327,7 +1284,7 @@ class LambdaForm {
if (c1 != NO_CHAR && !('A' <= c1 && c1 <= 'Z')) {
// wrong kind of char; bail out here
if (buf != null) {
buf.append(signature.substring(i - c1reps, len));
buf.append(signature, i - c1reps, len);
}
break;
}
@ -1410,11 +1367,6 @@ class LambdaForm {
return type.btChar;
}
void resolve() {
if (function != null)
function.resolve();
}
Name newIndex(int i) {
if (initIndex(i)) return this;
return cloneWithIndex(i);
@ -1609,10 +1561,6 @@ class LambdaForm {
return count;
}
boolean contains(Name n) {
return this == n || lastUseIndex(n) >= 0;
}
public boolean equals(Name that) {
if (this == that) return true;
if (isParam())

View file

@ -199,19 +199,13 @@ class MethodType
/*non-public*/
static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1; // deduct one more for invoker
private static void checkRtype(Class<?> rtype) {
Objects.requireNonNull(rtype);
}
private static void checkPtype(Class<?> ptype) {
Objects.requireNonNull(ptype);
if (ptype == void.class)
throw newIllegalArgumentException("parameter type cannot be void");
}
/** Return number of extra slots (count of long/double args). */
private static int checkPtypes(Class<?>[] ptypes) {
int slots = 0;
for (Class<?> ptype : ptypes) {
checkPtype(ptype);
Objects.requireNonNull(ptype);
if (ptype == void.class)
throw newIllegalArgumentException("parameter type cannot be void");
if (ptype == double.class || ptype == long.class) {
slots++;
}
@ -328,10 +322,14 @@ class MethodType
}
/**
* Sole factory method to find or create an interned method type.
* Sole factory method to find or create an interned method type. Will perform
* input validation on behalf of factory methods
*
* @param rtype desired return type
* @param ptypes desired parameter types
* @param trusted whether the ptypes can be used without cloning
* @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
* @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
* @return the unique method type of the desired structure
*/
/*trusted*/
@ -345,7 +343,7 @@ class MethodType
return mt;
// promote the object to the Real Thing, and reprobe
MethodType.checkRtype(rtype);
Objects.requireNonNull(rtype);
if (trusted) {
MethodType.checkPtypes(ptypes);
mt = primordialMT;
@ -415,7 +413,6 @@ class MethodType
*/
public MethodType changeParameterType(int num, Class<?> nptype) {
if (parameterType(num) == nptype) return this;
checkPtype(nptype);
Class<?>[] nptypes = ptypes.clone();
nptypes[num] = nptype;
return makeImpl(rtype, nptypes, true);