Explorar o código

swb: WriteBarrierPtr ctor, direct SetVirtualTable

We have initialization `... = {0}`. When the target contains fields of type
WriteBarrierPtr, this calls the default `WriteBarrierPtr()` constructor
for each of such fields. To be compatible the default constructor should
zero itself. Changed default `WriteBarrierPtr()` to zero its wrapped ptr.

However this reveals a side effect of SetVirtualTable implementation. We
use `placement new` to change an object's virtual table. `placement new`
causes constructors of the object and base classes to be called, and in
turn the default constructor of any fields are called. Above change causes
fields to be zeroed unexpectedly while changing virtual table.

Fixed by changing SetVirtualTable to directly change virtual table value.
Jianchun Xu %!s(int64=9) %!d(string=hai) anos
pai
achega
ec76597f46
Modificáronse 3 ficheiros con 23 adicións e 36 borrados
  1. 5 3
      lib/Common/Common/vtinfo.h
  2. 15 10
      lib/Common/Common/vtinfo.inl
  3. 3 23
      lib/Common/Memory/RecyclerPointers.h

+ 5 - 3
lib/Common/Common/vtinfo.h

@@ -87,6 +87,8 @@ class VirtualTableInfoBase
 {
 public:
     static INT_PTR GetVirtualTable(void * ptr) { return (*(INT_PTR*)ptr); }
+protected:
+    static void SetVirtualTable(void * ptr, INT_PTR vt) { *(INT_PTR*)ptr = vt; }
 };
 
 template <typename T>
@@ -94,15 +96,15 @@ class VirtualTableInfo : public VirtualTableInfoBase
 {
 public:
     static INT_PTR const Address;
-    static INT_PTR RegisterVirtualTable(INT_PTR vtable);
-    static void SetVirtualTable(void * ptr) { new (ptr) T(VirtualTableInfoCtorValue); }
+    static INT_PTR RegisterVirtualTable();
+    static void SetVirtualTable(void * ptr);
     static bool HasVirtualTable(void * ptr) { return GetVirtualTable(ptr) == Address; }
 };
 
 #if !defined(USED_IN_STATIC_LIB)
 #pragma warning(disable:4238) // class rvalue used as lvalue
 template <typename T>
-INT_PTR const VirtualTableInfo<T>::Address = VirtualTableInfo<T>::RegisterVirtualTable(*(INT_PTR const*)&T(VirtualTableInfoCtorValue));
+INT_PTR const VirtualTableInfo<T>::Address = VirtualTableInfo<T>::RegisterVirtualTable();
 #endif
 
 #define DEFINE_VTABLE_CTOR_NOBASE_ABSTRACT(T) \

+ 15 - 10
lib/Common/Common/vtinfo.inl

@@ -4,14 +4,13 @@
 //-------------------------------------------------------------------------------------------------------
 #pragma once
 
-// Note: VirtualTableInfo<T>::RegisterVirtualTable can be put into .cpp file but for that
-// we'll have to define quite a lot of explicit template instantiations for all classes that
-// use DEFINE_VTABLE_CTOR, to fix unresolved externals.
-#if DBG
 // static
 template <typename T>
-inline INT_PTR VirtualTableInfo<T>::RegisterVirtualTable(INT_PTR vtable)
+inline INT_PTR VirtualTableInfo<T>::RegisterVirtualTable()
 {
+    INT_PTR vtable = *(INT_PTR const*)&T(VirtualTableInfoCtorValue);
+
+#if DBG
 #if ENABLE_VALIDATE_VTABLE_CTOR
     //printf("m_vtableMapHash->Add(VirtualTableInfo<%s>::Address, dummy);\n", typeid(T).name());
 #endif
@@ -19,13 +18,19 @@ inline INT_PTR VirtualTableInfo<T>::RegisterVirtualTable(INT_PTR vtable)
     {
         VirtualTableRegistry::Add(vtable, typeid(T).name());
     }
+#endif
+
     return vtable;
 }
-#else
-// static
+
 template <typename T>
-inline INT_PTR VirtualTableInfo<T>::RegisterVirtualTable(INT_PTR vtable)
+inline void VirtualTableInfo<T>::SetVirtualTable(void * ptr)
 {
-    return vtable;
+    VirtualTableInfoBase::SetVirtualTable(ptr,
+#ifdef _MSC_VER  // work around VC linker bug
+        *(INT_PTR const*)&T(VirtualTableInfoCtorValue)
+#else
+        Address
+#endif
+    );
 }
-#endif // DBG

+ 3 - 23
lib/Common/Memory/RecyclerPointers.h

@@ -227,7 +227,7 @@ template <typename T>
 class NoWriteBarrierField
 {
 public:
-    NoWriteBarrierField() {}
+    NoWriteBarrierField() : value() {}
     explicit NoWriteBarrierField(T const& value) : value(value) {}
 
     // Getters
@@ -255,7 +255,7 @@ template <typename T>
 class NoWriteBarrierPtr
 {
 public:
-    NoWriteBarrierPtr() {}
+    NoWriteBarrierPtr() : value(nullptr) {}
     NoWriteBarrierPtr(T * value) : value(value) {}
 
     // Getters
@@ -307,7 +307,7 @@ template <typename T>
 class WriteBarrierPtr
 {
 public:
-    WriteBarrierPtr() {}
+    WriteBarrierPtr() : ptr(nullptr) {}
     WriteBarrierPtr(T * ptr)
     {
         // WriteBarrier
@@ -396,26 +396,6 @@ public:
         return result;
     }
 
-    static void MoveArray(WriteBarrierPtr * dst, WriteBarrierPtr * src, size_t count)
-    {
-        memmove((void *)dst, src, sizeof(WriteBarrierPtr) * count);
-        WriteBarrier(dst, count);
-    }
-    static void CopyArray(WriteBarrierPtr * dst, size_t dstCount, T* src, size_t srcCount)
-    {
-        js_memcpy_s((void *)dst, sizeof(WriteBarrierPtr) * dstCount, src, sizeof(T *) * srcCount);
-        WriteBarrier(dst, dstCount);
-    }
-    static void CopyArray(WriteBarrierPtr * dst, size_t dstCount, WriteBarrierPtr const* src, size_t srcCount)
-    {
-        js_memcpy_s((void *)dst, sizeof(WriteBarrierPtr) * dstCount, src, sizeof(WriteBarrierPtr) * srcCount);
-        WriteBarrier(dst, dstCount);
-    }
-    static void ClearArray(WriteBarrierPtr * dst, size_t count)
-    {
-        // assigning NULL don't need write barrier, just cast it and null it out
-        memset((void *)dst, 0, sizeof(WriteBarrierPtr<T>) * count);
-    }
 private:
     T * ptr;
 };