@@ -53,15 +53,6 @@ void ObjectAllocator::DoPhase()
53
53
}
54
54
}
55
55
56
- struct ObjectAllocator ::BuildConnGraphVisitorCallbackData
57
- {
58
- BuildConnGraphVisitorCallbackData (ObjectAllocator* objectAllocator) : m_objectAllocator(objectAllocator)
59
- {
60
- }
61
-
62
- ObjectAllocator* m_objectAllocator;
63
- };
64
-
65
56
// ------------------------------------------------------------------------------
66
57
// MarkLclVarAsEscaping : Mark local variable as escaping.
67
58
//
@@ -114,7 +105,7 @@ void ObjectAllocator::DoAnalysis()
114
105
if (comp->lvaCount > 0 )
115
106
{
116
107
m_EscapingPointers = BitVecOps::MakeEmpty (&m_bitVecTraits);
117
- m_ConnGraphAdjacencyMatrix = new (comp->getAllocator ()) BitSetShortLongRep[comp->lvaCount ];
108
+ m_ConnGraphAdjacencyMatrix = new (comp->getAllocator (CMK_ObjectAllocator )) BitSetShortLongRep[comp->lvaCount ];
118
109
119
110
MarkEscapingVarsAndBuildConnGraph ();
120
111
ComputeEscapingNodes (&m_bitVecTraits, m_EscapingPointers);
@@ -141,7 +132,47 @@ void ObjectAllocator::DoAnalysis()
141
132
142
133
void ObjectAllocator::MarkEscapingVarsAndBuildConnGraph ()
143
134
{
144
- BuildConnGraphVisitorCallbackData callbackData (this );
135
+ class BuildConnGraphVisitor final : public GenTreeVisitor<BuildConnGraphVisitor>
136
+ {
137
+ ObjectAllocator* m_allocator;
138
+
139
+ public:
140
+ enum
141
+ {
142
+ DoPreOrder = true ,
143
+ DoLclVarsOnly = true ,
144
+ ComputeStack = true ,
145
+ };
146
+
147
+ BuildConnGraphVisitor (ObjectAllocator* allocator)
148
+ : GenTreeVisitor<BuildConnGraphVisitor>(allocator->comp), m_allocator(allocator)
149
+ {
150
+ }
151
+
152
+ Compiler::fgWalkResult PreOrderVisit (GenTree** use, GenTree* user)
153
+ {
154
+ GenTree* tree = *use;
155
+ assert (tree != nullptr );
156
+ assert (tree->IsLocal ());
157
+
158
+ var_types type = tree->TypeGet ();
159
+ if ((tree->OperGet () == GT_LCL_VAR) && (type == TYP_REF || type == TYP_BYREF || type == TYP_I_IMPL))
160
+ {
161
+ unsigned int lclNum = tree->AsLclVar ()->GetLclNum ();
162
+ assert (tree == m_ancestors.Index (0 ));
163
+
164
+ if (m_allocator->CanLclVarEscapeViaParentStack (&m_ancestors, lclNum))
165
+ {
166
+ if (!m_allocator->IsLclVarEscaping (lclNum))
167
+ {
168
+ JITDUMP (" V%02u first escapes via [%06u]\n " , lclNum, m_compiler->dspTreeID (tree));
169
+ }
170
+ m_allocator->MarkLclVarAsEscaping (lclNum);
171
+ }
172
+ }
173
+ return Compiler::fgWalkResult::WALK_CONTINUE;
174
+ }
175
+ };
145
176
146
177
for (unsigned int lclNum = 0 ; lclNum < comp->lvaCount ; ++lclNum)
147
178
{
@@ -170,10 +201,8 @@ void ObjectAllocator::MarkEscapingVarsAndBuildConnGraph()
170
201
{
171
202
for (GenTreeStmt* stmt = block->firstStmt (); stmt; stmt = stmt->gtNextStmt )
172
203
{
173
- const bool lclVarsOnly = true ;
174
- const bool computeStack = true ;
175
-
176
- comp->fgWalkTreePre (&stmt->gtStmtExpr , BuildConnGraphVisitor, &callbackData, lclVarsOnly, computeStack);
204
+ BuildConnGraphVisitor buildConnGraphVisitor (this );
205
+ buildConnGraphVisitor.WalkTree (&stmt->gtStmtExpr , nullptr );
177
206
}
178
207
}
179
208
}
@@ -423,55 +452,13 @@ unsigned int ObjectAllocator::MorphAllocObjNodeIntoStackAlloc(GenTreeAllocObj* a
423
452
return lclNum;
424
453
}
425
454
426
- // ------------------------------------------------------------------------
427
- // BuildConnGraphVisitor: Check if the current tree is a local variable that can point to an object
428
- // and is escaping. Update the connection graph as necessary.
429
- //
430
- // Arguments:
431
- // pTree - Tree being visited
432
- // data - Walker data
433
- //
434
- // Return Value:
435
- // Always returns fgWalkResult::WALK_CONTINUE
436
-
437
- Compiler::fgWalkResult ObjectAllocator::BuildConnGraphVisitor (GenTree** pTree, Compiler::fgWalkData* data)
438
- {
439
- GenTree* tree = *pTree;
440
- assert (tree);
441
-
442
- var_types type = tree->TypeGet ();
443
- if (tree->OperGet () == GT_LCL_VAR && (type == TYP_REF || type == TYP_BYREF || type == TYP_I_IMPL))
444
- {
445
- Compiler* compiler = data->compiler ;
446
- GenTree* parent = data->parent ;
447
- BuildConnGraphVisitorCallbackData* callbackData =
448
- reinterpret_cast <BuildConnGraphVisitorCallbackData*>(data->pCallbackData );
449
- ObjectAllocator* objectAllocator = callbackData->m_objectAllocator ;
450
-
451
- unsigned int lclNum = tree->AsLclVar ()->GetLclNum ();
452
- assert (tree == data->parentStack ->Index (0 ));
453
- assert (data->parent == data->parentStack ->Index (1 ));
454
-
455
- if (objectAllocator->CanLclVarEscapeViaParentStack (data->parentStack , lclNum, data->compiler ))
456
- {
457
- if (!objectAllocator->IsLclVarEscaping (lclNum))
458
- {
459
- JITDUMP (" V%02u first escapes (2) via [%06u]\n " , lclNum, tree->gtTreeID );
460
- }
461
- objectAllocator->MarkLclVarAsEscaping (lclNum);
462
- }
463
- }
464
- return Compiler::fgWalkResult::WALK_CONTINUE;
465
- }
466
-
467
455
// ------------------------------------------------------------------------
468
456
// CanLclVarEscapeViaParentStack: Check if the local variable escapes via the given parent stack.
469
457
// Update the connection graph as necessary.
470
458
//
471
459
// Arguments:
472
460
// parentStack - Parent stack of the current visit
473
461
// lclNum - Local variable number
474
- // compiler - Compiler instance
475
462
//
476
463
// Return Value:
477
464
// true if the local can escape via the parent stack; false otherwise
@@ -480,17 +467,15 @@ Compiler::fgWalkResult ObjectAllocator::BuildConnGraphVisitor(GenTree** pTree, C
480
467
// The method currently treats all locals assigned to a field as escaping.
481
468
// The can potentially be tracked by special field edges in the connection graph.
482
469
483
- bool ObjectAllocator::CanLclVarEscapeViaParentStack (ArrayStack<GenTree*>* parentStack,
484
- unsigned int lclNum,
485
- Compiler* compiler)
470
+ bool ObjectAllocator::CanLclVarEscapeViaParentStack (ArrayStack<GenTree*>* parentStack, unsigned int lclNum)
486
471
{
487
472
assert (parentStack != nullptr );
488
473
int parentIndex = 1 ;
489
474
490
- bool done = false ;
475
+ bool keepChecking = true ;
491
476
bool canLclVarEscapeViaParentStack = true ;
492
477
493
- while (!done )
478
+ while (keepChecking )
494
479
{
495
480
if (parentStack->Height () <= parentIndex)
496
481
{
@@ -501,7 +486,7 @@ bool ObjectAllocator::CanLclVarEscapeViaParentStack(ArrayStack<GenTree*>* parent
501
486
canLclVarEscapeViaParentStack = true ;
502
487
GenTree* tree = parentStack->Index (parentIndex - 1 );
503
488
GenTree* parent = parentStack->Index (parentIndex);
504
- done = true ;
489
+ keepChecking = false ;
505
490
506
491
switch (parent->OperGet ())
507
492
{
@@ -566,7 +551,7 @@ bool ObjectAllocator::CanLclVarEscapeViaParentStack(ArrayStack<GenTree*>* parent
566
551
case GT_ADD:
567
552
// Check whether the local escapes via its grandparent.
568
553
++parentIndex;
569
- done = false ;
554
+ keepChecking = true ;
570
555
break ;
571
556
572
557
case GT_FIELD:
@@ -578,7 +563,7 @@ bool ObjectAllocator::CanLclVarEscapeViaParentStack(ArrayStack<GenTree*>* parent
578
563
{
579
564
// Check if the address of the field/ind escapes.
580
565
parentIndex += 2 ;
581
- done = false ;
566
+ keepChecking = true ;
582
567
}
583
568
else
584
569
{
@@ -594,7 +579,7 @@ bool ObjectAllocator::CanLclVarEscapeViaParentStack(ArrayStack<GenTree*>* parent
594
579
595
580
if (asCall->gtCallType == CT_HELPER)
596
581
{
597
- const CorInfoHelpFunc helperNum = compiler ->eeGetHelperNum (asCall->gtCallMethHnd );
582
+ const CorInfoHelpFunc helperNum = comp ->eeGetHelperNum (asCall->gtCallMethHnd );
598
583
599
584
if (Compiler::s_helperCallProperties.IsPure (helperNum))
600
585
{
@@ -644,46 +629,50 @@ Compiler::fgWalkResult ObjectAllocator::AssertWhenAllocObjFoundVisitor(GenTree**
644
629
645
630
void ObjectAllocator::RewriteUses ()
646
631
{
647
- BasicBlock* block;
648
-
649
- foreach_block (comp, block)
632
+ class RewriteUsesVisitor final : public GenTreeVisitor<RewriteUsesVisitor>
650
633
{
651
- for (GenTreeStmt* stmt = block->firstStmt (); stmt; stmt = stmt->gtNextStmt )
634
+ ObjectAllocator* m_allocator;
635
+
636
+ public:
637
+ enum
652
638
{
653
- const bool lclVarsOnly = true ;
654
- const bool computeStack = false ;
639
+ DoPreOrder = true ,
640
+ DoLclVarsOnly = true ,
641
+ };
655
642
656
- comp->fgWalkTreePre (&stmt->gtStmtExpr , RewriteUsesVisitor, this , lclVarsOnly, computeStack);
643
+ RewriteUsesVisitor (ObjectAllocator* allocator)
644
+ : GenTreeVisitor<RewriteUsesVisitor>(allocator->comp), m_allocator(allocator)
645
+ {
657
646
}
658
- }
659
- }
660
647
661
- // ------------------------------------------------------------------------
662
- // RewriteUsesVisitor: Replace a use of the newobj temp with address of the stack local.
663
- //
664
- // Arguments:
665
- // pTree - Tree to examine
666
- // data - Walker data
667
- //
668
- // Return Value:
669
- // Always returns fgWalkResult::WALK_CONTINUE
648
+ Compiler::fgWalkResult PreOrderVisit (GenTree** use, GenTree* user)
649
+ {
650
+ GenTree* tree = *use;
651
+ assert (tree != nullptr );
652
+ assert (tree->IsLocal ());
670
653
671
- Compiler::fgWalkResult ObjectAllocator::RewriteUsesVisitor (GenTree** pTree, Compiler::fgWalkData* data)
672
- {
673
- ObjectAllocator* allocator = reinterpret_cast <ObjectAllocator*>(data->pCallbackData );
674
- GenTree* tree = *pTree;
675
- assert (tree != nullptr );
676
- assert (tree->IsLocal ());
654
+ const unsigned int lclNum = tree->AsLclVarCommon ()->gtLclNum ;
655
+ unsigned int newLclNum = BAD_VAR_NUM;
656
+
657
+ if (m_allocator->m_HeapLocalToStackLocalMap .TryGetValue (lclNum, &newLclNum))
658
+ {
659
+ GenTree* newTree =
660
+ m_compiler->gtNewOperNode (GT_ADDR, TYP_BYREF, m_compiler->gtNewLclvNode (newLclNum, TYP_STRUCT));
661
+ *use = newTree;
662
+ }
677
663
678
- const unsigned int lclNum = tree->AsLclVarCommon ()->gtLclNum ;
679
- unsigned int newLclNum = BAD_VAR_NUM;
680
- Compiler* comp = allocator->comp ;
664
+ return Compiler::fgWalkResult::WALK_CONTINUE;
665
+ }
666
+ };
667
+
668
+ BasicBlock* block;
681
669
682
- if (allocator-> m_HeapLocalToStackLocalMap . TryGetValue (lclNum, &newLclNum) )
670
+ foreach_block (comp, block )
683
671
{
684
- GenTree* newTree = comp->gtNewOperNode (GT_ADDR, TYP_BYREF, comp->gtNewLclvNode (newLclNum, TYP_STRUCT));
685
- *pTree = newTree;
672
+ for (GenTreeStmt* stmt = block->firstStmt (); stmt; stmt = stmt->gtNextStmt )
673
+ {
674
+ RewriteUsesVisitor rewriteUsesVisitor (this );
675
+ rewriteUsesVisitor.WalkTree (&stmt->gtStmtExpr , nullptr );
676
+ }
686
677
}
687
-
688
- return Compiler::fgWalkResult::WALK_CONTINUE;
689
678
}
0 commit comments