فهرست منبع

[1.10>master] [MERGE #5481 @leirocks] seperate lockdown and closing states

Merge pull request #5481 from leirocks:counters

Compact counters on function body is locked when JIT started and then we should never change it afterward (unless redefer and unlock first)
however when function body cleanup we do cleanup the counters, at that time we unlock and then lock the counters, in between this, there might be JIT thread accessing the counters hence we Assert that counters should be in locked state.
seperating lockdown and closing state to avoid this racing condition
Lei Shi (CHAKRA) 7 سال پیش
والد
کامیت
f469675763
3فایلهای تغییر یافته به همراه11 افزوده شده و 8 حذف شده
  1. 3 2
      lib/Runtime/Base/CompactCounters.h
  2. 7 6
      lib/Runtime/Base/FunctionBody.cpp
  3. 1 0
      lib/Runtime/Base/FunctionBody.h

+ 3 - 2
lib/Runtime/Base/CompactCounters.h

@@ -32,8 +32,8 @@ namespace Js
     private:
         FieldWithBarrier(uint8) fieldSize;
 #if DBG
-
-        mutable FieldWithBarrier(bool) isLockedDown;
+        mutable FieldWithBarrier(bool) isLockedDown:1;
+        mutable FieldWithBarrier(bool) isClosing:1;
 #endif
         typename FieldWithBarrier(Fields*) fields;
 
@@ -42,6 +42,7 @@ namespace Js
             :fieldSize(0)
 #if DBG
             , isLockedDown(false)
+            , isClosing(false)
 #endif
         {
             AllocCounters<uint8>(host);

+ 7 - 6
lib/Runtime/Base/FunctionBody.cpp

@@ -245,19 +245,22 @@ namespace Js
     uint32 FunctionBody::GetCountField(FunctionBody::CounterFields fieldEnum) const
     {
 #if DBG
-        Assert(ThreadContext::GetContextForCurrentThread() || counters.isLockedDown
+        bool isCountersLockedDown = counters.isLockedDown;
+        Assert(ThreadContext::GetContextForCurrentThread() || isCountersLockedDown
             || (ThreadContext::GetCriticalSection()->IsLocked() && this->m_scriptContext->GetThreadContext()->GetFunctionBodyLock()->IsLocked())); // etw rundown
 #endif
         return counters.Get(fieldEnum);
     }
     uint32 FunctionBody::SetCountField(FunctionBody::CounterFields fieldEnum, uint32 val)
     {
-        Assert(!counters.isLockedDown);
+        DebugOnly(bool isCountersLockedDown = counters.isLockedDown);
+        Assert(!isCountersLockedDown || counters.isClosing);
         return counters.Set(fieldEnum, val, this);
     }
     uint32 FunctionBody::IncreaseCountField(FunctionBody::CounterFields fieldEnum)
     {
-        Assert(!counters.isLockedDown);
+        DebugOnly(bool isCountersLockedDown = counters.isLockedDown);
+        Assert(!isCountersLockedDown || counters.isClosing);
         return counters.Increase(fieldEnum, this);
     }
 
@@ -7552,7 +7555,7 @@ namespace Js
             return;
         }
 
-        DebugOnly(this->UnlockCounters());
+        DebugOnly(this->SetIsClosing());
 
         CleanupRecyclerData(isScriptContextClosing, false /* capture entry point cleanup stack trace */);
         CleanUpForInCache(isScriptContextClosing);
@@ -7591,8 +7594,6 @@ namespace Js
 #endif
 
         this->cleanedUp = true;
-
-        DebugOnly(this->LockDownCounters());
     }
 
 

+ 1 - 0
lib/Runtime/Base/FunctionBody.h

@@ -1894,6 +1894,7 @@ namespace Js
 #if DBG
             void LockDownCounters() { counters.isLockedDown = true; };
             void UnlockCounters() { counters.isLockedDown = false; };
+            void SetIsClosing() { counters.isClosing = true; };
 #endif
 
             struct StatementMap