Skip to content

Commit c788d98

Browse files
committed
8230662: Remove dead code from MethodTypeForm
Reviewed-by: vlivanov, mchung
1 parent 9c3ff10 commit c788d98

File tree

3 files changed

+31
-163
lines changed

3 files changed

+31
-163
lines changed

src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -123,9 +123,13 @@ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize,
123123
private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) {
124124
this(null, invokerType.parameterCount(),
125125
className, invokerName, invokerType);
126+
MethodType mt = invokerType.erase();
126127
// Create an array to map name indexes to locals indexes.
127-
for (int i = 0; i < localsMap.length; i++) {
128-
localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i);
128+
localsMap[0] = 0; // localsMap has at least one element
129+
for (int i = 1, index = 0; i < localsMap.length; i++) {
130+
Wrapper w = Wrapper.forBasicType(mt.parameterType(i - 1));
131+
index += w.stackSlots();
132+
localsMap[i] = index;
129133
}
130134
}
131135

src/java.base/share/classes/java/lang/invoke/MethodType.java

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -926,8 +926,8 @@ boolean isConvertibleTo(MethodType newType) {
926926
return false;
927927
return true;
928928
}
929-
if ((oldForm.primitiveParameterCount() == 0 && oldForm.erasedType == this) ||
930-
(newForm.primitiveParameterCount() == 0 && newForm.erasedType == newType)) {
929+
if ((!oldForm.hasPrimitives() && oldForm.erasedType == this) ||
930+
(!newForm.hasPrimitives() && newForm.erasedType == newType)) {
931931
// Somewhat complicated test to avoid a loop of 2 or more trips.
932932
// If either type has only Object parameters, we know we can convert.
933933
assert(canConvertParameters(srcTypes, dstTypes));
@@ -1073,49 +1073,6 @@ static boolean canConvert(Class<?> src, Class<?> dst) {
10731073
return inv;
10741074
}
10751075

1076-
/** Reports the number of JVM stack slots which carry all parameters including and after
1077-
* the given position, which must be in the range of 0 to
1078-
* {@code parameterCount} inclusive. Successive parameters are
1079-
* more shallowly stacked, and parameters are indexed in the bytecodes
1080-
* according to their trailing edge. Thus, to obtain the depth
1081-
* in the outgoing call stack of parameter {@code N}, obtain
1082-
* the {@code parameterSlotDepth} of its trailing edge
1083-
* at position {@code N+1}.
1084-
* <p>
1085-
* Parameters of type {@code long} and {@code double} occupy
1086-
* two stack slots (for historical reasons) and all others occupy one.
1087-
* Therefore, the number returned is the number of arguments
1088-
* <em>including</em> and <em>after</em> the given parameter,
1089-
* <em>plus</em> the number of long or double arguments
1090-
* at or after the argument for the given parameter.
1091-
* <p>
1092-
* This method is included for the benefit of applications that must
1093-
* generate bytecodes that process method handles and invokedynamic.
1094-
* @param num an index (zero-based, inclusive) within the parameter types
1095-
* @return the index of the (shallowest) JVM stack slot transmitting the
1096-
* given parameter
1097-
* @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
1098-
*/
1099-
/*non-public*/ int parameterSlotDepth(int num) {
1100-
if (num < 0 || num > ptypes.length)
1101-
parameterType(num); // force a range check
1102-
return form.parameterToArgSlot(num-1);
1103-
}
1104-
1105-
/** Reports the number of JVM stack slots required to receive a return value
1106-
* from a method of this type.
1107-
* If the {@link #returnType() return type} is void, it will be zero,
1108-
* else if the return type is long or double, it will be two, else one.
1109-
* <p>
1110-
* This method is included for the benefit of applications that must
1111-
* generate bytecodes that process method handles and invokedynamic.
1112-
* @return the number of JVM stack slots (0, 1, or 2) for this type's return value
1113-
* Will be removed for PFD.
1114-
*/
1115-
/*non-public*/ int returnSlotCount() {
1116-
return form.returnSlotCount();
1117-
}
1118-
11191076
/**
11201077
* Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
11211078
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.

src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java

Lines changed: 22 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -46,9 +46,8 @@
4646
* @author John Rose
4747
*/
4848
final class MethodTypeForm {
49-
final int[] argToSlotTable, slotToArgTable;
50-
final long argCounts; // packed slot & value counts
51-
final long primCounts; // packed prim & double counts
49+
final short parameterSlotCount;
50+
final short primitiveCount;
5251
final MethodType erasedType; // the canonical erasure
5352
final MethodType basicType; // the canonical erasure, with primitives simplified
5453

@@ -159,44 +158,33 @@ protected MethodTypeForm(MethodType erasedType) {
159158
this.erasedType = erasedType;
160159

161160
Class<?>[] ptypes = erasedType.ptypes();
162-
int ptypeCount = ptypes.length;
163-
int pslotCount = ptypeCount; // temp. estimate
164-
int rtypeCount = 1; // temp. estimate
165-
int rslotCount = 1; // temp. estimate
166-
167-
int[] argToSlotTab = null, slotToArgTab = null;
161+
int pslotCount = ptypes.length;
168162

169163
// Walk the argument types, looking for primitives.
170-
int pac = 0, lac = 0, prc = 0, lrc = 0;
164+
short primitiveCount = 0, longArgCount = 0;
171165
Class<?>[] epts = ptypes;
172166
Class<?>[] bpts = epts;
173167
for (int i = 0; i < epts.length; i++) {
174168
Class<?> pt = epts[i];
175169
if (pt != Object.class) {
176-
++pac;
170+
++primitiveCount;
177171
Wrapper w = Wrapper.forPrimitiveType(pt);
178-
if (w.isDoubleWord()) ++lac;
172+
if (w.isDoubleWord()) ++longArgCount;
179173
if (w.isSubwordOrInt() && pt != int.class) {
180174
if (bpts == epts)
181175
bpts = bpts.clone();
182176
bpts[i] = int.class;
183177
}
184178
}
185179
}
186-
pslotCount += lac; // #slots = #args + #longs
180+
pslotCount += longArgCount; // #slots = #args + #longs
187181
Class<?> rt = erasedType.returnType();
188182
Class<?> bt = rt;
189183
if (rt != Object.class) {
190-
++prc; // even void.class counts as a prim here
184+
++primitiveCount; // even void.class counts as a prim here
191185
Wrapper w = Wrapper.forPrimitiveType(rt);
192-
if (w.isDoubleWord()) ++lrc;
193186
if (w.isSubwordOrInt() && rt != int.class)
194187
bt = int.class;
195-
// adjust #slots, #args
196-
if (rt == void.class)
197-
rtypeCount = rslotCount = 0;
198-
else
199-
rslotCount += lrc;
200188
}
201189
if (epts == bpts && bt == rt) {
202190
this.basicType = erasedType;
@@ -205,112 +193,32 @@ protected MethodTypeForm(MethodType erasedType) {
205193
// fill in rest of data from the basic type:
206194
MethodTypeForm that = this.basicType.form();
207195
assert(this != that);
208-
this.primCounts = that.primCounts;
209-
this.argCounts = that.argCounts;
210-
this.argToSlotTable = that.argToSlotTable;
211-
this.slotToArgTable = that.slotToArgTable;
196+
this.parameterSlotCount = that.parameterSlotCount;
197+
this.primitiveCount = that.primitiveCount;
212198
this.methodHandles = null;
213199
this.lambdaForms = null;
214200
return;
215201
}
216-
if (lac != 0) {
217-
int slot = ptypeCount + lac;
218-
slotToArgTab = new int[slot+1];
219-
argToSlotTab = new int[1+ptypeCount];
220-
argToSlotTab[0] = slot; // argument "-1" is past end of slots
221-
for (int i = 0; i < epts.length; i++) {
222-
Class<?> pt = epts[i];
223-
Wrapper w = Wrapper.forBasicType(pt);
224-
if (w.isDoubleWord()) --slot;
225-
--slot;
226-
slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
227-
argToSlotTab[1+i] = slot;
228-
}
229-
assert(slot == 0); // filled the table
230-
} else if (pac != 0) {
231-
// have primitives but no long primitives; share slot counts with generic
232-
assert(ptypeCount == pslotCount);
233-
MethodTypeForm that = MethodType.genericMethodType(ptypeCount).form();
234-
assert(this != that);
235-
slotToArgTab = that.slotToArgTable;
236-
argToSlotTab = that.argToSlotTable;
237-
} else {
238-
int slot = ptypeCount; // first arg is deepest in stack
239-
slotToArgTab = new int[slot+1];
240-
argToSlotTab = new int[1+ptypeCount];
241-
argToSlotTab[0] = slot; // argument "-1" is past end of slots
242-
for (int i = 0; i < ptypeCount; i++) {
243-
--slot;
244-
slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
245-
argToSlotTab[1+i] = slot;
246-
}
247-
}
248-
this.primCounts = pack(lrc, prc, lac, pac);
249-
this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
250-
this.argToSlotTable = argToSlotTab;
251-
this.slotToArgTable = slotToArgTab;
252202

253203
if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments");
254204

205+
this.primitiveCount = primitiveCount;
206+
this.parameterSlotCount = (short)pslotCount;
207+
255208
// Initialize caches, but only for basic types
256209
assert(basicType == erasedType);
257210
this.lambdaForms = new SoftReference[LF_LIMIT];
258211
this.methodHandles = new SoftReference[MH_LIMIT];
259212
}
260213

261-
private static long pack(int a, int b, int c, int d) {
262-
assert(((a|b|c|d) & ~0xFFFF) == 0);
263-
long hw = ((a << 16) | b), lw = ((c << 16) | d);
264-
return (hw << 32) | lw;
265-
}
266-
private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
267-
assert(word <= 3);
268-
return (char)(packed >> ((3-word) * 16));
269-
}
270-
271214
public int parameterCount() { // # outgoing values
272-
return unpack(argCounts, 3);
215+
return erasedType.parameterCount();
273216
}
274217
public int parameterSlotCount() { // # outgoing interpreter slots
275-
return unpack(argCounts, 2);
276-
}
277-
public int returnCount() { // = 0 (V), or 1
278-
return unpack(argCounts, 1);
279-
}
280-
public int returnSlotCount() { // = 0 (V), 2 (J/D), or 1
281-
return unpack(argCounts, 0);
282-
}
283-
public int primitiveParameterCount() {
284-
return unpack(primCounts, 3);
285-
}
286-
public int longPrimitiveParameterCount() {
287-
return unpack(primCounts, 2);
288-
}
289-
public int primitiveReturnCount() { // = 0 (obj), or 1
290-
return unpack(primCounts, 1);
291-
}
292-
public int longPrimitiveReturnCount() { // = 1 (J/D), or 0
293-
return unpack(primCounts, 0);
218+
return parameterSlotCount;
294219
}
295220
public boolean hasPrimitives() {
296-
return primCounts != 0;
297-
}
298-
public boolean hasNonVoidPrimitives() {
299-
if (primCounts == 0) return false;
300-
if (primitiveParameterCount() != 0) return true;
301-
return (primitiveReturnCount() != 0 && returnCount() != 0);
302-
}
303-
public boolean hasLongPrimitives() {
304-
return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
305-
}
306-
public int parameterToArgSlot(int i) {
307-
return argToSlotTable[1+i];
308-
}
309-
public int argSlotToParameter(int argSlot) {
310-
// Note: Empty slots are represented by zero in this table.
311-
// Valid arguments slots contain incremented entries, so as to be non-zero.
312-
// We return -1 the caller to mean an empty slot.
313-
return slotToArgTable[argSlot] - 1;
221+
return primitiveCount != 0;
314222
}
315223

316224
static MethodTypeForm findForm(MethodType mt) {
@@ -334,17 +242,17 @@ static MethodTypeForm findForm(MethodType mt) {
334242
* (assumed to be a return type) to int if it is smaller than an int,
335243
* or if it is void.
336244
*/
337-
public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
245+
public static final int ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
338246

339247
/** Canonicalize the types in the given method type.
340248
* If any types change, intern the new type, and return it.
341249
* Otherwise return null.
342250
*/
343251
public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
344252
Class<?>[] ptypes = mt.ptypes();
345-
Class<?>[] ptc = MethodTypeForm.canonicalizeAll(ptypes, howArgs);
253+
Class<?>[] ptc = canonicalizeAll(ptypes, howArgs);
346254
Class<?> rtype = mt.returnType();
347-
Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
255+
Class<?> rtc = canonicalize(rtype, howRet);
348256
if (ptc == null && rtc == null) {
349257
// It is already canonical.
350258
return null;
@@ -414,9 +322,8 @@ static Class<?>[] canonicalizeAll(Class<?>[] ts, int how) {
414322
Class<?>[] cs = null;
415323
for (int imax = ts.length, i = 0; i < imax; i++) {
416324
Class<?> c = canonicalize(ts[i], how);
417-
if (c == void.class)
418-
c = null; // a Void parameter was unwrapped to void; ignore
419-
if (c != null) {
325+
// Void parameters may be unwrapped to void; ignore those
326+
if (c != null && c != void.class) {
420327
if (cs == null)
421328
cs = ts.clone();
422329
cs[i] = c;

0 commit comments

Comments
 (0)