8230662: Remove dead code from MethodTypeForm

Reviewed-by: vlivanov, mchung
This commit is contained in:
Claes Redestad 2019-09-07 15:44:04 +02:00
parent 9c3ff105df
commit c788d9841c
3 changed files with 31 additions and 163 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -123,9 +123,13 @@ class InvokerBytecodeGenerator {
private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) { private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) {
this(null, invokerType.parameterCount(), this(null, invokerType.parameterCount(),
className, invokerName, invokerType); className, invokerName, invokerType);
MethodType mt = invokerType.erase();
// Create an array to map name indexes to locals indexes. // Create an array to map name indexes to locals indexes.
for (int i = 0; i < localsMap.length; i++) { localsMap[0] = 0; // localsMap has at least one element
localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i); for (int i = 1, index = 0; i < localsMap.length; i++) {
Wrapper w = Wrapper.forBasicType(mt.parameterType(i - 1));
index += w.stackSlots();
localsMap[i] = index;
} }
} }

View file

@ -926,8 +926,8 @@ class MethodType
return false; return false;
return true; return true;
} }
if ((oldForm.primitiveParameterCount() == 0 && oldForm.erasedType == this) || if ((!oldForm.hasPrimitives() && oldForm.erasedType == this) ||
(newForm.primitiveParameterCount() == 0 && newForm.erasedType == newType)) { (!newForm.hasPrimitives() && newForm.erasedType == newType)) {
// Somewhat complicated test to avoid a loop of 2 or more trips. // Somewhat complicated test to avoid a loop of 2 or more trips.
// If either type has only Object parameters, we know we can convert. // If either type has only Object parameters, we know we can convert.
assert(canConvertParameters(srcTypes, dstTypes)); assert(canConvertParameters(srcTypes, dstTypes));
@ -1073,49 +1073,6 @@ class MethodType
return inv; return inv;
} }
/** Reports the number of JVM stack slots which carry all parameters including and after
* the given position, which must be in the range of 0 to
* {@code parameterCount} inclusive. Successive parameters are
* more shallowly stacked, and parameters are indexed in the bytecodes
* according to their trailing edge. Thus, to obtain the depth
* in the outgoing call stack of parameter {@code N}, obtain
* the {@code parameterSlotDepth} of its trailing edge
* at position {@code N+1}.
* <p>
* Parameters of type {@code long} and {@code double} occupy
* two stack slots (for historical reasons) and all others occupy one.
* Therefore, the number returned is the number of arguments
* <em>including</em> and <em>after</em> the given parameter,
* <em>plus</em> the number of long or double arguments
* at or after the argument for the given parameter.
* <p>
* This method is included for the benefit of applications that must
* generate bytecodes that process method handles and invokedynamic.
* @param num an index (zero-based, inclusive) within the parameter types
* @return the index of the (shallowest) JVM stack slot transmitting the
* given parameter
* @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
*/
/*non-public*/ int parameterSlotDepth(int num) {
if (num < 0 || num > ptypes.length)
parameterType(num); // force a range check
return form.parameterToArgSlot(num-1);
}
/** Reports the number of JVM stack slots required to receive a return value
* from a method of this type.
* If the {@link #returnType() return type} is void, it will be zero,
* else if the return type is long or double, it will be two, else one.
* <p>
* This method is included for the benefit of applications that must
* generate bytecodes that process method handles and invokedynamic.
* @return the number of JVM stack slots (0, 1, or 2) for this type's return value
* Will be removed for PFD.
*/
/*non-public*/ int returnSlotCount() {
return form.returnSlotCount();
}
/** /**
* Finds or creates an instance of a method type, given the spelling of its bytecode descriptor. * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -46,9 +46,8 @@ import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
* @author John Rose * @author John Rose
*/ */
final class MethodTypeForm { final class MethodTypeForm {
final int[] argToSlotTable, slotToArgTable; final short parameterSlotCount;
final long argCounts; // packed slot & value counts final short primitiveCount;
final long primCounts; // packed prim & double counts
final MethodType erasedType; // the canonical erasure final MethodType erasedType; // the canonical erasure
final MethodType basicType; // the canonical erasure, with primitives simplified final MethodType basicType; // the canonical erasure, with primitives simplified
@ -159,23 +158,18 @@ final class MethodTypeForm {
this.erasedType = erasedType; this.erasedType = erasedType;
Class<?>[] ptypes = erasedType.ptypes(); Class<?>[] ptypes = erasedType.ptypes();
int ptypeCount = ptypes.length; int pslotCount = ptypes.length;
int pslotCount = ptypeCount; // temp. estimate
int rtypeCount = 1; // temp. estimate
int rslotCount = 1; // temp. estimate
int[] argToSlotTab = null, slotToArgTab = null;
// Walk the argument types, looking for primitives. // Walk the argument types, looking for primitives.
int pac = 0, lac = 0, prc = 0, lrc = 0; short primitiveCount = 0, longArgCount = 0;
Class<?>[] epts = ptypes; Class<?>[] epts = ptypes;
Class<?>[] bpts = epts; Class<?>[] bpts = epts;
for (int i = 0; i < epts.length; i++) { for (int i = 0; i < epts.length; i++) {
Class<?> pt = epts[i]; Class<?> pt = epts[i];
if (pt != Object.class) { if (pt != Object.class) {
++pac; ++primitiveCount;
Wrapper w = Wrapper.forPrimitiveType(pt); Wrapper w = Wrapper.forPrimitiveType(pt);
if (w.isDoubleWord()) ++lac; if (w.isDoubleWord()) ++longArgCount;
if (w.isSubwordOrInt() && pt != int.class) { if (w.isSubwordOrInt() && pt != int.class) {
if (bpts == epts) if (bpts == epts)
bpts = bpts.clone(); bpts = bpts.clone();
@ -183,20 +177,14 @@ final class MethodTypeForm {
} }
} }
} }
pslotCount += lac; // #slots = #args + #longs pslotCount += longArgCount; // #slots = #args + #longs
Class<?> rt = erasedType.returnType(); Class<?> rt = erasedType.returnType();
Class<?> bt = rt; Class<?> bt = rt;
if (rt != Object.class) { if (rt != Object.class) {
++prc; // even void.class counts as a prim here ++primitiveCount; // even void.class counts as a prim here
Wrapper w = Wrapper.forPrimitiveType(rt); Wrapper w = Wrapper.forPrimitiveType(rt);
if (w.isDoubleWord()) ++lrc;
if (w.isSubwordOrInt() && rt != int.class) if (w.isSubwordOrInt() && rt != int.class)
bt = int.class; bt = int.class;
// adjust #slots, #args
if (rt == void.class)
rtypeCount = rslotCount = 0;
else
rslotCount += lrc;
} }
if (epts == bpts && bt == rt) { if (epts == bpts && bt == rt) {
this.basicType = erasedType; this.basicType = erasedType;
@ -205,112 +193,32 @@ final class MethodTypeForm {
// fill in rest of data from the basic type: // fill in rest of data from the basic type:
MethodTypeForm that = this.basicType.form(); MethodTypeForm that = this.basicType.form();
assert(this != that); assert(this != that);
this.primCounts = that.primCounts; this.parameterSlotCount = that.parameterSlotCount;
this.argCounts = that.argCounts; this.primitiveCount = that.primitiveCount;
this.argToSlotTable = that.argToSlotTable;
this.slotToArgTable = that.slotToArgTable;
this.methodHandles = null; this.methodHandles = null;
this.lambdaForms = null; this.lambdaForms = null;
return; return;
} }
if (lac != 0) {
int slot = ptypeCount + lac;
slotToArgTab = new int[slot+1];
argToSlotTab = new int[1+ptypeCount];
argToSlotTab[0] = slot; // argument "-1" is past end of slots
for (int i = 0; i < epts.length; i++) {
Class<?> pt = epts[i];
Wrapper w = Wrapper.forBasicType(pt);
if (w.isDoubleWord()) --slot;
--slot;
slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
argToSlotTab[1+i] = slot;
}
assert(slot == 0); // filled the table
} else if (pac != 0) {
// have primitives but no long primitives; share slot counts with generic
assert(ptypeCount == pslotCount);
MethodTypeForm that = MethodType.genericMethodType(ptypeCount).form();
assert(this != that);
slotToArgTab = that.slotToArgTable;
argToSlotTab = that.argToSlotTable;
} else {
int slot = ptypeCount; // first arg is deepest in stack
slotToArgTab = new int[slot+1];
argToSlotTab = new int[1+ptypeCount];
argToSlotTab[0] = slot; // argument "-1" is past end of slots
for (int i = 0; i < ptypeCount; i++) {
--slot;
slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
argToSlotTab[1+i] = slot;
}
}
this.primCounts = pack(lrc, prc, lac, pac);
this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
this.argToSlotTable = argToSlotTab;
this.slotToArgTable = slotToArgTab;
if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments"); if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments");
this.primitiveCount = primitiveCount;
this.parameterSlotCount = (short)pslotCount;
// Initialize caches, but only for basic types // Initialize caches, but only for basic types
assert(basicType == erasedType); assert(basicType == erasedType);
this.lambdaForms = new SoftReference[LF_LIMIT]; this.lambdaForms = new SoftReference[LF_LIMIT];
this.methodHandles = new SoftReference[MH_LIMIT]; this.methodHandles = new SoftReference[MH_LIMIT];
} }
private static long pack(int a, int b, int c, int d) {
assert(((a|b|c|d) & ~0xFFFF) == 0);
long hw = ((a << 16) | b), lw = ((c << 16) | d);
return (hw << 32) | lw;
}
private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
assert(word <= 3);
return (char)(packed >> ((3-word) * 16));
}
public int parameterCount() { // # outgoing values public int parameterCount() { // # outgoing values
return unpack(argCounts, 3); return erasedType.parameterCount();
} }
public int parameterSlotCount() { // # outgoing interpreter slots public int parameterSlotCount() { // # outgoing interpreter slots
return unpack(argCounts, 2); return parameterSlotCount;
}
public int returnCount() { // = 0 (V), or 1
return unpack(argCounts, 1);
}
public int returnSlotCount() { // = 0 (V), 2 (J/D), or 1
return unpack(argCounts, 0);
}
public int primitiveParameterCount() {
return unpack(primCounts, 3);
}
public int longPrimitiveParameterCount() {
return unpack(primCounts, 2);
}
public int primitiveReturnCount() { // = 0 (obj), or 1
return unpack(primCounts, 1);
}
public int longPrimitiveReturnCount() { // = 1 (J/D), or 0
return unpack(primCounts, 0);
} }
public boolean hasPrimitives() { public boolean hasPrimitives() {
return primCounts != 0; return primitiveCount != 0;
}
public boolean hasNonVoidPrimitives() {
if (primCounts == 0) return false;
if (primitiveParameterCount() != 0) return true;
return (primitiveReturnCount() != 0 && returnCount() != 0);
}
public boolean hasLongPrimitives() {
return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
}
public int parameterToArgSlot(int i) {
return argToSlotTable[1+i];
}
public int argSlotToParameter(int argSlot) {
// Note: Empty slots are represented by zero in this table.
// Valid arguments slots contain incremented entries, so as to be non-zero.
// We return -1 the caller to mean an empty slot.
return slotToArgTable[argSlot] - 1;
} }
static MethodTypeForm findForm(MethodType mt) { static MethodTypeForm findForm(MethodType mt) {
@ -334,7 +242,7 @@ final class MethodTypeForm {
* (assumed to be a return type) to int if it is smaller than an int, * (assumed to be a return type) to int if it is smaller than an int,
* or if it is void. * or if it is void.
*/ */
public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6; public static final int ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
/** Canonicalize the types in the given method type. /** Canonicalize the types in the given method type.
* If any types change, intern the new type, and return it. * If any types change, intern the new type, and return it.
@ -342,9 +250,9 @@ final class MethodTypeForm {
*/ */
public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) { public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
Class<?>[] ptypes = mt.ptypes(); Class<?>[] ptypes = mt.ptypes();
Class<?>[] ptc = MethodTypeForm.canonicalizeAll(ptypes, howArgs); Class<?>[] ptc = canonicalizeAll(ptypes, howArgs);
Class<?> rtype = mt.returnType(); Class<?> rtype = mt.returnType();
Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet); Class<?> rtc = canonicalize(rtype, howRet);
if (ptc == null && rtc == null) { if (ptc == null && rtc == null) {
// It is already canonical. // It is already canonical.
return null; return null;
@ -414,9 +322,8 @@ final class MethodTypeForm {
Class<?>[] cs = null; Class<?>[] cs = null;
for (int imax = ts.length, i = 0; i < imax; i++) { for (int imax = ts.length, i = 0; i < imax; i++) {
Class<?> c = canonicalize(ts[i], how); Class<?> c = canonicalize(ts[i], how);
if (c == void.class) // Void parameters may be unwrapped to void; ignore those
c = null; // a Void parameter was unwrapped to void; ignore if (c != null && c != void.class) {
if (c != null) {
if (cs == null) if (cs == null)
cs = ts.clone(); cs = ts.clone();
cs[i] = c; cs[i] = c;