@@ -476,12 +476,14 @@ private static void fillKillSet(LocationSet killed, List<Node> subList) {
476
476
477
477
private static void sortNodesLatestWithinBlock (ControlFlowGraph cfg , BlockMap <List <Node >> earliestBlockToNodesMap , BlockMap <List <Node >> latestBlockToNodesMap , NodeMap <HIRBlock > currentNodeMap ,
478
478
BlockMap <ArrayList <FloatingReadNode >> watchListMap , NodeBitMap visited , boolean supportsImplicitNullChecks ) {
479
+ NodeStack nodeStack = new NodeStack ();
479
480
for (HIRBlock b : cfg .getBlocks ()) {
480
- sortNodesLatestWithinBlock (b , earliestBlockToNodesMap , latestBlockToNodesMap , currentNodeMap , watchListMap , visited , supportsImplicitNullChecks );
481
+ sortNodesLatestWithinBlock (nodeStack , b , earliestBlockToNodesMap , latestBlockToNodesMap , currentNodeMap , watchListMap , visited , supportsImplicitNullChecks );
481
482
}
482
483
}
483
484
484
- private static void sortNodesLatestWithinBlock (HIRBlock b , BlockMap <List <Node >> earliestBlockToNodesMap , BlockMap <List <Node >> latestBlockToNodesMap , NodeMap <HIRBlock > nodeMap ,
485
+ private static void sortNodesLatestWithinBlock (NodeStack nodeStack , HIRBlock b , BlockMap <List <Node >> earliestBlockToNodesMap , BlockMap <List <Node >> latestBlockToNodesMap ,
486
+ NodeMap <HIRBlock > nodeMap ,
485
487
BlockMap <ArrayList <FloatingReadNode >> watchListMap , NodeBitMap unprocessed , boolean supportsImplicitNullChecks ) {
486
488
List <Node > earliestSorting = earliestBlockToNodesMap .get (b );
487
489
ArrayList <Node > result = new ArrayList <>(earliestSorting .size ());
@@ -499,7 +501,7 @@ private static void sortNodesLatestWithinBlock(HIRBlock b, BlockMap<List<Node>>
499
501
// if multiple proxies reference the same value, schedule the value of a
500
502
// proxy once
501
503
if (value != null && nodeMap .get (value ) == b && unprocessed .isMarked (value )) {
502
- sortIntoList (value , b , result , nodeMap , unprocessed , null );
504
+ sortIntoList (nodeStack , value , b , result , nodeMap , unprocessed );
503
505
}
504
506
}
505
507
}
@@ -509,18 +511,19 @@ private static void sortNodesLatestWithinBlock(HIRBlock b, BlockMap<List<Node>>
509
511
// Only if the end node is either a control split or an end node, we need to force
510
512
// it to be the last node in the schedule.
511
513
fixedEndNode = endNode ;
514
+ unprocessed .clear (fixedEndNode );
512
515
}
513
516
for (Node n : earliestSorting ) {
514
517
if (n != fixedEndNode ) {
515
518
if (n instanceof FixedNode ) {
516
519
assert nodeMap .get (n ) == b : Assertions .errorMessageContext ("n" , n , "b" , b );
517
- checkWatchList (b , nodeMap , unprocessed , result , watchList , n );
518
- sortIntoList (n , b , result , nodeMap , unprocessed , null );
520
+ checkWatchList (nodeStack , b , nodeMap , unprocessed , result , watchList , n );
521
+ sortIntoList (nodeStack , n , b , result , nodeMap , unprocessed );
519
522
} else if (nodeMap .get (n ) == b && n instanceof FloatingReadNode ) {
520
523
FloatingReadNode floatingReadNode = (FloatingReadNode ) n ;
521
524
if (isImplicitNullOpportunity (floatingReadNode , b , supportsImplicitNullChecks )) {
522
525
// Schedule at the beginning of the block.
523
- sortIntoList (floatingReadNode , b , result , nodeMap , unprocessed , null );
526
+ sortIntoList (nodeStack , floatingReadNode , b , result , nodeMap , unprocessed );
524
527
} else {
525
528
LocationIdentity location = floatingReadNode .getLocationIdentity ();
526
529
if (b .canKill (location )) {
@@ -539,38 +542,41 @@ private static void sortNodesLatestWithinBlock(HIRBlock b, BlockMap<List<Node>>
539
542
assert nodeMap .get (n ) == b : n ;
540
543
assert !(n instanceof FixedNode ) : n ;
541
544
if (unprocessed .isMarked (n )) {
542
- sortIntoList (n , b , result , nodeMap , unprocessed , fixedEndNode );
545
+ sortIntoList (nodeStack , n , b , result , nodeMap , unprocessed );
543
546
}
544
547
}
545
548
546
- if (endNode != null && unprocessed .isMarked (endNode )) {
547
- sortIntoList (endNode , b , result , nodeMap , unprocessed , null );
549
+ if (fixedEndNode != null ) {
550
+ result .add (fixedEndNode );
551
+ } else if (endNode != null && unprocessed .isMarked (endNode )) {
552
+ sortIntoList (nodeStack , endNode , b , result , nodeMap , unprocessed );
548
553
}
549
554
550
555
latestBlockToNodesMap .put (b , result );
551
556
}
552
557
553
- private static void checkWatchList (HIRBlock b , NodeMap <HIRBlock > nodeMap , NodeBitMap unprocessed , ArrayList <Node > result , ArrayList <FloatingReadNode > watchList , Node n ) {
558
+ private static void checkWatchList (NodeStack nodeStack , HIRBlock b , NodeMap <HIRBlock > nodeMap , NodeBitMap unprocessed , ArrayList <Node > result , ArrayList <FloatingReadNode > watchList , Node n ) {
554
559
if (watchList != null && !watchList .isEmpty ()) {
555
560
// Check if this node kills a node in the watch list.
556
561
if (MemoryKill .isSingleMemoryKill (n )) {
557
562
LocationIdentity identity = ((SingleMemoryKill ) n ).getKilledLocationIdentity ();
558
- checkWatchList (watchList , identity , b , result , nodeMap , unprocessed );
563
+ checkWatchList (nodeStack , watchList , identity , b , result , nodeMap , unprocessed );
559
564
} else if (MemoryKill .isMultiMemoryKill (n )) {
560
565
for (LocationIdentity identity : ((MultiMemoryKill ) n ).getKilledLocationIdentities ()) {
561
- checkWatchList (watchList , identity , b , result , nodeMap , unprocessed );
566
+ checkWatchList (nodeStack , watchList , identity , b , result , nodeMap , unprocessed );
562
567
}
563
568
}
564
569
}
565
570
}
566
571
567
- private static void checkWatchList (ArrayList <FloatingReadNode > watchList , LocationIdentity identity , HIRBlock b , ArrayList <Node > result , NodeMap <HIRBlock > nodeMap , NodeBitMap unprocessed ) {
572
+ private static void checkWatchList (NodeStack nodeStack , ArrayList <FloatingReadNode > watchList , LocationIdentity identity , HIRBlock b , ArrayList <Node > result , NodeMap <HIRBlock > nodeMap ,
573
+ NodeBitMap unprocessed ) {
568
574
if (identity .isImmutable ()) {
569
575
// Nothing to do. This can happen for an initialization write.
570
576
} else if (identity .isAny ()) {
571
577
for (FloatingReadNode r : watchList ) {
572
578
if (unprocessed .isMarked (r )) {
573
- sortIntoList (r , b , result , nodeMap , unprocessed , null );
579
+ sortIntoList (nodeStack , r , b , result , nodeMap , unprocessed );
574
580
}
575
581
}
576
582
watchList .clear ();
@@ -582,7 +588,7 @@ private static void checkWatchList(ArrayList<FloatingReadNode> watchList, Locati
582
588
assert locationIdentity .isMutable ();
583
589
if (unprocessed .isMarked (r )) {
584
590
if (identity .overlaps (locationIdentity )) {
585
- sortIntoList (r , b , result , nodeMap , unprocessed , null );
591
+ sortIntoList (nodeStack , r , b , result , nodeMap , unprocessed );
586
592
} else {
587
593
++index ;
588
594
continue ;
@@ -595,60 +601,54 @@ private static void checkWatchList(ArrayList<FloatingReadNode> watchList, Locati
595
601
}
596
602
}
597
603
598
- private static void sortIntoList (Node n , HIRBlock b , ArrayList <Node > result , NodeMap <HIRBlock > nodeMap , NodeBitMap unprocessed , Node excludeNode ) {
604
+ private static void sortIntoList (NodeStack stack , Node n , HIRBlock b , ArrayList <Node > result , NodeMap <HIRBlock > nodeMap , NodeBitMap unprocessed ) {
599
605
assert unprocessed .isMarked (n ) : Assertions .errorMessage (n );
600
606
assert nodeMap .get (n ) == b : Assertions .errorMessage (n );
601
-
602
- if (n instanceof PhiNode ) {
603
- return ;
604
- }
607
+ assert stack .isEmpty () : "Node stack must be pre-allocated, but empty." ;
608
+ assert !(n instanceof PhiNode ) : "Phi nodes will never be sorted into the list." ;
609
+ assert !(n instanceof ProxyNode ) : "Proxy nodes will never be sorted into the list." ;
605
610
606
611
unprocessed .clear (n );
607
612
608
613
/*
609
614
* Schedule all unprocessed transitive inputs. This uses an explicit stack instead of
610
615
* recursion to avoid overflowing the call stack.
611
616
*/
612
- NodeStack stack = new NodeStack ();
613
- ArrayList <Node > tempList = new ArrayList <>();
614
- stack .push (n );
617
+ pushUnprocessedInputs (n , b , nodeMap , unprocessed , stack );
615
618
while (!stack .isEmpty ()) {
616
619
Node top = stack .peek ();
617
- pushUnprocessedInputs (top , b , nodeMap , unprocessed , excludeNode , stack , tempList );
618
- if (stack .peek () == top ) {
619
- if (top != n ) {
620
- if (unprocessed .isMarked (top ) && !(top instanceof ProxyNode )) {
621
- result .add (top );
622
- }
620
+ int added = pushUnprocessedInputs (top , b , nodeMap , unprocessed , stack );
621
+ if (added == 0 ) {
622
+ if (unprocessed .isMarked (top )) {
623
+ result .add (top );
623
624
unprocessed .clear (top );
624
625
}
625
626
stack .pop ();
626
627
}
627
628
}
629
+ result .add (n );
630
+ }
628
631
629
- if (n instanceof ProxyNode ) {
630
- // Skip proxy nodes.
631
- } else {
632
- result .add (n );
632
+ private static int pushUnprocessedInputs (Node n , HIRBlock b , NodeMap <HIRBlock > nodeMap , NodeBitMap unprocessed , NodeStack stack ) {
633
+ int pushCount = 0 ;
634
+ for (Node input : n .inputs ()) {
635
+ if (nodeMap .get (input ) == b && unprocessed .isMarked (input )) {
636
+ assert !(input instanceof PhiNode ) : "Phi nodes will always be already unmarked in the bitmap." ;
637
+ assert !(input instanceof ProxyNode ) : "Proxy nodes will always be already unmarked in the bitmap." ;
638
+ stack .push (input );
639
+ pushCount ++;
640
+ }
633
641
}
634
- }
635
642
636
- private static void pushUnprocessedInputs (Node n , HIRBlock b , NodeMap <HIRBlock > nodeMap , NodeBitMap unprocessed , Node excludeNode , NodeStack stack , ArrayList <Node > tempList ) {
637
- tempList .clear ();
638
- n .inputs ().snapshotTo (tempList );
639
643
/*
640
644
* Nodes on top of the stack are scheduled first. Pushing inputs left to right would
641
645
* therefore mean scheduling them right to left. We observe the best performance when
642
646
* scheduling inputs left to right, therefore we push them in reverse order. We could
643
647
* explore more elaborate scheduling policies, like scheduling for reduced register
644
648
* pressure using Sethi-Ullman numbering (GR-34624).
645
649
*/
646
- for (int i = tempList .size () - 1 ; i >= 0 ; i --) {
647
- Node input = tempList .get (i );
648
- if (nodeMap .get (input ) == b && unprocessed .isMarked (input ) && input != excludeNode && !(input instanceof PhiNode )) {
649
- stack .push (input );
650
- }
651
- }
650
+ stack .reverseTopElements (pushCount );
651
+ return pushCount ;
652
652
}
653
653
654
654
protected void calcLatestBlock (HIRBlock earliestBlock , SchedulingStrategy strategy , Node currentNode , NodeMap <HIRBlock > currentNodeMap , LocationIdentity constrainingLocation ,
@@ -843,18 +843,9 @@ public void add(Node node) {
843
843
* Number of nodes in this micro block.
844
844
*/
845
845
public int getNodeCount () {
846
- assert getActualNodeCount () == nodeCount : getActualNodeCount () + " != " + nodeCount ;
847
846
return nodeCount ;
848
847
}
849
848
850
- private int getActualNodeCount () {
851
- int count = 0 ;
852
- for (NodeEntry e = head ; e != null ; e = e .next ) {
853
- count ++;
854
- }
855
- return count ;
856
- }
857
-
858
849
/**
859
850
* The id of the micro block, with a block always associated with a lower id than its
860
851
* successors.
@@ -940,7 +931,7 @@ private void scheduleEarliestIterative(BlockMap<List<Node>> blockToNodes, NodeMa
940
931
}
941
932
}
942
933
943
- if (graph .getGuardsStage ().allowsFloatingGuards () && graph .getNodes (GuardNode .TYPE ). isNotEmpty ( )) {
934
+ if (graph .getGuardsStage ().allowsFloatingGuards () && graph .hasNode (GuardNode .TYPE )) {
944
935
// Now process guards.
945
936
if (GuardPriorities .getValue (graph .getOptions ()) && withGuardOrder ) {
946
937
EnumMap <GuardPriority , List <GuardNode >> guardsByPriority = new EnumMap <>(GuardPriority .class );
@@ -955,8 +946,6 @@ private void scheduleEarliestIterative(BlockMap<List<Node>> blockToNodes, NodeMa
955
946
} else {
956
947
processNodes (visited , entries , stack , startBlock , graph .getNodes (GuardNode .TYPE ));
957
948
}
958
- } else {
959
- assert graph .getNodes (GuardNode .TYPE ).isEmpty ();
960
949
}
961
950
962
951
// Now process inputs of fixed nodes.
0 commit comments