mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8230768: Arrays of SoftReferences in MethodTypeForm should not be @Stable
Reviewed-by: mchung
This commit is contained in:
parent
2f67784a45
commit
52f9024232
1 changed files with 39 additions and 49 deletions
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
package java.lang.invoke;
|
package java.lang.invoke;
|
||||||
|
|
||||||
import jdk.internal.vm.annotation.Stable;
|
|
||||||
import sun.invoke.util.Wrapper;
|
import sun.invoke.util.Wrapper;
|
||||||
|
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
|
@ -52,7 +51,8 @@ final class MethodTypeForm {
|
||||||
final MethodType basicType; // the canonical erasure, with primitives simplified
|
final MethodType basicType; // the canonical erasure, with primitives simplified
|
||||||
|
|
||||||
// Cached adapter information:
|
// Cached adapter information:
|
||||||
@Stable final SoftReference<MethodHandle>[] methodHandles;
|
final SoftReference<MethodHandle>[] methodHandles;
|
||||||
|
|
||||||
// Indexes into methodHandles:
|
// Indexes into methodHandles:
|
||||||
static final int
|
static final int
|
||||||
MH_BASIC_INV = 0, // cached instance of MH.invokeBasic
|
MH_BASIC_INV = 0, // cached instance of MH.invokeBasic
|
||||||
|
@ -61,7 +61,8 @@ final class MethodTypeForm {
|
||||||
MH_LIMIT = 3;
|
MH_LIMIT = 3;
|
||||||
|
|
||||||
// Cached lambda form information, for basic types only:
|
// Cached lambda form information, for basic types only:
|
||||||
final @Stable SoftReference<LambdaForm>[] lambdaForms;
|
final SoftReference<LambdaForm>[] lambdaForms;
|
||||||
|
|
||||||
// Indexes into lambdaForms:
|
// Indexes into lambdaForms:
|
||||||
static final int
|
static final int
|
||||||
LF_INVVIRTUAL = 0, // DMH invokeVirtual
|
LF_INVVIRTUAL = 0, // DMH invokeVirtual
|
||||||
|
@ -103,15 +104,7 @@ final class MethodTypeForm {
|
||||||
return basicType;
|
return basicType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean assertIsBasicType() {
|
|
||||||
// primitives must be flattened also
|
|
||||||
assert(erasedType == basicType)
|
|
||||||
: "erasedType: " + erasedType + " != basicType: " + basicType;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MethodHandle cachedMethodHandle(int which) {
|
public MethodHandle cachedMethodHandle(int which) {
|
||||||
assert(assertIsBasicType());
|
|
||||||
SoftReference<MethodHandle> entry = methodHandles[which];
|
SoftReference<MethodHandle> entry = methodHandles[which];
|
||||||
return (entry != null) ? entry.get() : null;
|
return (entry != null) ? entry.get() : null;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +123,6 @@ final class MethodTypeForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public LambdaForm cachedLambdaForm(int which) {
|
public LambdaForm cachedLambdaForm(int which) {
|
||||||
assert(assertIsBasicType());
|
|
||||||
SoftReference<LambdaForm> entry = lambdaForms[which];
|
SoftReference<LambdaForm> entry = lambdaForms[which];
|
||||||
return (entry != null) ? entry.get() : null;
|
return (entry != null) ? entry.get() : null;
|
||||||
}
|
}
|
||||||
|
@ -162,59 +154,57 @@ final class MethodTypeForm {
|
||||||
|
|
||||||
// Walk the argument types, looking for primitives.
|
// Walk the argument types, looking for primitives.
|
||||||
short primitiveCount = 0, longArgCount = 0;
|
short primitiveCount = 0, longArgCount = 0;
|
||||||
Class<?>[] epts = ptypes;
|
Class<?>[] erasedPtypes = ptypes;
|
||||||
Class<?>[] bpts = epts;
|
Class<?>[] basicPtypes = erasedPtypes;
|
||||||
for (int i = 0; i < epts.length; i++) {
|
for (int i = 0; i < erasedPtypes.length; i++) {
|
||||||
Class<?> pt = epts[i];
|
Class<?> ptype = erasedPtypes[i];
|
||||||
if (pt != Object.class) {
|
if (ptype != Object.class) {
|
||||||
++primitiveCount;
|
++primitiveCount;
|
||||||
Wrapper w = Wrapper.forPrimitiveType(pt);
|
Wrapper w = Wrapper.forPrimitiveType(ptype);
|
||||||
if (w.isDoubleWord()) ++longArgCount;
|
if (w.isDoubleWord()) ++longArgCount;
|
||||||
if (w.isSubwordOrInt() && pt != int.class) {
|
if (w.isSubwordOrInt() && ptype != int.class) {
|
||||||
if (bpts == epts)
|
if (basicPtypes == erasedPtypes)
|
||||||
bpts = bpts.clone();
|
basicPtypes = basicPtypes.clone();
|
||||||
bpts[i] = int.class;
|
basicPtypes[i] = int.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pslotCount += longArgCount; // #slots = #args + #longs
|
pslotCount += longArgCount; // #slots = #args + #longs
|
||||||
Class<?> rt = erasedType.returnType();
|
Class<?> returnType = erasedType.returnType();
|
||||||
Class<?> bt = rt;
|
Class<?> basicReturnType = returnType;
|
||||||
if (rt != Object.class) {
|
if (returnType != Object.class) {
|
||||||
++primitiveCount; // 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(returnType);
|
||||||
if (w.isSubwordOrInt() && rt != int.class)
|
if (w.isSubwordOrInt() && returnType != int.class)
|
||||||
bt = int.class;
|
basicReturnType = int.class;
|
||||||
}
|
}
|
||||||
if (epts == bpts && bt == rt) {
|
if (erasedPtypes == basicPtypes && basicReturnType == returnType) {
|
||||||
|
// Basic type
|
||||||
this.basicType = erasedType;
|
this.basicType = erasedType;
|
||||||
} else {
|
|
||||||
this.basicType = MethodType.makeImpl(bt, bpts, true);
|
|
||||||
// fill in rest of data from the basic type:
|
|
||||||
MethodTypeForm that = this.basicType.form();
|
|
||||||
assert(this != that);
|
|
||||||
this.parameterSlotCount = that.parameterSlotCount;
|
|
||||||
this.primitiveCount = that.primitiveCount;
|
|
||||||
this.methodHandles = null;
|
|
||||||
this.lambdaForms = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments");
|
if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments");
|
||||||
|
|
||||||
this.primitiveCount = primitiveCount;
|
this.primitiveCount = primitiveCount;
|
||||||
this.parameterSlotCount = (short)pslotCount;
|
this.parameterSlotCount = (short)pslotCount;
|
||||||
|
|
||||||
// Initialize caches, but only for basic types
|
|
||||||
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];
|
||||||
|
} else {
|
||||||
|
this.basicType = MethodType.makeImpl(basicReturnType, basicPtypes, true);
|
||||||
|
// fill in rest of data from the basic type:
|
||||||
|
MethodTypeForm that = this.basicType.form();
|
||||||
|
assert(this != that);
|
||||||
|
|
||||||
|
this.parameterSlotCount = that.parameterSlotCount;
|
||||||
|
this.primitiveCount = that.primitiveCount;
|
||||||
|
this.methodHandles = null;
|
||||||
|
this.lambdaForms = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int parameterCount() { // # outgoing values
|
public int parameterCount() {
|
||||||
return erasedType.parameterCount();
|
return erasedType.parameterCount();
|
||||||
}
|
}
|
||||||
public int parameterSlotCount() { // # outgoing interpreter slots
|
public int parameterSlotCount() {
|
||||||
return parameterSlotCount;
|
return parameterSlotCount;
|
||||||
}
|
}
|
||||||
public boolean hasPrimitives() {
|
public boolean hasPrimitives() {
|
||||||
|
@ -250,17 +240,17 @@ 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 = canonicalizeAll(ptypes, howArgs);
|
Class<?>[] ptypesCanonical = canonicalizeAll(ptypes, howArgs);
|
||||||
Class<?> rtype = mt.returnType();
|
Class<?> rtype = mt.returnType();
|
||||||
Class<?> rtc = canonicalize(rtype, howRet);
|
Class<?> rtypeCanonical = canonicalize(rtype, howRet);
|
||||||
if (ptc == null && rtc == null) {
|
if (ptypesCanonical == null && rtypeCanonical == null) {
|
||||||
// It is already canonical.
|
// It is already canonical.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Find the erased version of the method type:
|
// Find the erased version of the method type:
|
||||||
if (rtc == null) rtc = rtype;
|
if (rtypeCanonical == null) rtypeCanonical = rtype;
|
||||||
if (ptc == null) ptc = ptypes;
|
if (ptypesCanonical == null) ptypesCanonical = ptypes;
|
||||||
return MethodType.makeImpl(rtc, ptc, true);
|
return MethodType.makeImpl(rtypeCanonical, ptypesCanonical, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Canonicalize the given return or param type.
|
/** Canonicalize the given return or param type.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue