mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8263087: Add a MethodHandle combinator that switches over a set of MethodHandles
Reviewed-by: redestad
This commit is contained in:
parent
85f616522b
commit
3623abb7f6
10 changed files with 974 additions and 26 deletions
|
@ -314,6 +314,7 @@ class LambdaForm {
|
|||
GET_DOUBLE_VOLATILE("getDoubleVolatile"),
|
||||
PUT_DOUBLE_VOLATILE("putDoubleVolatile"),
|
||||
TRY_FINALLY("tryFinally"),
|
||||
TABLE_SWITCH("tableSwitch"),
|
||||
COLLECT("collect"),
|
||||
COLLECTOR("collector"),
|
||||
CONVERT("convert"),
|
||||
|
@ -707,6 +708,32 @@ class LambdaForm {
|
|||
return isMatchingIdiom(pos, "tryFinally", 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if i-th name is a start of the tableSwitch idiom.
|
||||
*/
|
||||
boolean isTableSwitch(int pos) {
|
||||
// tableSwitch idiom:
|
||||
// t_{n}:L=MethodHandle.invokeBasic(...) // args
|
||||
// t_{n+1}:L=MethodHandleImpl.tableSwitch(*, *, *, t_{n})
|
||||
// t_{n+2}:?=MethodHandle.invokeBasic(*, t_{n+1})
|
||||
if (pos + 2 >= names.length) return false;
|
||||
|
||||
final int POS_COLLECT_ARGS = pos;
|
||||
final int POS_TABLE_SWITCH = pos + 1;
|
||||
final int POS_UNBOX_RESULT = pos + 2;
|
||||
|
||||
Name collectArgs = names[POS_COLLECT_ARGS];
|
||||
Name tableSwitch = names[POS_TABLE_SWITCH];
|
||||
Name unboxResult = names[POS_UNBOX_RESULT];
|
||||
return tableSwitch.refersTo(MethodHandleImpl.class, "tableSwitch") &&
|
||||
collectArgs.isInvokeBasic() &&
|
||||
unboxResult.isInvokeBasic() &&
|
||||
tableSwitch.lastUseIndex(collectArgs) == 3 && // t_{n+1}:L=MethodHandleImpl.<invoker>(*, *, *, t_{n});
|
||||
lastUseIndex(collectArgs) == POS_TABLE_SWITCH && // t_{n} is local: used only in t_{n+1}
|
||||
unboxResult.lastUseIndex(tableSwitch) == 1 && // t_{n+2}:?=MethodHandle.invokeBasic(*, t_{n+1})
|
||||
lastUseIndex(tableSwitch) == POS_UNBOX_RESULT; // t_{n+1} is local: used only in t_{n+2}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if i-th name is a start of the loop idiom.
|
||||
*/
|
||||
|
@ -1067,24 +1094,13 @@ class LambdaForm {
|
|||
final MemberName member;
|
||||
private @Stable MethodHandle resolvedHandle;
|
||||
@Stable MethodHandle invoker;
|
||||
private final MethodHandleImpl.Intrinsic intrinsicName;
|
||||
|
||||
NamedFunction(MethodHandle resolvedHandle) {
|
||||
this(resolvedHandle.internalMemberName(), resolvedHandle, MethodHandleImpl.Intrinsic.NONE);
|
||||
}
|
||||
NamedFunction(MethodHandle resolvedHandle, MethodHandleImpl.Intrinsic intrinsic) {
|
||||
this(resolvedHandle.internalMemberName(), resolvedHandle, intrinsic);
|
||||
this(resolvedHandle.internalMemberName(), resolvedHandle);
|
||||
}
|
||||
NamedFunction(MemberName member, MethodHandle resolvedHandle) {
|
||||
this(member, resolvedHandle, MethodHandleImpl.Intrinsic.NONE);
|
||||
}
|
||||
NamedFunction(MemberName member, MethodHandle resolvedHandle, MethodHandleImpl.Intrinsic intrinsic) {
|
||||
this.member = member;
|
||||
this.resolvedHandle = resolvedHandle;
|
||||
this.intrinsicName = intrinsic;
|
||||
assert(resolvedHandle == null ||
|
||||
resolvedHandle.intrinsicName() == MethodHandleImpl.Intrinsic.NONE ||
|
||||
resolvedHandle.intrinsicName() == intrinsic) : resolvedHandle.intrinsicName() + " != " + intrinsic;
|
||||
// The following assert is almost always correct, but will fail for corner cases, such as PrivateInvokeTest.
|
||||
//assert(!isInvokeBasic(member));
|
||||
}
|
||||
|
@ -1097,7 +1113,6 @@ class LambdaForm {
|
|||
// necessary to pass BigArityTest
|
||||
this.member = Invokers.invokeBasicMethod(basicInvokerType);
|
||||
}
|
||||
this.intrinsicName = MethodHandleImpl.Intrinsic.NONE;
|
||||
assert(isInvokeBasic(member));
|
||||
}
|
||||
|
||||
|
@ -1250,7 +1265,15 @@ class LambdaForm {
|
|||
}
|
||||
|
||||
public MethodHandleImpl.Intrinsic intrinsicName() {
|
||||
return intrinsicName;
|
||||
return resolvedHandle != null
|
||||
? resolvedHandle.intrinsicName()
|
||||
: MethodHandleImpl.Intrinsic.NONE;
|
||||
}
|
||||
|
||||
public Object intrinsicData() {
|
||||
return resolvedHandle != null
|
||||
? resolvedHandle.intrinsicData()
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1732,15 +1755,15 @@ class LambdaForm {
|
|||
Name[] idNames = new Name[] { argument(0, L_TYPE), argument(1, type) };
|
||||
idForm = new LambdaForm(2, idNames, 1, Kind.IDENTITY);
|
||||
idForm.compileToBytecode();
|
||||
idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm),
|
||||
MethodHandleImpl.Intrinsic.IDENTITY);
|
||||
idFun = new NamedFunction(idMem, MethodHandleImpl.makeIntrinsic(SimpleMethodHandle.make(idMem.getInvocationType(), idForm),
|
||||
MethodHandleImpl.Intrinsic.IDENTITY));
|
||||
|
||||
Object zeValue = Wrapper.forBasicType(btChar).zero();
|
||||
Name[] zeNames = new Name[] { argument(0, L_TYPE), new Name(idFun, zeValue) };
|
||||
zeForm = new LambdaForm(1, zeNames, 1, Kind.ZERO);
|
||||
zeForm.compileToBytecode();
|
||||
zeFun = new NamedFunction(zeMem, SimpleMethodHandle.make(zeMem.getInvocationType(), zeForm),
|
||||
MethodHandleImpl.Intrinsic.ZERO);
|
||||
zeFun = new NamedFunction(zeMem, MethodHandleImpl.makeIntrinsic(SimpleMethodHandle.make(zeMem.getInvocationType(), zeForm),
|
||||
MethodHandleImpl.Intrinsic.ZERO));
|
||||
}
|
||||
|
||||
LF_zero[ord] = zeForm;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue