5151import org .graalvm .compiler .nodes .ControlSinkNode ;
5252import org .graalvm .compiler .nodes .ControlSplitNode ;
5353import org .graalvm .compiler .nodes .EndNode ;
54+ import org .graalvm .compiler .nodes .FixedNode ;
5455import org .graalvm .compiler .nodes .IfNode ;
5556import org .graalvm .compiler .nodes .InvokeWithExceptionNode ;
5657import org .graalvm .compiler .nodes .LoopBeginNode ;
@@ -77,9 +78,12 @@ public class StackifierIRWalker extends IRWalker {
7778 public static final String LABEL_PREFIX = "looplabel_" ;
7879 protected final BlockNestingVerifier blockNestingVerifier ;
7980
81+ protected final StackifierData stackifierData ;
82+
8083 public StackifierIRWalker (CodeGenTool codeGenTool , ControlFlowGraph cfg , BlockMap <List <Node >> blockToNodeMap , NodeMap <HIRBlock > nodeToBlockMap , ReconstructionData reconstructionData ) {
8184 super (codeGenTool , cfg , blockToNodeMap , nodeToBlockMap , reconstructionData );
8285 this .blockNestingVerifier = new BlockNestingVerifier ();
86+ this .stackifierData = (StackifierData ) reconstructionData ;
8387 }
8488
8589 /**
@@ -155,7 +159,7 @@ public StackifierIRWalker(CodeGenTool codeGenTool, ControlFlowGraph cfg, BlockMa
155159 * via {@code continue} statements. As a side note, the end of a loop has an implicit back-edge.
156160 * Since all back-edges are handled via {@link LoopEndNode} and the corresponding
157161 * {@code continue} statement we place a {@code break} at the end of the loop to avoid this
158- * backwards jump, see {@link #lowerLoopStackifier(StackifierData, HIRBlock)}.
162+ * backwards jump, see {@link #lowerLoop( HIRBlock)}.
159163 *
160164 * Now an example where we assume {@code A()} might produce an exception
161165 *
@@ -193,7 +197,6 @@ public StackifierIRWalker(CodeGenTool codeGenTool, ControlFlowGraph cfg, BlockMa
193197 @ Override
194198 @ SuppressWarnings ({"unused" , "try" })
195199 protected void lower (DebugContext debugContext ) {
196- StackifierData stackifierData = (StackifierData ) reconstructionData ;
197200 stackifierData .debugDump (debugContext );
198201
199202 predeclareVariables (cfg .graph );
@@ -221,9 +224,7 @@ protected void predeclareVariables(StructuredGraph graph) {
221224 *
222225 * @param blocks blocks to be lowered
223226 */
224- @ SuppressWarnings ("deprecated" )
225- private void lowerBlocks (HIRBlock [] blocks ) {
226- StackifierData stackifierData = (StackifierData ) reconstructionData ;
227+ protected void lowerBlocks (HIRBlock [] blocks ) {
227228 for (HIRBlock currentBlock : blocks ) {
228229 if (blockHistory .blockVisited (currentBlock )) {
229230 continue ;
@@ -255,15 +256,18 @@ private void lowerBlocks(HIRBlock[] blocks) {
255256 }
256257 }
257258
258- LabeledBlock blockEnd = stackifierData .labeledBlockEnd (currentBlock );
259-
260259 /*
261260 * Generate the end of the labeled block before a possible loop header as well as all
262261 * labeled blocks that need to start before the loop header.
263262 */
264263 if (!isInRecursiveLoopCall (isLoopHeader , currentBlock , blocks )) {
265264 // generate end of forward blocks
266- genLabeledBlockEnd (blockEnd );
265+ LabeledBlock blockEnd = stackifierData .labeledBlockEnd (currentBlock );
266+ if (blockEnd != null ) {
267+ genLabeledBlockEnd (blockEnd );
268+ }
269+
270+ // Open labeled blocks before loop header
267271 labeledBlockStartsBeforeLoop .forEach (this ::genLabeledBlockHeader );
268272 }
269273
@@ -273,12 +277,13 @@ private void lowerBlocks(HIRBlock[] blocks) {
273277 * first basic block. If it does, we are already in that recursive call.
274278 */
275279 if (newLoopStartsHere (isLoopHeader , currentBlock , blocks )) {
276- lowerLoopStackifier ( stackifierData , currentBlock );
280+ lowerLoop ( currentBlock );
277281 continue ;
278282 }
279283
280284 codeGenTool .genComment ("Start of block " + currentBlock );
281285
286+ // Open labeled blocks after loop header
282287 labeledBlockStartsAfterLoop .forEach (this ::genLabeledBlockHeader );
283288
284289 for (Node node : blockToNodeMap .get (currentBlock )) {
@@ -287,8 +292,8 @@ private void lowerBlocks(HIRBlock[] blocks) {
287292 } else if (node instanceof LoopBeginNode ) {
288293 /*
289294 * We should only be able to visit a LoopBeginNode if we are recursively called
290- * from lowerLoopStackifier and as such the node can be ignored since
291- * lowerLoopStackifier already emitted the loop header.
295+ * from lowerLoop and as such the node can be ignored since lowerLoop already
296+ * emitted the loop header.
292297 */
293298 assert currentBlock == blocks [0 ];
294299 } else if (!(node instanceof LoopExitNode )) {
@@ -298,35 +303,24 @@ private void lowerBlocks(HIRBlock[] blocks) {
298303 verifier .visitNode (node , codeGenTool );
299304 }
300305
301- Node lastNode = currentBlock .getEndNode ();
306+ FixedNode lastNode = currentBlock .getEndNode ();
302307 if (lastNode instanceof ControlSinkNode ) {
303308 lowerNode (lastNode );
304- } else if (lastNode instanceof IfNode ) {
305- lowerIfStackifier (currentBlock , ( IfNode ) lastNode );
306- } else if (lastNode instanceof IntegerSwitchNode ) {
307- lowerSwitch (( IntegerSwitchNode ) lastNode , stackifierData );
308- } else if (lastNode instanceof TypeSwitchNode ) {
309- lowerTypeSwitch (( TypeSwitchNode ) lastNode , stackifierData );
309+ } else if (lastNode instanceof IfNode ifNode ) {
310+ lowerIf (currentBlock , ifNode );
311+ } else if (lastNode instanceof IntegerSwitchNode switchNode ) {
312+ lowerSwitch (switchNode );
313+ } else if (lastNode instanceof TypeSwitchNode switchNode ) {
314+ lowerTypeSwitch (switchNode );
310315 } else if (isWithExceptionNode (lastNode )) {
311- lowerWithExceptionStackifier (currentBlock , (WithExceptionNode ) lastNode );
316+ lowerWithException (currentBlock , (WithExceptionNode ) lastNode );
312317 } else if ((lastNode instanceof ControlSplitNode ) && !(lastNode instanceof BasicArrayCopyNode )) {
313318 // BasicArrayCopyNode is also a ControlSplitNode
314319 assert false : "Unsupported control split node " + lastNode + " is not implemented yet" ;
315- } else if (lastNode instanceof LoopEndNode ) {
316- lowerLoopEndResolver ((LoopEndNode ) lastNode );
317- codeGenTool .genLoopContinue ();
320+ } else if (lastNode instanceof LoopEndNode loopEnd ) {
321+ lowerLoopEnd (loopEnd );
318322 } else {
319- if (!(lastNode instanceof LoopExitNode ) && !(lastNode instanceof LoopBeginNode )) {
320- /*
321- * Special case for basic blocks with only one node. LoopExitNode and
322- * LoopBeginNode need to be handled separately again, as they must not be
323- * lowered by the node lowerer.
324- */
325- lowerNode (lastNode );
326- }
327- HIRBlock successor = nodeToBlockMap .get (lastNode .cfgSuccessors ().iterator ().next ());
328- generateForwardJump (currentBlock , successor , stackifierData );
329-
323+ lowerUnhandledBlockEnd (currentBlock , lastNode );
330324 }
331325
332326 verifier .visitNode (lastNode , codeGenTool );
@@ -337,8 +331,7 @@ private void lowerBlocks(HIRBlock[] blocks) {
337331
338332 /**
339333 * Whether the lowering of the given currentBlock happens inside a recursive call from
340- * {@link #lowerLoopStackifier(StackifierData, HIRBlock)} and the current block is the start of
341- * the loop.
334+ * {@link #lowerLoop(HIRBlock)} and the current block is the start of the loop.
342335 *
343336 * If this is true, the loop header was already emitted otherwise it hasn't.
344337 */
@@ -359,9 +352,8 @@ protected boolean isWithExceptionNode(Node lastNode) {
359352 *
360353 * @param currentBlock block from which to jump from
361354 * @param successor target of the jump
362- * @param stackifierData stackifier data
363355 */
364- private void generateForwardJump (HIRBlock currentBlock , HIRBlock successor , StackifierData stackifierData ) {
356+ private void generateForwardJump (HIRBlock currentBlock , HIRBlock successor ) {
365357 if (LabeledBlockGeneration .isNormalLoopExit (currentBlock , successor , stackifierData )) {
366358 Loop <HIRBlock > loop = currentBlock .getLoop ();
367359 Scope loopScope = ((LoopScopeContainer ) stackifierData .getScopeEntry (loop .getHeader ().getBeginNode ())).getLoopScope ();
@@ -428,11 +420,10 @@ private void generateForwardJump(HIRBlock currentBlock, HIRBlock successor, Stac
428420 * we want is to go to {@code C()}. Therefore a {@code break} is inserted at the loop end which
429421 * makes the back-edge at the end of the loop unreachable and adds a loop exit.
430422 *
431- * @param stackifierData data generated by the stackifier reconstruction algorithm
432423 * @param currentBlock current block
433424 */
434- private void lowerLoopStackifier ( StackifierData stackifierData , HIRBlock currentBlock ) {
435- assert currentBlock .getBeginNode () instanceof LoopBeginNode ;
425+ protected void lowerLoop ( HIRBlock currentBlock ) {
426+ assert currentBlock .isLoopHeader () ;
436427 LoopScopeContainer loopScopeEntry = (LoopScopeContainer ) stackifierData .getScopeEntry (currentBlock .getBeginNode ());
437428 Scope loopScope = loopScopeEntry .getLoopScope ();
438429
@@ -442,15 +433,19 @@ private void lowerLoopStackifier(StackifierData stackifierData, HIRBlock current
442433 genLoopEnd (currentBlock );
443434 }
444435
436+ protected void lowerLoopEnd (LoopEndNode loopEnd ) {
437+ lowerLoopEndResolver (loopEnd );
438+ codeGenTool .genLoopContinue ();
439+ }
440+
445441 /**
446442 * Lower a WithExceptionNode. For an example how the generated code looks like, see
447443 * {@link #lower(DebugContext)}.
448444 *
449445 * @param currentBlock basic block that contains {@link WithExceptionNode}
450446 * @param lastNode the {@link WithExceptionNode}
451447 */
452- private void lowerWithExceptionStackifier (HIRBlock currentBlock , WithExceptionNode lastNode ) {
453- StackifierData stackifierData = (StackifierData ) reconstructionData ;
448+ protected void lowerWithException (HIRBlock currentBlock , WithExceptionNode lastNode ) {
454449 HIRBlock normSucc = cfg .blockFor (lastNode .next ());
455450 HIRBlock excpSucc = cfg .blockFor (lastNode .exceptionEdge ());
456451 CatchScopeContainer scopeEntry = (CatchScopeContainer ) stackifierData .getScopeEntry (lastNode );
@@ -463,7 +458,7 @@ private void lowerWithExceptionStackifier(HIRBlock currentBlock, WithExceptionNo
463458 * once it is encountered in its own basic block.
464459 */
465460 lowerNode (lastNode );
466- generateForwardJump (currentBlock , normSucc , stackifierData );
461+ generateForwardJump (currentBlock , normSucc );
467462
468463 String caughtObjectName = codeGenTool .getExceptionObjectId (excpSucc .getBeginNode ());
469464 ResolvedJavaType caughtObjectType = codeGenTool .getProviders ().getMetaAccess ().lookupJavaType (Throwable .class );
@@ -473,15 +468,15 @@ private void lowerWithExceptionStackifier(HIRBlock currentBlock, WithExceptionNo
473468 * the caught object is set to Throwable, and only changed if the exception edge indeed is
474469 * an ExceptionObjectNode
475470 */
476- if (excpSucc .getBeginNode ()instanceof ExceptionObjectNode excpObj ) {
471+ if (excpSucc .getBeginNode () instanceof ExceptionObjectNode excpObj ) {
477472 caughtObjectType = excpObj .stamp (NodeView .DEFAULT ).javaType (codeGenTool .getProviders ().getMetaAccess ());
478473 }
479474 codeGenTool .genCatchBlockPrefix (caughtObjectName , caughtObjectType );
480475
481476 if (catchScope != null ) {
482477 lowerBlocks (catchScope .getSortedBlocks ());
483478 } else {
484- generateForwardJump (currentBlock , excpSucc , stackifierData );
479+ generateForwardJump (currentBlock , excpSucc );
485480 }
486481 codeGenTool .genScopeEnd ();
487482 }
@@ -497,28 +492,46 @@ protected void lowerIfHeader(IfNode ifNode) {
497492 * @param currentBlock basic block containing the {@link IfNode}
498493 * @param lastNode the {@link IfNode}
499494 */
500- private void lowerIfStackifier (HIRBlock currentBlock , IfNode lastNode ) {
501- StackifierData stackifierData = (StackifierData ) reconstructionData ;
502- HIRBlock trueBlock = nodeToBlockMap .get (lastNode .trueSuccessor ());
503- HIRBlock falseBlock = nodeToBlockMap .get (lastNode .falseSuccessor ());
495+ protected void lowerIf (HIRBlock currentBlock , IfNode lastNode ) {
504496 IfScopeContainer ifScopeContainer = (IfScopeContainer ) stackifierData .getScopeEntry (lastNode );
505497 Scope thenScope = ifScopeContainer .getThenScope ();
506498 Scope elseScope = ifScopeContainer .getElseScope ();
507499 lowerIfHeader (lastNode );
508500 if (thenScope != null ) {
509501 lowerBlocks (thenScope .getSortedBlocks ());
510502 } else {
511- generateForwardJump (currentBlock , trueBlock , stackifierData );
503+ HIRBlock trueBlock = nodeToBlockMap .get (lastNode .trueSuccessor ());
504+ generateForwardJump (currentBlock , trueBlock );
512505 }
513506 codeGenTool .genElseHeader ();
514507 if (elseScope != null ) {
515508 lowerBlocks (elseScope .getSortedBlocks ());
516509 } else {
517- generateForwardJump (currentBlock , falseBlock , stackifierData );
510+ HIRBlock falseBlock = nodeToBlockMap .get (lastNode .falseSuccessor ());
511+ generateForwardJump (currentBlock , falseBlock );
518512 }
519513 codeGenTool .genScopeEnd ();
520514 }
521515
516+ /**
517+ * Lowers the end of an HIR block (including the last node) in case the last node is not a
518+ * control-flow node.
519+ * <p>
520+ * Also generates a potential forward jump to the next basic block in the control-flow-graph.
521+ */
522+ protected void lowerUnhandledBlockEnd (HIRBlock currentBlock , FixedNode lastNode ) {
523+ if (!(lastNode instanceof LoopExitNode ) && !(lastNode instanceof LoopBeginNode )) {
524+ /*
525+ * Special case for basic blocks with only one node. LoopExitNode and LoopBeginNode need
526+ * to be handled separately again, as they must not be lowered by the node lowerer.
527+ */
528+ lowerNode (lastNode );
529+ }
530+
531+ HIRBlock successor = nodeToBlockMap .get (lastNode .cfgSuccessors ().iterator ().next ());
532+ generateForwardJump (currentBlock , successor );
533+ }
534+
522535 /**
523536 * Determine whether a given {@link LabeledBlock} that starts at the same block as a loop starts
524537 * ends inside the loop or outside of it.
@@ -618,9 +631,8 @@ protected void lowerSwitchDefaultCase(IntegerSwitchNode switchNode) {
618631 * blocks.
619632 *
620633 * @param switchNode node to be lowered
621- * @param stackifierData data for forward jumps
622634 */
623- public void lowerSwitch (IntegerSwitchNode switchNode , StackifierData stackifierData ) {
635+ protected void lowerSwitch (IntegerSwitchNode switchNode ) {
624636
625637 codeGenTool .genSwitchHeader (switchNode .value ());
626638
@@ -658,7 +670,7 @@ public void lowerSwitch(IntegerSwitchNode switchNode, StackifierData stackifierD
658670 if (caseScopes [i ] != null ) {
659671 lowerBlocks (caseScopes [i ].getSortedBlocks ());
660672 } else {
661- generateForwardJump (cfg .blockFor (switchNode ), cfg .blockFor (succ ), stackifierData );
673+ generateForwardJump (cfg .blockFor (switchNode ), cfg .blockFor (succ ));
662674 }
663675 codeGenTool .genBlockEndBreak ();
664676 codeGenTool .genScopeEnd ();
@@ -669,7 +681,7 @@ public void lowerSwitch(IntegerSwitchNode switchNode, StackifierData stackifierD
669681 if (caseScopes [defaultIndex ] != null ) {
670682 lowerBlocks (caseScopes [defaultIndex ].getSortedBlocks ());
671683 } else {
672- generateForwardJump (cfg .blockFor (switchNode ), cfg .blockFor (switchNode .defaultSuccessor ()), stackifierData );
684+ generateForwardJump (cfg .blockFor (switchNode ), cfg .blockFor (switchNode .defaultSuccessor ()));
673685 }
674686 codeGenTool .genBlockEndBreak ();
675687 codeGenTool .genScopeEnd ();
@@ -764,9 +776,8 @@ protected void lowerTypeSwitchDefaultCase(TypeSwitchNode switchNode) {
764776 * blocks.
765777 *
766778 * @param switchNode node to be lowered
767- * @param stackifierData data for forward jumps
768779 */
769- public void lowerTypeSwitch (TypeSwitchNode switchNode , StackifierData stackifierData ) {
780+ protected void lowerTypeSwitch (TypeSwitchNode switchNode ) {
770781 boolean hasdefault = switchNode .defaultSuccessor () != null ;
771782 for (int i = 0 ; i < switchNode .blockSuccessorCount (); i ++) {
772783 // one successor
@@ -788,29 +799,27 @@ public void lowerTypeSwitch(TypeSwitchNode switchNode, StackifierData stackifier
788799 }
789800 assert succKeys .size () > 0 : "no keys of " + switchNode + " have " + succ + " as block successor" ;
790801 lowerTypeSwitchCase (switchNode , succ , i , succKeys );
791- generateForwardJump (cfg .blockFor (switchNode ), cfg .blockFor (succ ), stackifierData );
802+ generateForwardJump (cfg .blockFor (switchNode ), cfg .blockFor (succ ));
792803 codeGenTool .genBlockEndBreak ();
793804 codeGenTool .genScopeEnd ();
794805 }
795806 if (hasdefault ) {
796807 lowerTypeSwitchDefaultCase (switchNode );
797- generateForwardJump (cfg .blockFor (switchNode ), cfg .blockFor (switchNode .defaultSuccessor ()), stackifierData );
808+ generateForwardJump (cfg .blockFor (switchNode ), cfg .blockFor (switchNode .defaultSuccessor ()));
798809 codeGenTool .genBlockEndBreak ();
799810 codeGenTool .genScopeEnd ();
800811 }
801812 }
802813
803- private void genLabeledBlockHeader (LabeledBlock labeledBlock ) {
814+ protected void genLabeledBlockHeader (LabeledBlock labeledBlock ) {
804815 blockNestingVerifier .pushLabel (labeledBlock );
805816 codeGenTool .genLabeledBlockHeader (labeledBlock .getLabel ());
806817 }
807818
808- private void genLabeledBlockEnd (LabeledBlock blockEnd ) {
809- if (blockEnd != null ) {
810- blockNestingVerifier .popLabel (blockEnd );
811- codeGenTool .genScopeEnd ();
812- codeGenTool .genComment ("End of LabeledBlock " + blockEnd .getLabel ());
813- }
819+ protected void genLabeledBlockEnd (LabeledBlock blockEnd ) {
820+ blockNestingVerifier .popLabel (blockEnd );
821+ codeGenTool .genScopeEnd ();
822+ codeGenTool .genComment ("End of LabeledBlock " + blockEnd .getLabel ());
814823 }
815824
816825 private void genLoopHeader (HIRBlock block ) {
0 commit comments