Parcourir la source

use bv for jit numeric property records

Michael Holman il y a 9 ans
Parent
commit
d0b29ad71b

+ 5 - 48
lib/Backend/NativeCodeGenerator.cpp

@@ -2036,57 +2036,14 @@ NativeCodeGenerator::UpdateJITState()
             return;
         }
 
-        // update all property records on server that have been changed since last jit
-        ThreadContext::PropertyList * pendingProps = scriptContext->GetThreadContext()->GetPendingJITProperties();
-        int * newPropArray = nullptr;
-        uint newCount = 0;
-        if (pendingProps->Count() > 0)
-        {
-            newCount = (uint)pendingProps->Count();
-            newPropArray = HeapNewArray(int, newCount);
-            uint index = 0;
-            while (!pendingProps->Empty())
-            {
-                newPropArray[index++] = (int)pendingProps->Pop();
-            }
-            Assert(index == newCount);
-        }
-
-        ThreadContext::PropertyList * reclaimedProps = scriptContext->GetThreadContext()->GetReclaimedJITProperties();
-        int * reclaimedPropArray = nullptr;
-        uint reclaimedCount = 0;
-        if (reclaimedProps->Count() > 0)
+        if (scriptContext->GetThreadContext()->JITNeedsPropUpdate())
         {
-            reclaimedCount = (uint)reclaimedProps->Count();
-            reclaimedPropArray = HeapNewArray(int, reclaimedCount);
-            uint index = 0;
-            while (!reclaimedProps->Empty())
-            {
-                reclaimedPropArray[index++] = (int)reclaimedProps->Pop();
-            }
-            Assert(index == reclaimedCount);
-        }
-
-        if (newCount > 0 || reclaimedCount > 0)
-        {
-            UpdatedPropertysIDL props = {0};
-            props.reclaimedPropertyCount = reclaimedCount;
-            props.reclaimedPropertyIdArray = reclaimedPropArray;
-            props.newPropertyCount = newCount;
-            props.newPropertyIdArray = newPropArray;
-
-            HRESULT hr = JITManager::GetJITManager()->UpdatePropertyRecordMap(scriptContext->GetThreadContext()->GetRemoteThreadContextAddr(), &props);
-
-            if (newPropArray)
-            {
-                HeapDeleteArray(newCount, newPropArray);
-            }
-            if (reclaimedPropArray)
-            {
-                HeapDeleteArray(reclaimedCount, reclaimedPropArray);
-            }
+            CompileAssert(sizeof(BVSparseNode) == sizeof(BVSparseNodeIDL));
+            BVSparseNodeIDL * bvHead = (BVSparseNodeIDL*)scriptContext->GetThreadContext()->GetJITNumericProperties()->head;
+            HRESULT hr = JITManager::GetJITManager()->UpdatePropertyRecordMap(scriptContext->GetThreadContext()->GetRemoteThreadContextAddr(), bvHead);
 
             JITManager::HandleServerCallResult(hr);
+            scriptContext->GetThreadContext()->ResetJITNeedsPropUpdate();
         }
     }
 }

+ 13 - 32
lib/Backend/ServerThreadContext.cpp

@@ -12,7 +12,7 @@
 ServerThreadContext::ServerThreadContext(ThreadContextDataIDL * data) :
     m_threadContextData(*data),
     m_refCount(0),
-    m_numericPropertySet(nullptr),
+    m_numericPropertyBV(nullptr),
     m_preReservedVirtualAllocator((HANDLE)data->processHandle),
     m_codePageAllocators(nullptr, ALLOC_XDATA, &m_preReservedVirtualAllocator, (HANDLE)data->processHandle),
 #if DYNAMIC_INTERPRETER_THUNK || defined(ASMJS_PLAT)
@@ -33,16 +33,15 @@ ServerThreadContext::ServerThreadContext(ThreadContextDataIDL * data) :
 #if !_M_X64_OR_ARM64 && _CONTROL_FLOW_GUARD
     m_codeGenAlloc.canCreatePreReservedSegment = data->allowPrereserveAlloc != FALSE;
 #endif
