8143131: Remove unused code from java.lang.invoke
Reviewed-by: vlivanov, jrose, mhaupt
This commit is contained in:
parent
c804d98306
commit
7010cf730d
@ -108,12 +108,6 @@ class DirectMethodHandle extends MethodHandle {
|
||||
return makeAllocator(member);
|
||||
return make(member.getDeclaringClass(), member);
|
||||
}
|
||||
static DirectMethodHandle make(Method method) {
|
||||
return make(method.getDeclaringClass(), new MemberName(method));
|
||||
}
|
||||
static DirectMethodHandle make(Field field) {
|
||||
return make(field.getDeclaringClass(), new MemberName(field));
|
||||
}
|
||||
private static DirectMethodHandle makeAllocator(MemberName ctor) {
|
||||
assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
|
||||
Class<?> instanceClass = ctor.getDeclaringClass();
|
||||
|
@ -56,7 +56,6 @@ class InvokerBytecodeGenerator {
|
||||
private static final String OBJ = "java/lang/Object";
|
||||
private static final String OBJARY = "[Ljava/lang/Object;";
|
||||
|
||||
private static final String MH_SIG = "L" + MH + ";";
|
||||
private static final String LF_SIG = "L" + LF + ";";
|
||||
private static final String LFN_SIG = "L" + LFN + ";";
|
||||
private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";";
|
||||
@ -77,7 +76,6 @@ class InvokerBytecodeGenerator {
|
||||
|
||||
/** Info about local variables in compiled lambda form */
|
||||
private final int[] localsMap; // index
|
||||
private final BasicType[] localTypes; // basic type
|
||||
private final Class<?>[] localClasses; // type
|
||||
|
||||
/** ASM bytecode generation. */
|
||||
@ -105,7 +103,6 @@ class InvokerBytecodeGenerator {
|
||||
this.invokerType = invokerType;
|
||||
this.localsMap = new int[localsMapSize+1];
|
||||
// last entry of localsMap is count of allocated local slots
|
||||
this.localTypes = new BasicType[localsMapSize+1];
|
||||
this.localClasses = new Class<?>[localsMapSize+1];
|
||||
}
|
||||
|
||||
@ -114,11 +111,8 @@ class InvokerBytecodeGenerator {
|
||||
this(null, invokerType.parameterCount(),
|
||||
className, invokerName, invokerType);
|
||||
// Create an array to map name indexes to locals indexes.
|
||||
localTypes[localTypes.length - 1] = V_TYPE;
|
||||
for (int i = 0; i < localsMap.length; i++) {
|
||||
localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i);
|
||||
if (i < invokerType.parameterCount())
|
||||
localTypes[i] = basicType(invokerType.parameterType(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +127,6 @@ class InvokerBytecodeGenerator {
|
||||
if (i < names.length) {
|
||||
BasicType type = names[i].type();
|
||||
index += type.basicTypeSlots();
|
||||
localTypes[i] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -461,31 +454,6 @@ class InvokerBytecodeGenerator {
|
||||
return xas - Opcodes.AASTORE + aaop;
|
||||
}
|
||||
|
||||
|
||||
private void freeFrameLocal(int oldFrameLocal) {
|
||||
int i = indexForFrameLocal(oldFrameLocal);
|
||||
if (i < 0) return;
|
||||
BasicType type = localTypes[i];
|
||||
int newFrameLocal = makeLocalTemp(type);
|
||||
mv.visitVarInsn(loadInsnOpcode(type), oldFrameLocal);
|
||||
mv.visitVarInsn(storeInsnOpcode(type), newFrameLocal);
|
||||
assert(localsMap[i] == oldFrameLocal);
|
||||
localsMap[i] = newFrameLocal;
|
||||
assert(indexForFrameLocal(oldFrameLocal) < 0);
|
||||
}
|
||||
private int indexForFrameLocal(int frameLocal) {
|
||||
for (int i = 0; i < localsMap.length; i++) {
|
||||
if (localsMap[i] == frameLocal && localTypes[i] != V_TYPE)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private int makeLocalTemp(BasicType type) {
|
||||
int frameLocal = localsMap[localsMap.length - 1];
|
||||
localsMap[localsMap.length - 1] = frameLocal + type.basicTypeSlots();
|
||||
return frameLocal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a boxing call.
|
||||
*
|
||||
|
@ -197,17 +197,6 @@ class LambdaForm {
|
||||
if (!type.isPrimitive()) return L_TYPE;
|
||||
return basicType(Wrapper.forPrimitiveType(type));
|
||||
}
|
||||
|
||||
static char basicTypeChar(Class<?> type) {
|
||||
return basicType(type).btChar;
|
||||
}
|
||||
static BasicType[] basicTypes(List<Class<?>> types) {
|
||||
BasicType[] btypes = new BasicType[types.size()];
|
||||
for (int i = 0; i < btypes.length; i++) {
|
||||
btypes[i] = basicType(types.get(i));
|
||||
}
|
||||
return btypes;
|
||||
}
|
||||
static BasicType[] basicTypes(String types) {
|
||||
BasicType[] btypes = new BasicType[types.length()];
|
||||
for (int i = 0; i < btypes.length; i++) {
|
||||
@ -215,13 +204,19 @@ class LambdaForm {
|
||||
}
|
||||
return btypes;
|
||||
}
|
||||
static byte[] basicTypesOrd(BasicType[] btypes) {
|
||||
byte[] ords = new byte[btypes.length];
|
||||
for (int i = 0; i < btypes.length; i++) {
|
||||
ords[i] = (byte)btypes[i].ordinal();
|
||||
|
||||
static char basicTypeChar(Class<?> type) {
|
||||
return basicType(type).btChar;
|
||||
}
|
||||
|
||||
static byte[] basicTypesOrd(Class<?>[] types) {
|
||||
byte[] ords = new byte[types.length];
|
||||
for (int i = 0; i < ords.length; i++) {
|
||||
ords[i] = (byte)basicType(types[i]).ordinal();
|
||||
}
|
||||
return ords;
|
||||
}
|
||||
|
||||
static boolean isBasicTypeChar(char c) {
|
||||
return "LIJFDV".indexOf(c) >= 0;
|
||||
}
|
||||
@ -929,99 +924,6 @@ class LambdaForm {
|
||||
return false;
|
||||
}
|
||||
|
||||
LambdaForm addArguments(int pos, BasicType... types) {
|
||||
// names array has MH in slot 0; skip it.
|
||||
int argpos = pos + 1;
|
||||
assert(argpos <= arity);
|
||||
int length = names.length;
|
||||
int inTypes = types.length;
|
||||
Name[] names2 = Arrays.copyOf(names, length + inTypes);
|
||||
int arity2 = arity + inTypes;
|
||||
int result2 = result;
|
||||
if (result2 >= argpos)
|
||||
result2 += inTypes;
|
||||
// Note: The LF constructor will rename names2[argpos...].
|
||||
// Make space for new arguments (shift temporaries).
|
||||
System.arraycopy(names, argpos, names2, argpos + inTypes, length - argpos);
|
||||
for (int i = 0; i < inTypes; i++) {
|
||||
names2[argpos + i] = new Name(types[i]);
|
||||
}
|
||||
return new LambdaForm(debugName, arity2, names2, result2);
|
||||
}
|
||||
|
||||
LambdaForm addArguments(int pos, List<Class<?>> types) {
|
||||
return addArguments(pos, basicTypes(types));
|
||||
}
|
||||
|
||||
LambdaForm permuteArguments(int skip, int[] reorder, BasicType[] types) {
|
||||
// Note: When inArg = reorder[outArg], outArg is fed by a copy of inArg.
|
||||
// The types are the types of the new (incoming) arguments.
|
||||
int length = names.length;
|
||||
int inTypes = types.length;
|
||||
int outArgs = reorder.length;
|
||||
assert(skip+outArgs == arity);
|
||||
assert(permutedTypesMatch(reorder, types, names, skip));
|
||||
int pos = 0;
|
||||
// skip trivial first part of reordering:
|
||||
while (pos < outArgs && reorder[pos] == pos) pos += 1;
|
||||
Name[] names2 = new Name[length - outArgs + inTypes];
|
||||
System.arraycopy(names, 0, names2, 0, skip+pos);
|
||||
// copy the body:
|
||||
int bodyLength = length - arity;
|
||||
System.arraycopy(names, skip+outArgs, names2, skip+inTypes, bodyLength);
|
||||
int arity2 = names2.length - bodyLength;
|
||||
int result2 = result;
|
||||
if (result2 >= 0) {
|
||||
if (result2 < skip+outArgs) {
|
||||
// return the corresponding inArg
|
||||
result2 = reorder[result2-skip];
|
||||
} else {
|
||||
result2 = result2 - outArgs + inTypes;
|
||||
}
|
||||
}
|
||||
// rework names in the body:
|
||||
for (int j = pos; j < outArgs; j++) {
|
||||
Name n = names[skip+j];
|
||||
int i = reorder[j];
|
||||
// replace names[skip+j] by names2[skip+i]
|
||||
Name n2 = names2[skip+i];
|
||||
if (n2 == null)
|
||||
names2[skip+i] = n2 = new Name(types[i]);
|
||||
else
|
||||
assert(n2.type == types[i]);
|
||||
for (int k = arity2; k < names2.length; k++) {
|
||||
names2[k] = names2[k].replaceName(n, n2);
|
||||
}
|
||||
}
|
||||
// some names are unused, but must be filled in
|
||||
for (int i = skip+pos; i < arity2; i++) {
|
||||
if (names2[i] == null)
|
||||
names2[i] = argument(i, types[i - skip]);
|
||||
}
|
||||
for (int j = arity; j < names.length; j++) {
|
||||
int i = j - arity + arity2;
|
||||
// replace names2[i] by names[j]
|
||||
Name n = names[j];
|
||||
Name n2 = names2[i];
|
||||
if (n != n2) {
|
||||
for (int k = i+1; k < names2.length; k++) {
|
||||
names2[k] = names2[k].replaceName(n, n2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new LambdaForm(debugName, arity2, names2, result2);
|
||||
}
|
||||
|
||||
static boolean permutedTypesMatch(int[] reorder, BasicType[] types, Name[] names, int skip) {
|
||||
int inTypes = types.length;
|
||||
int outArgs = reorder.length;
|
||||
for (int i = 0; i < outArgs; i++) {
|
||||
assert(names[skip+i].isParam());
|
||||
assert(names[skip+i].type == types[reorder[i]]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static class NamedFunction {
|
||||
final MemberName member;
|
||||
private @Stable MethodHandle resolvedHandle;
|
||||
@ -1054,19 +956,15 @@ class LambdaForm {
|
||||
"invokeBasic".equals(member.getName());
|
||||
}
|
||||
|
||||
// The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc.
|
||||
// The next 2 constructors are used to break circular dependencies on MH.invokeStatic, etc.
|
||||
// Any LambdaForm containing such a member is not interpretable.
|
||||
// This is OK, since all such LFs are prepared with special primitive vmentry points.
|
||||
// And even without the resolvedHandle, the name can still be compiled and optimized.
|
||||
NamedFunction(Method method) {
|
||||
this(new MemberName(method));
|
||||
}
|
||||
NamedFunction(Field field) {
|
||||
this(new MemberName(field));
|
||||
}
|
||||
NamedFunction(MemberName member) {
|
||||
this.member = member;
|
||||
this.resolvedHandle = null;
|
||||
this(member, null);
|
||||
}
|
||||
|
||||
MethodHandle resolvedHandle() {
|
||||
@ -1408,9 +1306,7 @@ class LambdaForm {
|
||||
}
|
||||
Name(NamedFunction function, Object... arguments) {
|
||||
this(-1, function.returnType(), function, arguments = Arrays.copyOf(arguments, arguments.length, Object[].class));
|
||||
assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
|
||||
for (int i = 0; i < arguments.length; i++)
|
||||
assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
|
||||
assert(typesMatch(function, arguments));
|
||||
}
|
||||
/** Create a raw parameter of the given type, with an expected index. */
|
||||
Name(int index, BasicType type) {
|
||||
@ -1550,7 +1446,15 @@ class LambdaForm {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
static boolean typesMatch(BasicType parameterType, Object object) {
|
||||
private boolean typesMatch(NamedFunction function, Object ... arguments) {
|
||||
assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
assert (typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean typesMatch(BasicType parameterType, Object object) {
|
||||
if (object instanceof Name) {
|
||||
return ((Name)object).type == parameterType;
|
||||
}
|
||||
@ -1630,7 +1534,7 @@ class LambdaForm {
|
||||
|
||||
/** Return the number of times n is used as an argument or return value. */
|
||||
int useCount(Name n) {
|
||||
int ni = n.index, nmax = names.length;
|
||||
int nmax = names.length;
|
||||
int end = lastUseIndex(n);
|
||||
if (end < 0) return 0;
|
||||
int count = 0;
|
||||
@ -1643,9 +1547,6 @@ class LambdaForm {
|
||||
return count;
|
||||
}
|
||||
|
||||
static Name argument(int which, char type) {
|
||||
return argument(which, basicType(type));
|
||||
}
|
||||
static Name argument(int which, BasicType type) {
|
||||
if (which >= INTERNED_ARGUMENT_LIMIT)
|
||||
return new Name(which, type);
|
||||
@ -1661,28 +1562,7 @@ class LambdaForm {
|
||||
int length = types.length();
|
||||
Name[] names = new Name[length + extra];
|
||||
for (int i = 0; i < length; i++)
|
||||
names[i] = argument(i, types.charAt(i));
|
||||
return names;
|
||||
}
|
||||
static Name[] arguments(int extra, char... types) {
|
||||
int length = types.length;
|
||||
Name[] names = new Name[length + extra];
|
||||
for (int i = 0; i < length; i++)
|
||||
names[i] = argument(i, types[i]);
|
||||
return names;
|
||||
}
|
||||
static Name[] arguments(int extra, List<Class<?>> types) {
|
||||
int length = types.size();
|
||||
Name[] names = new Name[length + extra];
|
||||
for (int i = 0; i < length; i++)
|
||||
names[i] = argument(i, basicType(types.get(i)));
|
||||
return names;
|
||||
}
|
||||
static Name[] arguments(int extra, Class<?>... types) {
|
||||
int length = types.length;
|
||||
Name[] names = new Name[length + extra];
|
||||
for (int i = 0; i < length; i++)
|
||||
names[i] = argument(i, basicType(types[i]));
|
||||
names[i] = argument(i, basicType(types.charAt(i)));
|
||||
return names;
|
||||
}
|
||||
static Name[] arguments(int extra, MethodType types) {
|
||||
|
@ -565,12 +565,12 @@ class LambdaFormEditor {
|
||||
if (collectorArity == 1 && !dropResult) {
|
||||
return filterArgumentForm(pos, basicType(collectorType.parameterType(0)));
|
||||
}
|
||||
BasicType[] newTypes = BasicType.basicTypes(collectorType.parameterList());
|
||||
byte[] newTypes = BasicType.basicTypesOrd(collectorType.parameterArray());
|
||||
Transform.Kind kind = (dropResult
|
||||
? Transform.Kind.COLLECT_ARGS_TO_VOID
|
||||
: Transform.Kind.COLLECT_ARGS);
|
||||
if (dropResult && collectorArity == 0) pos = 1; // pure side effect
|
||||
Transform key = Transform.of(kind, pos, collectorArity, BasicType.basicTypesOrd(newTypes));
|
||||
Transform key = Transform.of(kind, pos, collectorArity, newTypes);
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
assert(form.arity == lambdaForm.arity - (dropResult ? 0 : 1) + collectorArity);
|
||||
@ -680,9 +680,8 @@ class LambdaFormEditor {
|
||||
combinerArgs, 1, combinerArity);
|
||||
} else {
|
||||
newParams = new Name[combinerArity];
|
||||
BasicType[] newTypes = basicTypes(combinerType.parameterList());
|
||||
for (int i = 0; i < newTypes.length; i++) {
|
||||
newParams[i] = new Name(pos + i, newTypes[i]);
|
||||
for (int i = 0; i < newParams.length; i++) {
|
||||
newParams[i] = new Name(pos + i, basicType(combinerType.parameterType(i)));
|
||||
}
|
||||
System.arraycopy(newParams, 0,
|
||||
combinerArgs, 1, combinerArity);
|
||||
|
@ -92,33 +92,6 @@ import jdk.internal.misc.Unsafe;
|
||||
TRACE_METHOD_LINKAGE);
|
||||
}
|
||||
|
||||
/*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
|
||||
if (type == null)
|
||||
type = target.type();
|
||||
MemberName name = null;
|
||||
if (target != null)
|
||||
name = target.internalMemberName();
|
||||
if (name == null)
|
||||
return "invoke" + type;
|
||||
return name.getName() + type;
|
||||
}
|
||||
|
||||
/*non-public*/ static String getNameString(MethodHandle target, MethodHandle typeHolder) {
|
||||
return getNameString(target, typeHolder == null ? (MethodType) null : typeHolder.type());
|
||||
}
|
||||
|
||||
/*non-public*/ static String getNameString(MethodHandle target) {
|
||||
return getNameString(target, (MethodType) null);
|
||||
}
|
||||
|
||||
/*non-public*/ static String addTypeString(Object obj, MethodHandle target) {
|
||||
String str = String.valueOf(obj);
|
||||
if (target == null) return str;
|
||||
int paren = str.indexOf('(');
|
||||
if (paren >= 0) str = str.substring(0, paren);
|
||||
return str + target.type();
|
||||
}
|
||||
|
||||
// handy shared exception makers (they simplify the common case code)
|
||||
/*non-public*/ static InternalError newInternalError(String message) {
|
||||
return new InternalError(message);
|
||||
@ -150,9 +123,6 @@ import jdk.internal.misc.Unsafe;
|
||||
if (ex instanceof RuntimeException) throw (RuntimeException) ex;
|
||||
throw newInternalError("uncaught exception", ex);
|
||||
}
|
||||
static Error NYI() {
|
||||
throw new AssertionError("NYI");
|
||||
}
|
||||
private static String message(String message, Object obj) {
|
||||
if (obj != null) message = message + ": " + obj;
|
||||
return message;
|
||||
|
@ -179,9 +179,11 @@ class MethodType implements java.io.Serializable {
|
||||
checkSlotCount(ptypes.length + slots);
|
||||
return slots;
|
||||
}
|
||||
static void checkSlotCount(int count) {
|
||||
assert((MAX_JVM_ARITY & (MAX_JVM_ARITY+1)) == 0);
|
||||
static {
|
||||
// MAX_JVM_ARITY must be power of 2 minus 1 for following code trick to work:
|
||||
assert((MAX_JVM_ARITY & (MAX_JVM_ARITY+1)) == 0);
|
||||
}
|
||||
static void checkSlotCount(int count) {
|
||||
if ((count & MAX_JVM_ARITY) != count)
|
||||
throw newIllegalArgumentException("bad parameter count "+count);
|
||||
}
|
||||
@ -813,11 +815,6 @@ class MethodType implements java.io.Serializable {
|
||||
boolean isViewableAs(MethodType newType, boolean keepInterfaces) {
|
||||
if (!VerifyType.isNullConversion(returnType(), newType.returnType(), keepInterfaces))
|
||||
return false;
|
||||
return parametersAreViewableAs(newType, keepInterfaces);
|
||||
}
|
||||
/** True if the new parameters can be viewed (w/o casting) under the old parameter types. */
|
||||
/*non-public*/
|
||||
boolean parametersAreViewableAs(MethodType newType, boolean keepInterfaces) {
|
||||
if (form == newType.form && form.erasedType == this)
|
||||
return true; // my reference parameters are all Object
|
||||
if (ptypes == newType.ptypes)
|
||||
@ -1088,7 +1085,6 @@ class MethodType implements java.io.Serializable {
|
||||
throw newIllegalArgumentException("not a method descriptor: "+descriptor);
|
||||
List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
|
||||
Class<?> rtype = types.remove(types.size() - 1);
|
||||
checkSlotCount(types.size());
|
||||
Class<?>[] ptypes = listToArray(types);
|
||||
return makeImpl(rtype, ptypes, true);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class TypeConvertingMethodAdapter extends MethodVisitor {
|
||||
private static final Wrapper[] FROM_WRAPPER_NAME = new Wrapper[16];
|
||||
|
||||
// Table of wrappers for primitives, indexed by ASM type sorts
|
||||
private static final Wrapper[] FROM_TYPE_SORT = new Wrapper[16];
|
||||
private static final Wrapper[] FROM_TYPE_SORT = new Wrapper[12];
|
||||
|
||||
static {
|
||||
for (Wrapper w : Wrapper.values()) {
|
||||
@ -63,11 +63,8 @@ class TypeConvertingMethodAdapter extends MethodVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_WRAPPERS; i++) {
|
||||
for (int j = 0; j < NUM_WRAPPERS; j++) {
|
||||
wideningOpcodes[i][j] = Opcodes.NOP;
|
||||
}
|
||||
}
|
||||
// wideningOpcodes[][] will be NOP-initialized by default
|
||||
assert(Opcodes.NOP == 0);
|
||||
|
||||
initWidening(LONG, Opcodes.I2L, BYTE, SHORT, INT, CHAR);
|
||||
initWidening(LONG, Opcodes.F2L, FLOAT);
|
||||
@ -192,10 +189,6 @@ class TypeConvertingMethodAdapter extends MethodVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPrimitive(Wrapper w) {
|
||||
return w != OBJECT;
|
||||
}
|
||||
|
||||
private Wrapper toWrapper(String desc) {
|
||||
char first = desc.charAt(0);
|
||||
if (first == '[' || first == '(') {
|
||||
|
@ -113,7 +113,7 @@ public class BytecodeDescriptor {
|
||||
}
|
||||
|
||||
public static String unparse(MethodType type) {
|
||||
return unparseMethod(type.returnType(), type.parameterList());
|
||||
return unparseMethod(type.returnType(), type.parameterArray());
|
||||
}
|
||||
|
||||
public static String unparse(Object type) {
|
||||
@ -134,6 +134,16 @@ public class BytecodeDescriptor {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String unparseMethod(Class<?> rtype, Class<?>[] ptypes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
for (Class<?> pt : ptypes)
|
||||
unparseSig(pt, sb);
|
||||
sb.append(')');
|
||||
unparseSig(rtype, sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void unparseSig(Class<?> t, StringBuilder sb) {
|
||||
char c = Wrapper.forBasicType(t).basicTypeChar();
|
||||
if (c != 'L') {
|
||||
|
Loading…
Reference in New Issue
Block a user