Skip to content

Commit 74ad47b

Browse files
committed
[GR-29688] New method handle intrinsification.
PullRequest: graal/14869
2 parents a216052 + b497acf commit 74ad47b

File tree

60 files changed

+1960
-912
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1960
-912
lines changed

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/hightiercodegen/NodeLowerer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
import org.graalvm.compiler.nodes.java.AtomicReadAndWriteNode;
8787
import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode;
8888
import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
89+
import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode;
8990
import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
9091
import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
9192
import org.graalvm.compiler.nodes.java.InstanceOfNode;
@@ -333,6 +334,8 @@ protected void dispatch(Node node) {
333334
lower((IdentityHashCodeNode) node);
334335
} else if (node instanceof ClassIsAssignableFromNode) {
335336
lower((ClassIsAssignableFromNode) node);
337+
} else if (node instanceof DynamicNewInstanceNode n) {
338+
lower(n);
336339
} else {
337340
if (!isIgnored(node)) {
338341
handleUnknownNodeType(node);
@@ -439,6 +442,8 @@ protected void handleUnknownNodeType(Node node) {
439442

440443
protected abstract void lower(NewInstanceNode node);
441444

445+
protected abstract void lower(DynamicNewInstanceNode node);
446+
442447
protected abstract void lower(NotNode node);
443448

444449
protected abstract void lower(NarrowNode node);

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/java/BytecodeParser.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,16 @@ protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKi
13381338
deopt.updateNodeSourcePosition(() -> createBytecodePosition());
13391339
}
13401340

1341+
protected FrameStateBuilder createFrameStateForExceptionHandling(@SuppressWarnings("unused") int bci) {
1342+
FrameStateBuilder dispatchState = frameState.copy();
1343+
dispatchState.clearStack();
1344+
return dispatchState;
1345+
}
1346+
1347+
protected void clearNonLiveLocals(FrameStateBuilder state, BciBlock block, boolean liveIn) {
1348+
state.clearNonLiveLocals(block, liveness, liveIn);
1349+
}
1350+
13411351
/**
13421352
* @return the entry point to exception dispatch
13431353
*/
@@ -1346,8 +1356,7 @@ protected AbstractBeginNode handleException(ValueNode exceptionObject, int bci,
13461356
assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci";
13471357
debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci)));
13481358

1349-
FrameStateBuilder dispatchState = frameState.copy();
1350-
dispatchState.clearStack();
1359+
FrameStateBuilder dispatchState = createFrameStateForExceptionHandling(bci);
13511360

