@@ -242,7 +242,6 @@ class ShadowStackAllocator
242
242
class LssaDomTreeVisitor : public DomTreeVisitor <LssaDomTreeVisitor>
243
243
{
244
244
class NotExposedReason ;
245
- struct NotExposedReasonLink ;
246
245
247
246
// Cannot use raw node pointers as their values influence hash table iteration order.
248
247
struct DeterministicNodeHashInfo : public HashTableInfo <DeterministicNodeHashInfo>
@@ -329,7 +328,7 @@ class ShadowStackAllocator
329
328
ArrayStack<BitVec> m_candidateBitSetPool;
330
329
331
330
#ifdef DEBUG
332
- JitHashTable<LclSsaVarDsc*, JitPtrKeyFuncs<LclSsaVarDsc>, NotExposedReasonLink *> m_notExposedReasonMap;
331
+ JitHashTable<LclSsaVarDsc*, JitPtrKeyFuncs<LclSsaVarDsc>, const char *> m_notExposedReasonMap;
333
332
#endif // DEBUG
334
333
335
334
public:
@@ -748,9 +747,7 @@ class ShadowStackAllocator
748
747
unsigned status = GetGcExposedStatus (ssaDsc);
749
748
if (status == GC_EXPOSED_UNKNOWN)
750
749
{
751
- bool isExposed = true ;
752
750
GenTreeLclVarCommon* defNode = ssaDsc->GetDefNode ();
753
- INDEBUG (NotExposedReason defReason (this ));
754
751
if (defNode == nullptr )
755
752
{
756
753
assert (ssaNum == SsaConfig::FIRST_SSA_NUM);
@@ -760,19 +757,25 @@ class ShadowStackAllocator
760
757
assert (initKind != ValueInitKind::None);
761
758
if (initKind != ValueInitKind::Param)
762
759
{
763
- INDEBUG (defReason. Add (" implicit zero def" ));
764
- isExposed = false ;
760
+ INDEBUG (pReason-> Add (" implicit zero def" ));
761
+ status = GC_EXPOSED_NO ;
765
762
}
766
763
}
767
764
else if (defNode->OperIs (GT_STORE_LCL_VAR) &&
768
- !IsGcExposedValue (defNode->Data (), DefStatus::Unknown DEBUGARG (&defReason )))
765
+ !IsGcExposedValue (defNode->Data (), DefStatus::Unknown DEBUGARG (pReason )))
769
766
{
770
- isExposed = false ;
767
+ status = GC_EXPOSED_NO ;
771
768
}
772
769
773
- // This caching is designed to prevent quadratic behavior.
774
- status = isExposed ? GC_EXPOSED_YES : GC_EXPOSED_NO;
775
- SetGcExposedStatus (ssaDsc, status DEBUGARG (varDsc) DEBUGARG (&defReason));
770
+ if (status != GC_EXPOSED_NO)
771
+ {
772
+ // This caching is designed to prevent quadratic behavior. However, we can't cache "NO" results as
773
+ // they depend on the current execution point (different points may yield different results as
774
+ // shadow slots get overwritten with new values), so this is not a complete solution...
775
+ // TODO-LLVM-LSSA: fix the above with a new LSSA algorithm.
776
+ status = GC_EXPOSED_YES;
777
+ SetGcExposedStatus (ssaDsc, status DEBUGARG (varDsc));
778
+ }
776
779
}
777
780
// Take care not to depend on potentially stale information. Consider:
778
781
//
@@ -1112,7 +1115,7 @@ class ShadowStackAllocator
1112
1115
}
1113
1116
1114
1117
void SetGcExposedStatus (
1115
- LclSsaVarDsc* ssaDsc, unsigned status DEBUGARG (LclVarDsc* varDsc) DEBUGARG(NotExposedReason* pReason))
1118
+ LclSsaVarDsc* ssaDsc, unsigned status DEBUGARG (LclVarDsc* varDsc) DEBUGARG(NotExposedReason* pReason = nullptr ))
1116
1119
{
1117
1120
unsigned oldStatus = GetGcExposedStatus (ssaDsc);
1118
1121
assert ((oldStatus == GC_EXPOSED_UNKNOWN) || ((oldStatus == GC_EXPOSED_YES) && (status == GC_EXPOSED_SPILL)));
@@ -1123,7 +1126,7 @@ class ShadowStackAllocator
1123
1126
1124
1127
JITDUMP (" V%02u/%u: %s -> %s\n " , m_compiler->lvaGetLclNum (varDsc),
1125
1128
varDsc->GetSsaNumForSsaDef (ssaDsc), GcStatusToString (oldStatus), GcStatusToString (status));
1126
- INDEBUG ( pReason->SaveForDef (ssaDsc));
1129
+ DBEXEC (pReason != nullptr , pReason->SaveForDef (ssaDsc));
1127
1130
}
1128
1131
1129
1132
unsigned GetGcExposedStatus (LclSsaVarDsc* ssaDsc)
@@ -1353,12 +1356,6 @@ class ShadowStackAllocator
1353
1356
}
1354
1357
}
1355
1358
1356
- struct NotExposedReasonLink
1357
- {
1358
- const char * Reason;
1359
- NotExposedReasonLink* Next;
1360
- };
1361
-
1362
1359
class NotExposedReason
1363
1360
{
1364
1361
LssaDomTreeVisitor* m_visitor;
@@ -1393,12 +1390,11 @@ class ShadowStackAllocator
1393
1390
{
1394
1391
if (m_enabled)
1395
1392
{
1393
+ const char * reason;
1396
1394
LclSsaVarDsc* ssaDsc = varDsc->GetPerSsaData (ssaNum);
1397
- NotExposedReasonLink* link = m_visitor->m_notExposedReasonMap [ssaDsc];
1398
- while (link != nullptr )
1395
+ if (m_visitor->m_notExposedReasonMap .Lookup (ssaDsc, &reason))
1399
1396
{
1400
- Add (link->Reason );
1401
- link = link->Next ;
1397
+ Add (reason);
1402
1398
}
1403
1399
1404
1400
unsigned lclNum = m_visitor->m_compiler ->lvaGetLclNum (varDsc);
@@ -1429,26 +1425,11 @@ class ShadowStackAllocator
1429
1425
1430
1426
void SaveForDef (LclSsaVarDsc* ssaDsc)
1431
1427
{
1432
- CompAllocator alloc = m_visitor->m_compiler ->getAllocator (CMK_DebugOnly);
1433
- NotExposedReasonLink* links = nullptr ;
1434
- NotExposedReasonLink* last = nullptr ;
1435
- for (int i = 0 ; i < m_chain.Height (); i++)
1436
- {
1437
- NotExposedReasonLink* link = new (alloc) NotExposedReasonLink ();
1438
- link->Reason = m_chain.Bottom (i);
1439
- if (last == nullptr )
1440
- {
1441
- links = link;
1442
- }
1443
- else
1444
- {
1445
- last->Next = link;
1446
- }
1447
- last = link;
1448
- }
1449
- if (links != nullptr )
1428
+ if (m_enabled)
1450
1429
{
1451
- m_visitor->m_notExposedReasonMap .Set (ssaDsc, links);
1430
+ assert (m_chain.Height () == 1 ); // Full support currently not needed.
1431
+ const char * reason = m_chain.Top ();
1432
+ m_visitor->m_notExposedReasonMap .Set (ssaDsc, reason);
1452
1433
}
1453
1434
}
1454
1435
0 commit comments