-    m_numericPropertySet = HeapNew(PropertySet, &HeapAllocator::Instance);
+    m_numericPropertyBV = HeapNew(BVSparse<HeapAllocator>, &HeapAllocator::Instance);
 }
 
 ServerThreadContext::~ServerThreadContext()
 {
-    // TODO: OOP JIT, clear out elements of map. maybe should arena alloc?
-    if (this->m_numericPropertySet != nullptr)
+    if (this->m_numericPropertyBV != nullptr)
     {
-        HeapDelete(m_numericPropertySet);
-        this->m_numericPropertySet = nullptr;
+        HeapDelete(m_numericPropertyBV);
+        this->m_numericPropertyBV = nullptr;
     }
 
 }
@@ -166,38 +165,20 @@ ServerThreadContext::IsNumericProperty(Js::PropertyId propertyId)
         return Js::InternalPropertyRecords::GetInternalPropertyName(propertyId)->IsNumeric();
     }
 
-    m_numericPropertySet->LockResize();
-    bool found = m_numericPropertySet->ContainsKey(propertyId);
-    m_numericPropertySet->UnlockResize();
-
-    return found;
-}
-
-void
-ServerThreadContext::RemoveFromNumericPropertySet(Js::PropertyId reclaimedId)
-{
-    if (m_numericPropertySet->ContainsKey(reclaimedId))
+    bool found = false;
     {
-        // if there was reclaimed property that had its pid reused, delete the old property record
-        m_numericPropertySet->Remove(reclaimedId);
-    }
-    else
-    {
-        // we should only ever ask to reclaim properties which were previously added to the jit map
-        Assert(UNREACHED);
+        AutoCriticalSection lock(&m_cs);
+        found = m_numericPropertyBV->Test(propertyId) != FALSE;
     }
+
+    return found;
 }
 
 void
-ServerThreadContext::AddToNumericPropertySet(Js::PropertyId propId)
+ServerThreadContext::UpdateNumericPropertyBV(BVSparseNode * newProps)
 {
-    // this should only happen if there was reclaimed property that we failed to add to reclaimed list due to a prior oom
-    if (m_numericPropertySet->ContainsKey(propId))
-    {
-        m_numericPropertySet->Remove(propId);
-    }
-
-    m_numericPropertySet->Add(propId);
+    AutoCriticalSection lock(&m_cs);
+    m_numericPropertyBV->CopyFromNode(newProps);
 }
 
 void ServerThreadContext::AddRef()

+ 4 - 6
lib/Backend/ServerThreadContext.h

@@ -36,8 +36,7 @@ public:
 
     CodeGenAllocators * GetCodeGenAllocators();
     CustomHeap::CodePageAllocators * GetCodePageAllocators();
-    void RemoveFromNumericPropertySet(Js::PropertyId reclaimedId);
-    void AddToNumericPropertySet(Js::PropertyId propertyId);
+    void UpdateNumericPropertyBV(BVSparseNode * newProps);
     void SetWellKnownHostTypeId(Js::TypeId typeId) { this->wellKnownHostTypeHTMLAllCollectionTypeId = typeId; }
 #if DYNAMIC_INTERPRETER_THUNK || defined(ASMJS_PLAT)
     CustomHeap::CodePageAllocators * GetThunkPageAllocators();
@@ -54,9 +53,7 @@ private:
     intptr_t GetRuntimeChakraBaseAddress() const;
     intptr_t GetRuntimeCRTBaseAddress() const;
 
-    typedef JsUtil::BaseHashSet<Js::PropertyId, HeapAllocator, PrimeSizePolicy, Js::PropertyId,
-        DefaultComparer, JsUtil::SimpleHashedEntry, JsUtil::AsymetricResizeLock> PropertySet;
-    PropertySet * m_numericPropertySet;
+    BVSparse<HeapAllocator> * m_numericPropertyBV;
 
     PreReservedVirtualAllocWrapper m_preReservedVirtualAllocator;
 #if DYNAMIC_INTERPRETER_THUNK || defined(ASMJS_PLAT)
@@ -70,7 +67,8 @@ private:
     ThreadContextDataIDL m_threadContextData;
 
     DWORD m_pid; //save client process id for easier diagnose
-    
+
+    CriticalSection m_cs;
     intptr_t m_jitCRTBaseAddress;
     uint m_refCount;
 };

+ 10 - 3
lib/Common/DataStructures/SparseBitVector.h