13521361
AbstractBeginNode dispatchBegin;
13531362
if (exceptionObject == null) {
@@ -1374,13 +1383,20 @@ protected AbstractBeginNode handleException(ValueNode exceptionObject, int bci,
13741383
return dispatchBegin;
13751384
}
13761385

1377-
protected void createHandleExceptionTarget(FixedWithNextNode afterExceptionLoaded, int bci, FrameStateBuilder dispatchState) {
1386+
private void createHandleExceptionTarget(FixedWithNextNode afterExceptionLoaded, int bci, FrameStateBuilder dispatchState) {
13781387
FixedWithNextNode afterInstrumentation = afterExceptionLoaded;
13791388
for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
13801389
afterInstrumentation = plugin.instrumentExceptionDispatch(graph, afterInstrumentation, () -> dispatchState.create(bci, getNonIntrinsicAncestor(), false, null, null));
13811390
assert afterInstrumentation.next() == null : "exception dispatch instrumentation will be linked to dispatch block";
13821391
}
13831392

1393+
BciBlock dispatchBlock = getDispatchBlock(bci);
1394+
1395+
FixedNode target = createTarget(dispatchBlock, dispatchState);
1396+
afterInstrumentation.setNext(target);
1397+
}
1398+
1399+
protected BciBlock getDispatchBlock(int bci) {
13841400
BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock();
13851401
/*
13861402
* The exception dispatch block is always for the last bytecode of a block, so if we are not
@@ -1391,8 +1407,7 @@ protected void createHandleExceptionTarget(FixedWithNextNode afterExceptionLoade
13911407
dispatchBlock = blockMap.getUnwindBlock();
13921408
}
13931409

1394-
FixedNode target = createTarget(dispatchBlock, dispatchState);
1395-
afterInstrumentation.setNext(target);
1410+
return dispatchBlock;
13961411
}
13971412

13981413
protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind kind) {

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/java/FrameStateBuilder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,9 @@ public boolean contains(ValueNode value) {
729729
return false;
730730
}
731731

732+
/**
733+
* @param liveIn true if live in, false if live out
734+
*/
732735
public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) {
733736
/*
734737
* Non-live local clearing is mandatory for the entry block of an OSR compilation so that

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/nodes/GraphDecoder.java

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import org.graalvm.compiler.nodes.spi.Canonicalizable;
7575
import org.graalvm.compiler.nodes.spi.CanonicalizerTool;
7676
import org.graalvm.compiler.options.OptionValues;
77+
import org.graalvm.compiler.replacements.nodes.MethodHandleWithExceptionNode;
7778

7879
import jdk.vm.ci.code.Architecture;
7980
import jdk.vm.ci.meta.Assumptions;
@@ -446,31 +447,21 @@ public int hashCode() {
446447
}
447448
}
448449

449-
/**
450-
* Additional information encoded for {@link Invoke} nodes to allow method inlining without
451-
* decoding the frame state and successors beforehand.
452-
*/
453-
protected static class InvokeData {
454-
public final Invoke invoke;
450+
protected static class InvokableData<T extends Invokable> {
451+
public final T invoke;
455452
public final ResolvedJavaType contextType;
456-
public final int invokeOrderId;
457-
public final int callTargetOrderId;
453+
public final int orderId;
458454
public final int stateAfterOrderId;
459455
public final int nextOrderId;
460-
461456
public final int exceptionOrderId;
462457
public final int exceptionStateOrderId;
463458
public final int exceptionNextOrderId;
464-
public JavaConstant constantReceiver;
465-
public CallTargetNode callTarget;
466-
public FixedWithNextNode invokePredecessor;
467459

468-
protected InvokeData(Invoke invoke, ResolvedJavaType contextType, int invokeOrderId, int callTargetOrderId, int stateAfterOrderId, int nextOrderId,
460+
protected InvokableData(T invoke, ResolvedJavaType contextType, int orderId, int stateAfterOrderId, int nextOrderId,
469461
int exceptionOrderId, int exceptionStateOrderId, int exceptionNextOrderId) {
470462
this.invoke = invoke;
471463
this.contextType = contextType;
472-
this.invokeOrderId = invokeOrderId;
473-
this.callTargetOrderId = callTargetOrderId;
464+
this.orderId = orderId;
474465
this.stateAfterOrderId = stateAfterOrderId;
475466
this.nextOrderId = nextOrderId;
476467
this.exceptionOrderId = exceptionOrderId;
@@ -479,6 +470,31 @@ protected InvokeData(Invoke invoke, ResolvedJavaType contextType, int invokeOrde
479470
}
480471
}
481472

473+
/**
474+
* Additional information encoded for {@link Invoke} nodes to allow method inlining without
475+
* decoding the frame state and successors beforehand.
476+
*/
477+
protected static class InvokeData extends InvokableData<Invoke> {
478+
static InvokeData createFrom(InvokableData<? extends Invoke> from, int callTargetOrderId, boolean intrinsifiedMethodHandle) {
479+
return new InvokeData(from.invoke, from.contextType, from.orderId, callTargetOrderId, intrinsifiedMethodHandle,
480+
from.stateAfterOrderId, from.nextOrderId, from.exceptionOrderId, from.exceptionStateOrderId, from.exceptionNextOrderId);
481+
}
482+
483+
public final int callTargetOrderId;
484+
public final boolean intrinsifiedMethodHandle;
485+
486+
public JavaConstant constantReceiver;
487+
public CallTargetNode callTarget;
488+
public FixedWithNextNode invokePredecessor;
489+
490+
public InvokeData(Invoke invoke, ResolvedJavaType contextType, int invokeOrderId, int callTargetOrderId, boolean intrinsifiedMethodHandle,
491+
int stateAfterOrderId, int nextOrderId, int exceptionOrderId, int exceptionStateOrderId, int exceptionNextOrderId) {
492+
super(invoke, contextType, invokeOrderId, stateAfterOrderId, nextOrderId, exceptionOrderId, exceptionStateOrderId, exceptionNextOrderId);
493+
this.callTargetOrderId = callTargetOrderId;
494+
this.intrinsifiedMethodHandle = intrinsifiedMethodHandle;
495+
}
496+
}
497+
482498
/**
483499
* A node that is created during {@link LoopExplosionKind#MERGE_EXPLODE loop explosion} that can
484500
* later be replaced by a ProxyNode if {@link LoopDetector loop detection} finds out that the
@@ -903,6 +919,9 @@ protected LoopScope processNextNode(MethodScope methodScope, LoopScope loopScope
903919
} else if (node instanceof Invoke) {
904920
InvokeData invokeData = readInvokeData(methodScope, nodeOrderId, (Invoke) node);
905921
resultScope = handleInvoke(methodScope, loopScope, invokeData);
922+
} else if (node instanceof MethodHandleWithExceptionNode methodHandle) {
923+
InvokableData<MethodHandleWithExceptionNode> invokableData = readInvokableData(methodScope, nodeOrderId, methodHandle);
924+
resultScope = handleMethodHandle(methodScope, loopScope, invokableData);
906925
} else if (node instanceof ReturnNode || node instanceof UnwindNode) {
907926
methodScope.returnAndUnwindNodes.add((ControlSinkNode) node);
908927
} else {
@@ -923,23 +942,32 @@ protected LoopScope processNextNode(MethodScope methodScope, LoopScope loopScope
923942
}
924943
}
925944

926-
protected InvokeData readInvokeData(MethodScope methodScope, int invokeOrderId, Invoke invoke) {
945+
protected LoopScope handleMethodHandle(MethodScope methodScope, LoopScope loopScope, InvokableData<MethodHandleWithExceptionNode> invokableData) {
946+
appendInvokable(methodScope, loopScope, invokableData);
947+
return loopScope;
948+
}
949+
950+
protected <T extends Invokable> InvokableData<T> readInvokableData(MethodScope methodScope, int orderId, T node) {
927951
ResolvedJavaType contextType = (ResolvedJavaType) readObject(methodScope);
928-
int callTargetOrderId = readOrderId(methodScope);
929952
int stateAfterOrderId = readOrderId(methodScope);
930953
int nextOrderId = readOrderId(methodScope);
931954

932-
if (invoke instanceof InvokeWithExceptionNode) {
955+
if (node instanceof WithExceptionNode) {
933956
int exceptionOrderId = readOrderId(methodScope);
934957
int exceptionStateOrderId = readOrderId(methodScope);
935958
int exceptionNextOrderId = readOrderId(methodScope);
936-
return new InvokeData(invoke, contextType, invokeOrderId, callTargetOrderId, stateAfterOrderId, nextOrderId, exceptionOrderId, exceptionStateOrderId,
937-
exceptionNextOrderId);
959+
return new InvokableData<>(node, contextType, orderId, stateAfterOrderId, nextOrderId, exceptionOrderId, exceptionStateOrderId, exceptionNextOrderId);
938960
} else {
939-
return new InvokeData(invoke, contextType, invokeOrderId, callTargetOrderId, stateAfterOrderId, nextOrderId, -1, -1, -1);
961+
return new InvokableData<>(node, contextType, orderId, stateAfterOrderId, nextOrderId, -1, -1, -1);
940962
}
941963
}
942964

965+
protected InvokeData readInvokeData(MethodScope methodScope, int invokeOrderId, Invoke invoke) {
966+
int callTargetOrderId = readOrderId(methodScope);
967+
InvokableData<Invoke> invokableData = readInvokableData(methodScope, invokeOrderId, invoke);
968+
return InvokeData.createFrom(invokableData, callTargetOrderId, false);
969+
}
970+
943971
/**
944972
* {@link Invoke} nodes do not have the {@link CallTargetNode}, {@link FrameState}, and
945973
* successors encoded. Instead, this information is provided separately to allow method inlining
@@ -963,15 +991,21 @@ protected void appendInvoke(MethodScope methodScope, LoopScope loopScope, Invoke
963991
} else {
964992
((InvokeNode) invokeData.invoke).setCallTarget(callTarget);
965993
}
994+
appendInvokable(methodScope, loopScope, invokeData);
995+
}
966996

997+
private <T extends Invokable & StateSplit> void appendInvokable(MethodScope methodScope, LoopScope loopScope, InvokableData<T> invokeData) {
967998
if (invokeData.invoke.stateAfter() == null) {
968999
invokeData.invoke.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId));
9691000
}
970-
assert invokeData.invoke.stateDuring() == null : "stateDuring is not used in high tier graphs";
1001+
assert !(invokeData.invoke instanceof Invoke inv && inv.stateDuring() != null) : "stateDuring is not used in high tier graphs";
9711002

972-
invokeData.invoke.setNext(makeStubNode(methodScope, loopScope, invokeData.nextOrderId));
973-
if (invokeData.invoke instanceof InvokeWithExceptionNode) {
974-
((InvokeWithExceptionNode) invokeData.invoke).setExceptionEdge((AbstractBeginNode) makeStubNode(methodScope, loopScope, invokeData.exceptionOrderId));
1003+
FixedNode next = makeStubNode(methodScope, loopScope, invokeData.nextOrderId);
1004+
if (invokeData.invoke instanceof WithExceptionNode withException) {
1005+
withException.setNext((AbstractBeginNode) next);
1006+
withException.setExceptionEdge((AbstractBeginNode) makeStubNode(methodScope, loopScope, invokeData.exceptionOrderId));
1007+
} else {
1008+
((FixedWithNextNode) invokeData.invoke).setNext(next);
9751009
}
9761010
}
9771011

@@ -1705,18 +1739,17 @@ protected FixedNode makeStubNode(MethodScope methodScope, LoopScope loopScope, i
17051739
}
17061740

17071741
protected static boolean skipDirectEdge(Node node, Edges edges, int index) {
1708-
if (node instanceof Invoke) {
1709-
assert node instanceof InvokeNode || node instanceof InvokeWithExceptionNode : "The only two Invoke node classes. Got " + node.getClass();
1742+
if (node instanceof Invoke || node instanceof MethodHandleWithExceptionNode) {
1743+
assert node instanceof InvokeNode || node instanceof InvokeWithExceptionNode || node instanceof MethodHandleWithExceptionNode : "The only supported node classes. Got " + node.getClass();
17101744
if (edges.type() == Edges.Type.Successors) {
1711-
assert edges.getCount() == (node instanceof InvokeWithExceptionNode ? 2
1712-
: 1) : "InvokeNode has one successor (next); InvokeWithExceptionNode has two successors (next, exceptionEdge)";
1745+
assert edges.getCount() == (node instanceof WithExceptionNode ? 2 : 1) : "Base Invokable has one successor (next); WithExceptionNode has two successors (next, exceptionEdge)";
17131746
return true;
17141747
} else {
17151748
assert edges.type() == Edges.Type.Inputs;
17161749
if (edges.getType(index) == CallTargetNode.class) {
17171750
return true;
17181751
} else if (edges.getType(index) == FrameState.class) {
1719-
assert edges.get(node, index) == null || edges.get(node, index) == ((Invoke) node).stateAfter() : "Only stateAfter can be a FrameState during encoding";
1752+
assert edges.get(node, index) == null || edges.get(node, index) == ((StateSplit) node).stateAfter() : "Only stateAfter can be a FrameState during encoding";
17201753
return true;
17211754
}
17221755
}

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/nodes/GraphEncoder.java

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.graalvm.compiler.graph.iterators.NodeIterable;
4848
import org.graalvm.compiler.nodes.EncodedGraph.EncodedNodeReference;
4949
import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
50+
import org.graalvm.compiler.replacements.nodes.MethodHandleWithExceptionNode;
5051

5152
import jdk.vm.ci.code.Architecture;
5253

@@ -216,8 +217,8 @@ public void prepare(StructuredGraph graph) {
216217
addObject(nodeClass.getData().get(node, i));
217218
}
218219
}
219-
if (node instanceof Invoke) {
220-
addObject(((Invoke) node).getContextType());
220+
if (node instanceof Invoke || node instanceof MethodHandleWithExceptionNode) {
221+
addObject(((Invokable) node).getContextType());
221222
}
222223
}
223224
}
@@ -313,19 +314,24 @@ protected int encode(StructuredGraph graph, Iterable<EncodedNodeReference> nodeR
313314
writeOrderId(proxy, nodeOrder);
314315
}
315316

316-
} else if (node instanceof Invoke) {
317-
Invoke invoke = (Invoke) node;
318-
assert invoke.stateDuring() == null : "stateDuring is not used in high-level graphs";
317+
} else if (node instanceof Invoke || node instanceof MethodHandleWithExceptionNode) {
318+
Node next;
319+
if (node instanceof Invoke invoke) {
320+
assert invoke.stateDuring() == null : "stateDuring is not used in high-level graphs";
321+
writeOrderId(invoke.callTarget(), nodeOrder);
322+
next = invoke.next();
323+
} else {
324+
next = ((MethodHandleWithExceptionNode) node).next();
325+
}
319326

320-
writeObjectId(invoke.getContextType());
321-
writeOrderId(invoke.callTarget(), nodeOrder);
322-
writeOrderId(invoke.stateAfter(), nodeOrder);
323-
writeOrderId(invoke.next(), nodeOrder);
324-
if (invoke instanceof InvokeWithExceptionNode) {
325-
InvokeWithExceptionNode invokeWithExcpetion = (InvokeWithExceptionNode) invoke;
326-
ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithExcpetion.exceptionEdge();
327+
Invokable inv = (Invokable) node;
328+
writeObjectId(inv.getContextType());
329+
writeOrderId(((StateSplit) inv).stateAfter(), nodeOrder);
330+
writeOrderId(next, nodeOrder);
331+
if (inv instanceof WithExceptionNode withException) {
332+
ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) withException.exceptionEdge();
327333

328-
writeOrderId(invokeWithExcpetion.exceptionEdge(), nodeOrder);
334+
writeOrderId(withException.exceptionEdge(), nodeOrder);
329335
writeOrderId(exceptionEdge.stateAfter(), nodeOrder);
330336
writeOrderId(exceptionEdge.next(), nodeOrder);
331337
}

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/nodes/Invokable.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.graalvm.compiler.graph.Node;
2929

3030
import jdk.vm.ci.meta.ResolvedJavaMethod;
31+
import jdk.vm.ci.meta.ResolvedJavaType;
3132

3233
/**
3334
* A marker interface for nodes that represent calls to other methods.
@@ -42,6 +43,20 @@ public interface Invokable extends DeoptBciSupplier {
4243
*/
4344
ResolvedJavaMethod getContextMethod();
4445

46+
/**
47+
* Returns the {@linkplain ResolvedJavaType type} from which this invoke is executed. This is
48+
* the declaring type of the caller method.
49+
*
50+
* @return the type from which this invoke is executed.
51+
*/
52+
default ResolvedJavaType getContextType() {
53+
ResolvedJavaMethod contextMethod = getContextMethod();
54+
if (contextMethod == null) {
55+
return null;
56+
}
57+
return contextMethod.getDeclaringClass();
58+
}
59+
4560
/**
4661
* Returns the receiver cast to {@link FixedNode}, or null if this invokable is a placeholder.
4762
*/

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/nodes/Invoke.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,20 +110,6 @@ default ResolvedJavaMethod getContextMethod() {
110110
return state.getMethod();
111111
}
112112

113-
/**
114-
* Returns the {@linkplain ResolvedJavaType type} from which this invoke is executed. This is
115-
* the declaring type of the caller method.
116-
*
117-
* @return the type from which this invoke is executed.
118-
*/
119-
default ResolvedJavaType getContextType() {
120-
ResolvedJavaMethod contextMethod = getContextMethod();
121-
if (contextMethod == null) {
122-
return null;
123-
}
124-
return contextMethod.getDeclaringClass();
125-
}
126-
127113
@Override
128114
default void computeStateDuring(FrameState stateAfter) {
129115
FrameState newStateDuring = stateAfter.duplicateModifiedDuringCall(bci(), asNode().getStackKind());

0 commit comments

Comments
 (0)