8143131: Remove unused code from java.lang.invoke

Reviewed-by: vlivanov, jrose, mhaupt
This commit is contained in:
Claes Redestad 2015-12-02 12:28:24 +01:00
parent c804d98306
commit 7010cf730d
8 changed files with 46 additions and 236 deletions

View File

@ -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();

View File

@ -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.
*

View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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 == '(') {

View File

@ -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') {