@@ -174,6 +174,7 @@ public:
 
             template <class TSrcAllocator>
             void            Copy(const BVSparse<TSrcAllocator> *bv);
+            void            CopyFromNode(const BVSparseNode * node2);
             BVSparse<TAllocator> *      CopyNew(TAllocator* allocator) const;
             BVSparse<TAllocator> *      CopyNew() const;
             void            ComplimentAll();
@@ -793,9 +794,15 @@ BVSparse<TAllocator>::Copy(const BVSparse<TSrcAllocator> * bv2)
 {
     AssertBV(bv2);
 
-          BVSparseNode * node1      = this->head;
-    const BVSparseNode * node2      = bv2->head;
-          BVSparseNode ** prevNextField = &this->head;
+    CopyFromNode(bv2->head);
+}
+
+template <class TAllocator>
+void
+BVSparse<TAllocator>::CopyFromNode(const BVSparseNode * node2)
+{
+    BVSparseNode * node1 = this->head;
+    BVSparseNode ** prevNextField = &this->head;
 
     while (node1 != nullptr && node2 != nullptr)
     {

+ 2 - 2
lib/JITClient/JITManager.cpp

@@ -454,14 +454,14 @@ JITManager::SetWellKnownHostTypeId(
 HRESULT
 JITManager::UpdatePropertyRecordMap(
     __in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
-    __in UpdatedPropertysIDL * updatedProps)
+    __in BVSparseNodeIDL * updatedPropsBVHead)
 {
     Assert(IsOOPJITEnabled());
 
     HRESULT hr = E_FAIL;
     RpcTryExcept
     {
-        hr = ClientUpdatePropertyRecordMap(m_rpcBindingHandle, threadContextInfoAddress, updatedProps);
+        hr = ClientUpdatePropertyRecordMap(m_rpcBindingHandle, threadContextInfoAddress, updatedPropsBVHead);
     }
     RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
     {

+ 2 - 2
lib/JITClient/JITManager.h

@@ -31,7 +31,7 @@ public:
 
     HRESULT UpdatePropertyRecordMap(
         __in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
-        __in UpdatedPropertysIDL * updatedProps);
+        __in BVSparseNodeIDL * updatedPropsBVHead);
 
     HRESULT NewInterpreterThunkBlock(
         __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
@@ -144,7 +144,7 @@ public:
 
     HRESULT UpdatePropertyRecordMap(
         __in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
-        __in UpdatedPropertysIDL * updatedProps)
+        __in BVSparseNodeIDL * updatedPropsBVHead)
         { Assert(false); return E_FAIL; }
 
     HRESULT AddDOMFastPathHelper(

+ 1 - 1
lib/JITIDL/ChakraJIT.idl

@@ -30,7 +30,7 @@ interface IChakraJIT
     HRESULT UpdatePropertyRecordMap(
         [in] handle_t binding,
         [in] PTHREADCONTEXT_HANDLE threadContextInfoAddress,
-        [in] UpdatedPropertysIDL * updatedProps);
+        [in] BVSparseNodeIDL * updatedPropsBVHead);
 
     HRESULT AddDOMFastPathHelper(
         [in] handle_t binding,

+ 8 - 8
lib/JITIDL/JITTypes.h

@@ -172,6 +172,14 @@ typedef struct BVFixedIDL
     IDL_DEF([size_is(((len - 1) >> BV_SHIFT) + 1)]) BVUnitIDL data[IDL_DEF(*)];
 } BVFixedIDL;
 
+typedef struct BVSparseNodeIDL
+{
+    struct BVSparseNodeIDL * next;
+    unsigned int startIndex;
+    X64_PAD4(0)
+    __int64 data;
+} BVSparseNodeIDL;
+
 typedef struct CallSiteIDL
 {
     unsigned short bitFields;
@@ -807,14 +815,6 @@ typedef struct JITOutputIDL
     __int64 startTime;
 } JITOutputIDL;
 
-typedef struct UpdatedPropertysIDL
-{
-    unsigned int reclaimedPropertyCount;
-    unsigned int newPropertyCount;
-    [size_is(reclaimedPropertyCount)] int * reclaimedPropertyIdArray;
-    [size_is(newPropertyCount)] int * newPropertyIdArray;
-} UpdatedPropertysIDL;
-
 typedef struct InterpreterThunkInfoIDL
 {
     unsigned int thunkCount;

+ 3 - 10
lib/JITServer/JITServer.cpp

@@ -250,7 +250,7 @@ HRESULT
 ServerUpdatePropertyRecordMap(
     /* [in] */ handle_t binding,
     /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
-    /* [in] */ __RPC__in UpdatedPropertysIDL * updatedProps)
+    /* [in] */ __RPC__in BVSparseNodeIDL * updatedPropsBVHead)
 {
     ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
 
@@ -262,15 +262,8 @@ ServerUpdatePropertyRecordMap(
 
     return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
     {
-        for (uint i = 0; i < updatedProps->reclaimedPropertyCount; ++i)
-        {
-            threadContextInfo->RemoveFromNumericPropertySet((Js::PropertyId)updatedProps->reclaimedPropertyIdArray[i]);
-        }
-
-        for (uint i = 0; i < updatedProps->newPropertyCount; ++i)
-        {
-            threadContextInfo->AddToNumericPropertySet((Js::PropertyId)updatedProps->newPropertyIdArray[i]);
-        }
+        CompileAssert(sizeof(BVSparseNode) == sizeof(BVSparseNodeIDL));
+        threadContextInfo->UpdateNumericPropertyBV((BVSparseNode*)updatedPropsBVHead);
 
         return S_OK;
     });

+ 14 - 35
lib/Runtime/Base/ThreadContext.cpp

@@ -170,8 +170,8 @@ ThreadContext::ThreadContext(AllocationPolicyManager * allocationPolicyManager,
     codeGenNumberThreadAllocator(nullptr),
     xProcNumberPageSegmentManager(nullptr),
 #endif
-    m_pendingJITProperties(nullptr),
-    m_reclaimedJITProperties(nullptr),
+    m_jitNumericProperties(nullptr),
+    m_jitNeedsPropertyUpdate(false),
 #if DYNAMIC_INTERPRETER_THUNK || defined(ASMJS_PLAT)
     thunkPageAllocators(allocationPolicyManager, /* allocXData */ false, /* virtualAllocator */ nullptr, GetCurrentProcess()),
 #endif
@@ -473,15 +473,10 @@ ThreadContext::~ThreadContext()
         }
 
 #if ENABLE_NATIVE_CODEGEN
-        if (this->m_pendingJITProperties != nullptr)
+        if (this->m_jitNumericProperties != nullptr)
         {
-            HeapDelete(this->m_pendingJITProperties);
-            this->m_pendingJITProperties = nullptr;
-        }
-        if (this->m_reclaimedJITProperties != nullptr)
-        {
-            HeapDelete(this->m_reclaimedJITProperties);
-            this->m_reclaimedJITProperties = nullptr;
+            HeapDelete(this->m_jitNumericProperties);
+            this->m_jitNumericProperties = nullptr;
         }
 #endif
         // Unpin the memory for leak report so we don't report this as a leak.
@@ -950,19 +945,6 @@ void ThreadContext::InitializePropertyMaps()
         }
         this->propertyMap = nullptr;
 
-#if ENABLE_NATIVE_CODEGEN
-        if (this->m_pendingJITProperties != nullptr)
-        {
-            HeapDelete(this->m_pendingJITProperties);
-            this->m_pendingJITProperties = nullptr;
-        }
-        if (this->m_reclaimedJITProperties != nullptr)
-        {
-            HeapDelete(this->m_reclaimedJITProperties);
-            this->m_reclaimedJITProperties = nullptr;
-        }
-#endif
-
         this->caseInvariantPropertySet = nullptr;
         memset(propertyNamesDirect, 0, 128*sizeof(Js::PropertyRecord *));
         throw;
@@ -1121,15 +1103,12 @@ ThreadContext::AddPropertyRecordInternal(const Js::PropertyRecord * propertyReco
     propertyMap->Add(propertyRecord);
 
 #if ENABLE_NATIVE_CODEGEN
-    if (m_pendingJITProperties)
+    if (m_jitNumericProperties)
     {
-        Assert(m_reclaimedJITProperties);
         if (propertyRecord->IsNumeric())
         {
-            if (!m_reclaimedJITProperties->Remove(propertyRecord->GetPropertyId()))
-            {
-                m_pendingJITProperties->Prepend(propertyRecord->GetPropertyId());
-            }
+            m_jitNumericProperties->Set(propertyRecord->GetPropertyId());
+            m_jitNeedsPropertyUpdate = true;
         }
     }
 #endif
@@ -1287,10 +1266,10 @@ void ThreadContext::InvalidatePropertyRecord(const Js::PropertyRecord * property
 {
     InternalInvalidateProtoTypePropertyCaches(propertyRecord->GetPropertyId());     // use the internal version so we don't check for active property id
 #if ENABLE_NATIVE_CODEGEN
-    if (propertyRecord->IsNumeric() && m_pendingJITProperties && !m_pendingJITProperties->Remove(propertyRecord->GetPropertyId()))
+    if (propertyRecord->IsNumeric() && m_jitNumericProperties)
     {
-        // if it wasn't pending, that means it was already sent to the jit, so add to list that jit needs to reclaim
-        m_reclaimedJITProperties->PrependNoThrow(&HeapAllocator::Instance, propertyRecord->GetPropertyId());
+        m_jitNumericProperties->Clear(propertyRecord->GetPropertyId());
+        m_jitNeedsPropertyUpdate = true;
     }
 #endif
     this->propertyMap->Remove(propertyRecord);
@@ -2006,14 +1985,14 @@ ThreadContext::EnsureJITThreadContext(bool allowPrereserveAlloc)
     contextData.simdTempAreaBaseAddr = (intptr_t)GetSimdTempArea();
 #endif
 
-    m_reclaimedJITProperties = HeapNew(PropertyList, &HeapAllocator::Instance);
-    m_pendingJITProperties = HeapNew(PropertyList, &HeapAllocator::Instance);
+    m_jitNumericProperties = HeapNew(BVSparse<HeapAllocator>, &HeapAllocator::Instance);
     
     for (auto iter = propertyMap->GetIterator(); iter.IsValid(); iter.MoveNext())
     {
         if (iter.CurrentKey()->IsNumeric())
         {
-            m_pendingJITProperties->Prepend(iter.CurrentKey()->GetPropertyId());
+            m_jitNumericProperties->Set(iter.CurrentKey()->GetPropertyId());
+            m_jitNeedsPropertyUpdate = true;
         }
     }
 

+ 10 - 10
lib/Runtime/Base/ThreadContext.h

@@ -475,8 +475,6 @@ public:
         Js::PropertyRecordStringHashComparer, JsUtil::SimpleHashedEntry, JsUtil::AsymetricResizeLock> PropertyMap;
     PropertyMap * propertyMap;
 
-    typedef SListCounted<Js::PropertyId, HeapAllocator> PropertyList;
-
     typedef JsUtil::BaseHashSet<Js::CaseInvariantPropertyListWithHashCode*, Recycler, PowerOf2SizePolicy, Js::CaseInvariantPropertyListWithHashCode*, JsUtil::NoCaseComparer, JsUtil::SimpleDictionaryEntry>
         PropertyNoCaseSetType;
     typedef JsUtil::WeaklyReferencedKeyDictionary<Js::Type, bool> TypeHashSet;
@@ -488,18 +486,20 @@ private:
     intptr_t m_prereservedRegionAddr;
 
 #if ENABLE_NATIVE_CODEGEN
-    PropertyList * m_pendingJITProperties;
-    PropertyList  * m_reclaimedJITProperties;
+    BVSparse<HeapAllocator> * m_jitNumericProperties;
+    bool m_jitNeedsPropertyUpdate;
 public:
-
-    PropertyList * GetReclaimedJITProperties() const
+    BVSparse<HeapAllocator> * GetJITNumericProperties() const
     {
-        return m_reclaimedJITProperties;
+        return m_jitNumericProperties;
     }
-
-    PropertyList * GetPendingJITProperties() const
+    bool JITNeedsPropUpdate() const
+    {
+        return m_jitNeedsPropertyUpdate;
+    }
+    void ResetJITNeedsPropUpdate()
     {
-        return m_pendingJITProperties;
+        m_jitNeedsPropertyUpdate = false;
     }
 
     static void SetJITConnectionInfo(HANDLE processHandle, void* serverSecurityDescriptor, UUID connectionId);