7474import org .graalvm .compiler .nodes .spi .Canonicalizable ;
7575import org .graalvm .compiler .nodes .spi .CanonicalizerTool ;
7676import org .graalvm .compiler .options .OptionValues ;
77+ import org .graalvm .compiler .replacements .nodes .MethodHandleWithExceptionNode ;
7778
7879import jdk .vm .ci .code .Architecture ;
7980import 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 }
0 commit comments