Forráskód Böngészése

fixes for enabling write barrier testing on windows

restore the compiler assert, thanks @CurtisMan for the better solution
get the hard limit of stack to initialize the card table, instead a hard coded 1 page more
some other minor fixes
Lei Shi 9 éve
szülő
commit
cd044300ac

+ 1 - 1
lib/Common/Memory/Recycler.cpp

@@ -995,8 +995,8 @@ Recycler::GetRecyclerPageAllocator()
     {
         return &this->recyclerWithBarrierPageAllocator;
     }
-#endif
     else
+#endif
     {
 #ifdef RECYCLER_WRITE_WATCH
         return &this->recyclerPageAllocator;

+ 5 - 4
lib/Common/Memory/Recycler.inl

@@ -93,11 +93,12 @@ Recycler::AllocWithAttributesInlined(DECLSPEC_GUARD_OVERFLOW size_t size)
 
     char* memBlock = nullptr;
 #if GLOBAL_ENABLE_WRITE_BARRIER
-    if (CONFIG_FLAG(ForceSoftwareWriteBarrier)
-        && ((attributes & LeafBit) != LeafBit
-            || (attributes & FinalizeBit) == FinalizeBit)) // there's no Finalize Leaf bucket
+    if (CONFIG_FLAG(ForceSoftwareWriteBarrier) && (attributes & InternalObjectInfoBitMask ) != LeafBit)
     {
-        memBlock = RealAlloc<(ObjectInfoBits)((attributes | WithBarrierBit) & InternalObjectInfoBitMask), nothrow>(&autoHeap, allocSize);
+        // explicitly adding "& ~LeafBit" to avoid the CompilerAssert in SmallFinalizableHeapBucket.h
+        // pure LeafBit going through the else below, and use the LeafBit specialization to get the bucket
+        // if there FinalizeBit, it goes through FinalizeWithBarrier bucket, whatever there's LeafBit or not
+        memBlock = RealAlloc<(ObjectInfoBits)(((attributes | WithBarrierBit) & ~LeafBit) & InternalObjectInfoBitMask), nothrow>(&autoHeap, allocSize);
     }
     else
 #endif

+ 9 - 7
lib/Common/Memory/RecyclerWriteBarrierManager.cpp

@@ -56,10 +56,17 @@ X64WriteBarrierCardTableManager::OnThreadInit()
 
     // xplat-todo: Replace this on Windows too with GetCurrentThreadStackBounds
 #ifdef _WIN32
+    // check StackProber.cpp for the stack pages layout information
     NT_TIB* teb = (NT_TIB*) ::NtCurrentTeb();
-
     char* stackBase = (char*) teb->StackBase;
-    char* stackEnd  = (char*) teb->StackLimit;
+    char* stackEnd = (char*)__readgsqword(0x1478); // 0x1478 is offset of DeallocationStack field on ntdll!_TEB on x64
+                                                   // this is undocumented, verifying with following code
+#if DBG
+    MEMORY_BASIC_INFORMATION memInfo;
+    VirtualQuery((LPCVOID)teb->StackLimit, &memInfo, sizeof(memInfo));
+    Assert((char*)memInfo.AllocationBase == stackEnd);
+    Assert(memInfo.AllocationProtect == PAGE_READWRITE);
+#endif
 #else
     ULONG_PTR stackBase = 0;
     ULONG_PTR stackEnd = 0;
@@ -71,11 +78,6 @@ X64WriteBarrierCardTableManager::OnThreadInit()
     this->_stacklimit = (char*)stackEnd;
 #endif
 
-    // on Windows server 2012 stack limit can expand with process running, and causes
-    // accessing uncommitted card table page.
-    // TODO: use VirtualQuery twice to get the max possible stack limit
-    stackEnd -= AutoSystemInfo::PageSize * AutoSystemInfo::PageSize;
-
     size_t numPages = (stackBase - stackEnd) / AutoSystemInfo::PageSize;
     // stackEnd is the lower boundary
     bool ret = OnSegmentAlloc((char*) stackEnd, numPages);

+ 2 - 1
lib/Common/Memory/SmallFinalizableHeapBucket.h

@@ -81,6 +81,7 @@ template <ObjectInfoBits attributes, class TBlockAttributes>
 class SmallHeapBlockType
 {
 public:
+    CompileAssert(attributes & FinalizeBit);
     typedef SmallFinalizableHeapBlockT<TBlockAttributes> BlockType;
     typedef SmallFinalizableHeapBucketT<TBlockAttributes> BucketType;
 };
@@ -173,7 +174,7 @@ class HeapBucketGroup
         typedef typename SmallHeapBlockType<objectAttributes, TBlockAttributes>::BucketType BucketType;
         static BucketType& GetBucket(HeapBucketGroup<TBlockAttributes> * heapBucketGroup)
         {
-            Assert(objectAttributes & FinalizeBit);
+            CompileAssert(objectAttributes & FinalizeBit);
             return heapBucketGroup->finalizableHeapBucket;
         }
     };

+ 1 - 1
lib/Runtime/Language/ObjTypeSpecFldInfo.cpp

@@ -533,7 +533,7 @@ namespace Js
 
         // Need to create a local array here and not allocate one from the recycler,
         // as the allocation may trigger a GC which can clear the inline caches.
-        FixedFieldInfo localFixedFieldInfoArray[Js::DynamicProfileInfo::maxPolymorphicInliningSize] = { 0 };
+        FixedFieldInfo localFixedFieldInfoArray[Js::DynamicProfileInfo::maxPolymorphicInliningSize] = { };
 
         // For polymorphic field loads we only support fixed functions on prototypes. This helps keep the equivalence check helper simple.
         // Since all types in the polymorphic cache share the same prototype, it's enough to grab the fixed function from the prototype object.