Переглянути джерело

swb: write barrier annotations 1

Change CopyArray/MoveArray policy. Now they template specialize on
element type only, and specializes differently to Fields. They only
trigger write barrier if element type is WriteBarrierPtr. (We choose
to wrap element type with WriteBarrierPtr if needed so that we don't
worry about individual item operations.)

Change WriteBarrierPtr::AddressOf to return its address (instead of
ptr field's address). Add global `AddressOf()` function. Use to pass
WriteBarrierPtr by reference when calling a function that may change
the field value.

stringification fix in `WriteBarrierMacros.h`.

This commit contains some annotations that involved more manual fixes.
Jianchun Xu 9 роки тому
батько
коміт
fd0a121a0b
31 змінених файлів з 856 додано та 595 видалено
  1. 10 6
      lib/Common/DataStructures/BaseDictionary.h
  2. 223 125
      lib/Common/DataStructures/SparseBitVector.h
  3. 2 2
      lib/Common/Exceptions/JavascriptException.h
  4. 139 16
      lib/Common/Memory/RecyclerPointers.h
  5. 5 5
      lib/Common/Memory/RecyclerWeakReference.h
  6. 8 11
      lib/Common/Memory/WriteBarrierMacros.h
  7. 13 5
      lib/JITIDL/JITTypes.h
  8. 10 10
      lib/Parser/OctoquadIdentifier.h
  9. 3 3
      lib/Runtime/Base/FunctionBody.cpp
  10. 3 3
      lib/Runtime/Base/ScriptContext.cpp
  11. 27 27
      lib/Runtime/Base/ThreadContext.h
  12. 8 2
      lib/Runtime/Language/DynamicProfileInfo.cpp
  13. 54 37
      lib/Runtime/Language/DynamicProfileInfo.h
  14. 2 12
      lib/Runtime/Language/FunctionCodeGenJitTimeData.cpp
  15. 2 2
      lib/Runtime/Language/InterpreterStackFrame.cpp
  16. 1 1
      lib/Runtime/Language/JavascriptExceptionOperators.cpp
  17. 1 1
      lib/Runtime/Language/JavascriptOperators.cpp
  18. 5 1
      lib/Runtime/Language/SourceTextModuleRecord.cpp
  19. 8 7
      lib/Runtime/Library/ConcatString.cpp
  20. 11 11
      lib/Runtime/Library/ConcatString.h
  21. 4 1
      lib/Runtime/Library/ES5ArrayIndexEnumerator.cpp
  22. 4 2
      lib/Runtime/Library/IteratorObjectEnumerator.cpp
  23. 23 22
      lib/Runtime/Library/JavascriptArray.cpp
  24. 8 6
      lib/Runtime/Library/JavascriptArray.h
  25. 17 15
      lib/Runtime/Library/JavascriptArray.inl
  26. 15 13
      lib/Runtime/Library/JavascriptLibrary.cpp
  27. 238 238
      lib/Runtime/Library/JavascriptLibrary.h
  28. 4 3
      lib/Runtime/Library/RegexHelper.cpp
  29. 2 2
      lib/Runtime/Library/SparseArraySegment.h
  30. 5 5
      lib/Runtime/Library/SparseArraySegment.inl
  31. 1 1
      lib/Runtime/SerializableFunctionFields.h

+ 10 - 6
lib/Common/DataStructures/BaseDictionary.h

@@ -181,8 +181,9 @@ namespace JsUtil
             freeList = other.freeList;
             freeList = other.freeList;
             freeCount = other.freeCount;
             freeCount = other.freeCount;
 
 
-            CopyArray<TAllocator>(buckets, bucketCount, other.buckets, bucketCount);
-            CopyArray<TAllocator, EntryType, ValueType>(entries, size, other.entries, size);
+            CopyArray(buckets, bucketCount, other.buckets, bucketCount);
+            CopyArray<EntryType, Field(ValueType, TAllocator)>(
+                entries, size, other.entries, size);
 
 
 #if PROFILE_DICTIONARY
 #if PROFILE_DICTIONARY
             stats = DictionaryStats::Create(typeid(this).name(), size);
             stats = DictionaryStats::Create(typeid(this).name(), size);
@@ -712,8 +713,9 @@ namespace JsUtil
             freeList = other->freeList;
             freeList = other->freeList;
             freeCount = other->freeCount;
             freeCount = other->freeCount;
 
 
-            CopyArray<TAllocator>(buckets, bucketCount, other->buckets, bucketCount);
-            CopyArray<TAllocator, EntryType, ValueType>(entries, size, other->entries, size);
+            CopyArray(buckets, bucketCount, other->buckets, bucketCount);
+            CopyArray<EntryType, Field(ValueType, TAllocator)>(
+                entries, size, other->entries, size);
 
 
 #if PROFILE_DICTIONARY
 #if PROFILE_DICTIONARY
             stats = DictionaryStats::Create(typeid(this).name(), size);
             stats = DictionaryStats::Create(typeid(this).name(), size);
@@ -1018,7 +1020,8 @@ namespace JsUtil
             {
             {
                 // no need to rehash
                 // no need to rehash
                 newEntries = AllocateEntries(newSize);
                 newEntries = AllocateEntries(newSize);
-                CopyArray<TAllocator, EntryType, ValueType>(newEntries, newSize, entries, count);
+                CopyArray<EntryType, Field(ValueType, TAllocator)>(
+                    newEntries, newSize, entries, count);
 
 
                 DeleteEntries(entries, size);
                 DeleteEntries(entries, size);
 
 
@@ -1028,7 +1031,8 @@ namespace JsUtil
             }
             }
 
 
             Allocate(&newBuckets, &newEntries, newBucketCount, newSize);
             Allocate(&newBuckets, &newEntries, newBucketCount, newSize);
-            CopyArray<TAllocator, EntryType, ValueType>(newEntries, newSize, entries, count);
+            CopyArray<EntryType, Field(ValueType, TAllocator)>(
+                newEntries, newSize, entries, count);
 
 
             // When TAllocator is of type Recycler, it is possible that the Allocate above causes a collection, which
             // When TAllocator is of type Recycler, it is possible that the Allocate above causes a collection, which
             // in turn can cause entries in the dictionary to be removed - i.e. the dictionary contains weak references
             // in turn can cause entries in the dictionary to be removed - i.e. the dictionary contains weak references

+ 223 - 125
lib/Common/DataStructures/SparseBitVector.h

@@ -9,7 +9,7 @@ typedef  BVUnit64 SparseBVUnit;
 #define FOREACH_BITSET_IN_SPARSEBV(index, bv) \
 #define FOREACH_BITSET_IN_SPARSEBV(index, bv) \
 { \
 { \
     BVIndex index; \
     BVIndex index; \
-    for(BVSparseNode * _curNode = (bv)->head; _curNode != 0 ; _curNode = _curNode->next) \
+    for(auto * _curNode = (bv)->head; _curNode != 0 ; _curNode = _curNode->next) \
     { \
     { \
         BVIndex _offset; \
         BVIndex _offset; \
         BVIndex _startIndex = _curNode->startIndex; \
         BVIndex _startIndex = _curNode->startIndex; \
@@ -57,11 +57,12 @@ typedef  BVUnit64 SparseBVUnit;
 
 
 #define SPARSEBV_CLEAR_CURRENT_BIT() _curNodeEdit->data.Clear(_offset)
 #define SPARSEBV_CLEAR_CURRENT_BIT() _curNodeEdit->data.Clear(_offset)
 
 
+template <class TAllocator>
 struct BVSparseNode
 struct BVSparseNode
 {
 {
-    BVSparseNode *  next;
-    BVIndex         startIndex;
-    SparseBVUnit    data;
+    Field(BVSparseNode*, TAllocator)    next;
+    Field(BVIndex)                      startIndex;
+    Field(SparseBVUnit)                 data;
 
 
     BVSparseNode(BVIndex beginIndex, BVSparseNode * nextNode);
     BVSparseNode(BVIndex beginIndex, BVSparseNode * nextNode);
 
 
@@ -80,24 +81,20 @@ struct BVSparseNode
 #endif
 #endif
 };
 };
 
 
-#if defined(_M_ARM64) || defined(_M_X64)
-CompileAssert(sizeof(BVSparseNode) == 24); // Performance assert, BVSparseNode is heavily used in the backend, do perf measurement before changing this.
-#else
-CompileAssert(sizeof(BVSparseNode) == 16);
-#endif
-
 template <class TAllocator>
 template <class TAllocator>
 class BVSparse
 class BVSparse
 {
 {
+    typedef BVSparseNode<TAllocator> BVSparseNode;
+
 // Data
 // Data
 public:
 public:
-            BVSparseNode *      head;
+    Field(BVSparseNode*, TAllocator)    head;
 
 
 private:
 private:
-            TAllocator *        alloc;
-            BVSparseNode **     lastUsedNodePrevNextField;
+    FieldNoBarrier(TAllocator*)         alloc;
+    FieldNoBarrier(Field(BVSparseNode*, TAllocator)*) lastUsedNodePrevNextField;
 
 
-    static const SparseBVUnit       s_EmptyUnit;
+    static const SparseBVUnit s_EmptyUnit;
 
 
 // Constructor
 // Constructor
 public:
 public:
@@ -107,16 +104,16 @@ public:
 // Implementation
 // Implementation
 protected:
 protected:
     template <class TOtherAllocator>
     template <class TOtherAllocator>
-    static  void            AssertBV(const BVSparse<TOtherAllocator> * bv);
+    static  void    AssertBV(const BVSparse<TOtherAllocator> * bv);
 
 
-
-            SparseBVUnit *      BitsFromIndex(BVIndex i, bool create = true);
-            const SparseBVUnit *      BitsFromIndex(BVIndex i) const;
-            BVSparseNode*   NodeFromIndex(BVIndex i, BVSparseNode *** prevNextFieldOut, bool create = true);
-            const BVSparseNode*   NodeFromIndex(BVIndex i, BVSparseNode *const** prevNextFieldOut) const;
-            BVSparseNode *  DeleteNode(BVSparseNode *node, bool bResetLastUsed = true);
-            void            QueueInFreeList(BVSparseNode* node);
-            BVSparseNode *  Allocate(const BVIndex searchIndex, BVSparseNode *prevNode);
+    SparseBVUnit *  BitsFromIndex(BVIndex i, bool create = true);
+    const SparseBVUnit * BitsFromIndex(BVIndex i) const;
+    BVSparseNode*   NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator)** prevNextFieldOut,
+                                  bool create = true);
+    const BVSparseNode* NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator) const** prevNextFieldOut) const;
+    BVSparseNode *  DeleteNode(BVSparseNode *node, bool bResetLastUsed = true);
+    void            QueueInFreeList(BVSparseNode* node);
+    BVSparseNode *  Allocate(const BVIndex searchIndex, BVSparseNode *prevNode);
 
 
     template<void (SparseBVUnit::*callback)(SparseBVUnit)>
     template<void (SparseBVUnit::*callback)(SparseBVUnit)>
     void for_each(const BVSparse<TAllocator> *bv2);
     void for_each(const BVSparse<TAllocator> *bv2);
@@ -126,78 +123,179 @@ protected:
 
 
 // Methods
 // Methods
 public:
 public:
-
-            BOOLEAN         operator[](BVIndex i) const;
-            BOOLEAN         Test(BVIndex i) const;
-            BVIndex         GetNextBit(BVIndex i) const;
-            BVIndex         GetNextBit(BVSparseNode * node) const;
-
-            BOOLEAN         TestEmpty() const;
-            BOOLEAN         TestAndSet(BVIndex i);
-            BOOLEAN         TestAndClear(BVIndex i);
-            void            Set(BVIndex i);
-            void            Clear(BVIndex i);
-            void            Compliment(BVIndex i);
-
-
-            // this |= bv;
-            void            Or(const BVSparse<TAllocator> *bv);
-            // this = bv1 | bv2;
-            void            Or(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
-            // newBv = this | bv;
-            BVSparse<TAllocator> *      OrNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
-            BVSparse<TAllocator> *      OrNew(const BVSparse<TAllocator> *bv) const { return this->OrNew(bv, this->alloc); }
-
-            // this &= bv;
-            void            And(const BVSparse<TAllocator> *bv);
-            // this = bv1 & bv2;
-            void            And(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
-            // newBv = this & bv;
-            BVSparse<TAllocator> *      AndNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
-            BVSparse<TAllocator> *      AndNew(const BVSparse<TAllocator> *bv) const { return this->AndNew(bv, this->alloc); }
-
-            // this ^= bv;
-            void            Xor(const BVSparse<TAllocator> *bv);
-            // this = bv1 ^ bv2;
-            void            Xor(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
-            // newBv = this ^ bv;
-            BVSparse<TAllocator> *      XorNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
-            BVSparse<TAllocator> *      XorNew(const BVSparse<TAllocator> *bv) const { return this->XorNew(bv, this->alloc); }
-
-            // this -= bv;
-            void            Minus(const BVSparse<TAllocator> *bv);
-            // this = bv1 - bv2;
-            void            Minus(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
-            // newBv = this - bv;
-            BVSparse<TAllocator> *      MinusNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
-            BVSparse<TAllocator> *      MinusNew(const BVSparse<TAllocator> *bv) const { return this->MinusNew(bv, this->alloc); }
-
-            template <class TSrcAllocator>
-            void            Copy(const BVSparse<TSrcAllocator> *bv);
-            BVSparse<TAllocator> *      CopyNew(TAllocator* allocator) const;
-            BVSparse<TAllocator> *      CopyNew() const;
-            void            ComplimentAll();
-            void            ClearAll();
-
-            BVIndex         Count() const;
-            bool            IsEmpty() const;
-            bool            Equal(BVSparse<TAllocator> const * bv) const;
-
-            // this & bv != empty
-            bool            Test(BVSparse const * bv) const;
-
-            // Needed for the VS NatVis Extension
+    BOOLEAN         operator[](BVIndex i) const;
+    BOOLEAN         Test(BVIndex i) const;
+    BVIndex         GetNextBit(BVIndex i) const;
+    BVIndex         GetNextBit(BVSparseNode * node) const;
+
+    BOOLEAN         TestEmpty() const;
+    BOOLEAN         TestAndSet(BVIndex i);
+    BOOLEAN         TestAndClear(BVIndex i);
+    void            Set(BVIndex i);
+    void            Clear(BVIndex i);
+    void            Compliment(BVIndex i);
+
+
+    // this |= bv;
+    void            Or(const BVSparse<TAllocator> *bv);
+    // this = bv1 | bv2;
+    void            Or(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
+    // newBv = this | bv;
+    BVSparse<TAllocator> *      OrNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
+    BVSparse<TAllocator> *      OrNew(const BVSparse<TAllocator> *bv) const { return this->OrNew(bv, this->alloc); }
+
+    // this &= bv;
+    void            And(const BVSparse<TAllocator> *bv);
+    // this = bv1 & bv2;
+    void            And(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
+    // newBv = this & bv;
+    BVSparse<TAllocator> *      AndNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
+    BVSparse<TAllocator> *      AndNew(const BVSparse<TAllocator> *bv) const { return this->AndNew(bv, this->alloc); }
+
+    // this ^= bv;
+    void            Xor(const BVSparse<TAllocator> *bv);
+    // this = bv1 ^ bv2;
+    void            Xor(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
+    // newBv = this ^ bv;
+    BVSparse<TAllocator> *      XorNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
+    BVSparse<TAllocator> *      XorNew(const BVSparse<TAllocator> *bv) const { return this->XorNew(bv, this->alloc); }
+
+    // this -= bv;
+    void            Minus(const BVSparse<TAllocator> *bv);
+    // this = bv1 - bv2;
+    void            Minus(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
+    // newBv = this - bv;
+    BVSparse<TAllocator> *      MinusNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
+    BVSparse<TAllocator> *      MinusNew(const BVSparse<TAllocator> *bv) const { return this->MinusNew(bv, this->alloc); }
+
+    template <class TSrcAllocator>
+    void            Copy(const BVSparse<TSrcAllocator> *bv);
+    BVSparse<TAllocator> *      CopyNew(TAllocator* allocator) const;
+    BVSparse<TAllocator> *      CopyNew() const;
+    void            ComplimentAll();
+    void            ClearAll();
+
+    BVIndex         Count() const;
+    bool            IsEmpty() const;
+    bool            Equal(BVSparse<TAllocator> const * bv) const;
+
+    // this & bv != empty
+    bool            Test(BVSparse const * bv) const;
+
+    // Needed for the VS NatVis Extension
 #ifdef _WIN32
 #ifdef _WIN32
-            void            ToString(__out_ecount(strSize) char *const str, const size_t strSize) const;
-            template<class F> void ToString(__out_ecount(strSize) char *const str, const size_t strSize, const F ReadNode) const;
+    void            ToString(__out_ecount(strSize) char *const str, const size_t strSize) const;
+    template<class F> void ToString(__out_ecount(strSize) char *const str, const size_t strSize, const F ReadNode) const;
 #endif
 #endif
 
 
-            TAllocator *    GetAllocator() const { return alloc; }
+    TAllocator *    GetAllocator() const { return alloc; }
 #if DBG_DUMP
 #if DBG_DUMP
-            void            Dump() const;
+    void            Dump() const;
 #endif
 #endif
 };
 };
 
 
+
+template <class TAllocator>
+BVSparseNode<TAllocator>::BVSparseNode(BVIndex beginIndex, BVSparseNode<TAllocator> * nextNode) :
+    startIndex(beginIndex),
+    data(0),
+    next(nextNode)
+{
+    // Performance assert, BVSparseNode is heavily used in the backend, do perf
+    // measurement before changing this.
+#if defined(_M_ARM64) || defined(_M_X64)
+    CompileAssert(sizeof(BVSparseNode) == 24);
+#else
+    CompileAssert(sizeof(BVSparseNode) == 16);
+#endif
+}
+
+template <class TAllocator>
+void BVSparseNode<TAllocator>::init(BVIndex beginIndex, BVSparseNode<TAllocator> * nextNode)
+{
+    this->startIndex = beginIndex;
+    this->data = 0;
+    this->next = nextNode;
+}
+
+#ifdef _WIN32
+template <class TAllocator>
+bool BVSparseNode<TAllocator>::ToString(
+    __out_ecount(strSize) char *const str,
+    const size_t strSize,
+    size_t *const writtenLengthRef,
+    const bool isInSequence,
+    const bool isFirstInSequence,
+    const bool isLastInSequence) const
+{
+    Assert(str);
+    Assert(!isFirstInSequence || isInSequence);
+    Assert(!isLastInSequence || isInSequence);
+
+    if (strSize == 0)
+    {
+        if (writtenLengthRef)
+        {
+            *writtenLengthRef = 0;
+        }
+        return false;
+    }
+    str[0] = '\0';
+
+    const size_t reservedLength = _countof(", ...}");
+    if (strSize <= reservedLength)
+    {
+        if (writtenLengthRef)
+        {
+            *writtenLengthRef = 0;
+        }
+        return false;
+    }
+
+    size_t length = 0;
+    if (!isInSequence || isFirstInSequence)
+    {
+        str[length++] = '{';
+    }
+
+    bool insertComma = isInSequence && !isFirstInSequence;
+    char tempStr[13];
+    for (BVIndex i = data.GetNextBit(); i != BVInvalidIndex; i = data.GetNextBit(i + 1))
+    {
+        const size_t copyLength = sprintf_s(tempStr, insertComma ? ", %u" : "%u", startIndex + i);
+        Assert(static_cast<int>(copyLength) > 0);
+
+        Assert(strSize > length);
+        Assert(strSize - length > reservedLength);
+        if (strSize - length - reservedLength <= copyLength)
+        {
+            strcpy_s(&str[length], strSize - length, insertComma ? ", ...}" : "...}");
+            if (writtenLengthRef)
+            {
+                *writtenLengthRef = length + (insertComma ? _countof(", ...}") : _countof("...}"));
+            }
+            return false;
+        }
+
+        strcpy_s(&str[length], strSize - length - reservedLength, tempStr);
+        length += copyLength;
+        insertComma = true;
+    }
+    if (!isInSequence || isLastInSequence)
+    {
+        Assert(_countof("}") < strSize - length);
+        strcpy_s(&str[length], strSize - length, "}");
+        length += _countof("}");
+    }
+    if (writtenLengthRef)
+    {
+        *writtenLengthRef = length;
+    }
+    return true;
+}
+#endif
+
+
 #if DBG_DUMP
 #if DBG_DUMP
 template <typename T> void Dump(T const& t);
 template <typename T> void Dump(T const& t);
 
 
@@ -224,8 +322,9 @@ BVSparse<TAllocator>::BVSparse(TAllocator* allocator) :
    alloc(allocator),
    alloc(allocator),
    head(nullptr)
    head(nullptr)
 {
 {
-    this->lastUsedNodePrevNextField = &this->head;
+    this->lastUsedNodePrevNextField = AddressOf(this->head);
 }
 }
+
 template <class TAllocator>
 template <class TAllocator>
 void
 void
 BVSparse<TAllocator>::QueueInFreeList(BVSparseNode *curNode)
 BVSparse<TAllocator>::QueueInFreeList(BVSparseNode *curNode)
@@ -234,7 +333,7 @@ BVSparse<TAllocator>::QueueInFreeList(BVSparseNode *curNode)
 }
 }
 
 
 template <class TAllocator>
 template <class TAllocator>
-BVSparseNode *
+BVSparseNode<TAllocator> *
 BVSparse<TAllocator>::Allocate(const BVIndex searchIndex, BVSparseNode *nextNode)
 BVSparse<TAllocator>::Allocate(const BVIndex searchIndex, BVSparseNode *nextNode)
 {
 {
     return AllocatorNew(TAllocator, this->alloc, BVSparseNode, searchIndex, nextNode);
     return AllocatorNew(TAllocator, this->alloc, BVSparseNode, searchIndex, nextNode);
@@ -255,13 +354,13 @@ BVSparse<TAllocator>::~BVSparse()
 // a new node in the appropriate position.
 // a new node in the appropriate position.
 //
 //
 template <class TAllocator>
 template <class TAllocator>
-BVSparseNode *
-BVSparse<TAllocator>::NodeFromIndex(BVIndex i, BVSparseNode *** prevNextFieldOut, bool create)
+BVSparseNode<TAllocator> *
+BVSparse<TAllocator>::NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator)** prevNextFieldOut, bool create)
 {
 {
     const BVIndex searchIndex = SparseBVUnit::Floor(i);
     const BVIndex searchIndex = SparseBVUnit::Floor(i);
 
 
-    BVSparseNode ** prevNextField = this->lastUsedNodePrevNextField;
-    BVSparseNode * curNode = (*prevNextField);
+    Field(BVSparseNode*, TAllocator)* prevNextField = this->lastUsedNodePrevNextField;
+    BVSparseNode* curNode = *prevNextField;
     if (curNode != nullptr)
     if (curNode != nullptr)
     {
     {
         if (curNode->startIndex == searchIndex)
         if (curNode->startIndex == searchIndex)
@@ -272,19 +371,19 @@ BVSparse<TAllocator>::NodeFromIndex(BVIndex i, BVSparseNode *** prevNextFieldOut
 
 
         if (curNode->startIndex > searchIndex)
         if (curNode->startIndex > searchIndex)
         {
         {
-            prevNextField = &this->head;
+            prevNextField = AddressOf(this->head);
             curNode = this->head;
             curNode = this->head;
         }
         }
     }
     }
     else
     else
     {
     {
-        prevNextField = &this->head;
+        prevNextField = AddressOf(this->head);
         curNode = this->head;
         curNode = this->head;
     }
     }
 
 
     for (; curNode && searchIndex > curNode->startIndex; curNode = curNode->next)
     for (; curNode && searchIndex > curNode->startIndex; curNode = curNode->next)
     {
     {
-        prevNextField = &curNode->next;
+        prevNextField = AddressOf(curNode->next);
     }
     }
 
 
     if(curNode && searchIndex == curNode->startIndex)
     if(curNode && searchIndex == curNode->startIndex)
@@ -307,13 +406,13 @@ BVSparse<TAllocator>::NodeFromIndex(BVIndex i, BVSparseNode *** prevNextFieldOut
 }
 }
 
 
 template <class TAllocator>
 template <class TAllocator>
-const BVSparseNode *
-BVSparse<TAllocator>::NodeFromIndex(BVIndex i, BVSparseNode *const** prevNextFieldOut) const
+const BVSparseNode<TAllocator> *
+BVSparse<TAllocator>::NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator) const** prevNextFieldOut) const
 {
 {
     const BVIndex searchIndex = SparseBVUnit::Floor(i);
     const BVIndex searchIndex = SparseBVUnit::Floor(i);
 
 
-    BVSparseNode *const* prevNextField = &this->head;
-    const BVSparseNode * curNode = (*prevNextField);
+    Field(BVSparseNode*, TAllocator) const* prevNextField = AddressOf(this->head);
+    const BVSparseNode * curNode = *prevNextField;
     if (curNode != nullptr)
     if (curNode != nullptr)
     {
     {
         if (curNode->startIndex == searchIndex)
         if (curNode->startIndex == searchIndex)
@@ -324,19 +423,19 @@ BVSparse<TAllocator>::NodeFromIndex(BVIndex i, BVSparseNode *const** prevNextFie
 
 
         if (curNode->startIndex > searchIndex)
         if (curNode->startIndex > searchIndex)
         {
         {
-            prevNextField = &this->head;
+            prevNextField = AddressOf(this->head);
             curNode = this->head;
             curNode = this->head;
         }
         }
     }
     }
     else
     else
     {
     {
-        prevNextField = &this->head;
+        prevNextField = AddressOf(this->head);
         curNode = this->head;
         curNode = this->head;
     }
     }
 
 
     for (; curNode && searchIndex > curNode->startIndex; curNode = curNode->next)
     for (; curNode && searchIndex > curNode->startIndex; curNode = curNode->next)
     {
     {
-        prevNextField = &curNode->next;
+        prevNextField = AddressOf(curNode->next);
     }
     }
 
 
     if (curNode && searchIndex == curNode->startIndex)
     if (curNode && searchIndex == curNode->startIndex)
@@ -349,12 +448,11 @@ BVSparse<TAllocator>::NodeFromIndex(BVIndex i, BVSparseNode *const** prevNextFie
 }
 }
 
 
 
 
-
 template <class TAllocator>
 template <class TAllocator>
 SparseBVUnit *
 SparseBVUnit *
 BVSparse<TAllocator>::BitsFromIndex(BVIndex i, bool create)
 BVSparse<TAllocator>::BitsFromIndex(BVIndex i, bool create)
 {
 {
-    BVSparseNode ** prevNextField;
+    Field(BVSparseNode*, TAllocator)* prevNextField;
     BVSparseNode * node = NodeFromIndex(i, &prevNextField, create);
     BVSparseNode * node = NodeFromIndex(i, &prevNextField, create);
     if (node)
     if (node)
     {
     {
@@ -370,7 +468,7 @@ template <class TAllocator>
 const SparseBVUnit *
 const SparseBVUnit *
 BVSparse<TAllocator>::BitsFromIndex(BVIndex i) const
 BVSparse<TAllocator>::BitsFromIndex(BVIndex i) const
 {
 {
-    BVSparseNode *const* prevNextField;
+    Field(BVSparseNode*, TAllocator) const* prevNextField;
     const BVSparseNode * node = NodeFromIndex(i, &prevNextField);
     const BVSparseNode * node = NodeFromIndex(i, &prevNextField);
     if (node)
     if (node)
     {
     {
@@ -383,7 +481,7 @@ BVSparse<TAllocator>::BitsFromIndex(BVIndex i) const
 }
 }
 
 
 template <class TAllocator>
 template <class TAllocator>
-BVSparseNode *
+BVSparseNode<TAllocator> *
 BVSparse<TAllocator>::DeleteNode(BVSparseNode *node, bool bResetLastUsed)
 BVSparse<TAllocator>::DeleteNode(BVSparseNode *node, bool bResetLastUsed)
 {
 {
     BVSparseNode *next = node->next;
     BVSparseNode *next = node->next;
@@ -391,11 +489,11 @@ BVSparse<TAllocator>::DeleteNode(BVSparseNode *node, bool bResetLastUsed)
 
 
     if (bResetLastUsed)
     if (bResetLastUsed)
     {
     {
-        this->lastUsedNodePrevNextField = &this->head;
+        this->lastUsedNodePrevNextField = AddressOf(this->head);
     }
     }
     else
     else
     {
     {
-        Assert(this->lastUsedNodePrevNextField != &node->next);
+        Assert(this->lastUsedNodePrevNextField != AddressOf(node->next));
     }
     }
     return next;
     return next;
 }
 }
@@ -463,7 +561,7 @@ BVSparse<TAllocator>::ClearAll()
         QueueInFreeList(node);
         QueueInFreeList(node);
     }
     }
     this->head = nullptr;
     this->head = nullptr;
-    this->lastUsedNodePrevNextField = &this->head;
+    this->lastUsedNodePrevNextField = AddressOf(this->head);
 }
 }
 
 
 template <class TAllocator>
 template <class TAllocator>
@@ -477,7 +575,7 @@ template <class TAllocator>
 void
 void
 BVSparse<TAllocator>::Clear(BVIndex i)
 BVSparse<TAllocator>::Clear(BVIndex i)
 {
 {
-    BVSparseNode ** prevNextField;
+    Field(BVSparseNode*, TAllocator)* prevNextField;
     BVSparseNode * current = this->NodeFromIndex(i, &prevNextField, false /* create */);
     BVSparseNode * current = this->NodeFromIndex(i, &prevNextField, false /* create */);
     if(current)
     if(current)
     {
     {
@@ -525,7 +623,7 @@ template <class TAllocator>
 BOOLEAN
 BOOLEAN
 BVSparse<TAllocator>::TestAndClear(BVIndex i)
 BVSparse<TAllocator>::TestAndClear(BVIndex i)
 {
 {
-    BVSparseNode ** prevNextField;
+    Field(BVSparseNode*, TAllocator)* prevNextField;
     BVSparseNode * current = this->NodeFromIndex(i, &prevNextField, false /* create */);
     BVSparseNode * current = this->NodeFromIndex(i, &prevNextField, false /* create */);
     if (current == nullptr)
     if (current == nullptr)
     {
     {
@@ -557,14 +655,14 @@ void BVSparse<TAllocator>::for_each(const BVSparse *bv2)
 
 
           BVSparseNode * node1      = this->head;
           BVSparseNode * node1      = this->head;
     const BVSparseNode * node2      = bv2->head;
     const BVSparseNode * node2      = bv2->head;
-          BVSparseNode ** prevNodeNextField   = &this->head;
+          Field(BVSparseNode*, TAllocator)* prevNodeNextField = AddressOf(this->head);
 
 
     while(node1 != nullptr && node2 != nullptr)
     while(node1 != nullptr && node2 != nullptr)
     {
     {
         if(node2->startIndex == node1->startIndex)
         if(node2->startIndex == node1->startIndex)
         {
         {
             (node1->data.*callback)(node2->data);
             (node1->data.*callback)(node2->data);
-            prevNodeNextField = &node1->next;
+            prevNodeNextField = AddressOf(node1->next);
             node1 = node1->next;
             node1 = node1->next;
             node2 = node2->next;
             node2 = node2->next;
         }
         }
@@ -578,7 +676,7 @@ void BVSparse<TAllocator>::for_each(const BVSparse *bv2)
             }
             }
             else
             else
             {
             {
-                prevNodeNextField = &node1->next;
+                prevNodeNextField = AddressOf(node1->next);
                 node1 = node1->next;
                 node1 = node1->next;
             }
             }
 
 
@@ -590,7 +688,7 @@ void BVSparse<TAllocator>::for_each(const BVSparse *bv2)
                 BVSparseNode * newNode = Allocate(node2->startIndex, node1);
                 BVSparseNode * newNode = Allocate(node2->startIndex, node1);
                 (newNode->data.*callback)(node2->data);
                 (newNode->data.*callback)(node2->data);
                 *prevNodeNextField = newNode;
                 *prevNodeNextField = newNode;
-                prevNodeNextField = &newNode->next;
+                prevNodeNextField = AddressOf(newNode->next);
             }
             }
             node2 = node2->next;
             node2 = node2->next;
         }
         }
@@ -614,7 +712,7 @@ void BVSparse<TAllocator>::for_each(const BVSparse *bv2)
 
 
             (newNode->data.*callback)(node2->data);
             (newNode->data.*callback)(node2->data);
             node2       = node2->next;
             node2       = node2->next;
-            prevNodeNextField    = &newNode->next;
+            prevNodeNextField    = AddressOf(newNode->next);
         }
         }
     }
     }
 }
 }
@@ -631,7 +729,7 @@ void BVSparse<TAllocator>::for_each(const BVSparse *bv1, const BVSparse *bv2)
           BVSparseNode * node1      = bv1->head;
           BVSparseNode * node1      = bv1->head;
     const BVSparseNode * node2      = bv2->head;
     const BVSparseNode * node2      = bv2->head;
           BVSparseNode * lastNode   = nullptr;
           BVSparseNode * lastNode   = nullptr;
-          BVSparseNode ** prevNextField = &this->head;
+          Field(BVSparseNode*, TAllocator)* prevNextField = AddressOf(this->head);
 
 
     while(node1 != nullptr && node2 != nullptr)
     while(node1 != nullptr && node2 != nullptr)
     {
     {
@@ -667,7 +765,7 @@ void BVSparse<TAllocator>::for_each(const BVSparse *bv1, const BVSparse *bv2)
             BVSparseNode * newNode = Allocate(startIndex, nullptr);
             BVSparseNode * newNode = Allocate(startIndex, nullptr);
             newNode->data = bvUnit1;
             newNode->data = bvUnit1;
             *prevNextField = newNode;
             *prevNextField = newNode;
-            prevNextField = &newNode->next;
+            prevNextField = AddressOf(newNode->next);
         }
         }
     }
     }
 
 
@@ -683,7 +781,7 @@ void BVSparse<TAllocator>::for_each(const BVSparse *bv1, const BVSparse *bv2)
                 BVSparseNode * newNode = Allocate(copyNode->startIndex, nullptr);
                 BVSparseNode * newNode = Allocate(copyNode->startIndex, nullptr);
                 newNode->data = copyNode->data;
                 newNode->data = copyNode->data;
                 *prevNextField = newNode;
                 *prevNextField = newNode;
-                prevNextField = &newNode->next;
+                prevNextField = AddressOf(newNode->next);
             }
             }
             copyNode = copyNode->next;
             copyNode = copyNode->next;
         }
         }
@@ -795,7 +893,7 @@ BVSparse<TAllocator>::Copy(const BVSparse<TSrcAllocator> * bv2)
 
 
           BVSparseNode * node1      = this->head;
           BVSparseNode * node1      = this->head;
     const BVSparseNode * node2      = bv2->head;
     const BVSparseNode * node2      = bv2->head;
-          BVSparseNode ** prevNextField = &this->head;
+          Field(BVSparseNode*, TAllocator)* prevNextField = AddressOf(this->head);
 
 
     while (node1 != nullptr && node2 != nullptr)
     while (node1 != nullptr && node2 != nullptr)
     {
     {
@@ -803,7 +901,7 @@ BVSparse<TAllocator>::Copy(const BVSparse<TSrcAllocator> * bv2)
         {
         {
             node1->startIndex = node2->startIndex;
             node1->startIndex = node2->startIndex;
             node1->data.Copy(node2->data);
             node1->data.Copy(node2->data);
-            prevNextField = &node1->next;
+            prevNextField = AddressOf(node1->next);
             node1 = node1->next;
             node1 = node1->next;
         }
         }
 
 
@@ -827,7 +925,7 @@ BVSparse<TAllocator>::Copy(const BVSparse<TSrcAllocator> * bv2)
                 BVSparseNode * newNode = Allocate(node2->startIndex, nullptr);
                 BVSparseNode * newNode = Allocate(node2->startIndex, nullptr);
                 newNode->data.Copy(node2->data);
                 newNode->data.Copy(node2->data);
                 *prevNextField = newNode;
                 *prevNextField = newNode;
-                prevNextField = &newNode->next;
+                prevNextField = AddressOf(newNode->next);
             }
             }
             node2 = node2->next;
             node2 = node2->next;
         }
         }
@@ -838,7 +936,7 @@ template <class TAllocator>
 BVSparse<TAllocator> *
 BVSparse<TAllocator> *
 BVSparse<TAllocator>::CopyNew(TAllocator* allocator) const
 BVSparse<TAllocator>::CopyNew(TAllocator* allocator) const
 {
 {
-    BVSparse * bv = AllocatorNew(TAllocator, allocator, BVSparse, allocator);
+    BVSparse * bv = AllocatorNew(TAllocator, allocator, BVSparse<TAllocator>, allocator);
     bv->Copy(this);
     bv->Copy(this);
     return bv;
     return bv;
 }
 }

+ 2 - 2
lib/Common/Exceptions/JavascriptException.h

@@ -18,13 +18,13 @@ namespace Js {
     class JavascriptException : public ExceptionBase
     class JavascriptException : public ExceptionBase
     {
     {
     private:
     private:
-        JavascriptExceptionObject** const addressOfException;
+        Field(JavascriptExceptionObject*)* const addressOfException;
 
 
     public:
     public:
         // Caller should have stored the JavascriptExceptionObject reference in
         // Caller should have stored the JavascriptExceptionObject reference in
         // thread context data. addressOfException should be the thread context data
         // thread context data. addressOfException should be the thread context data
         // address.
         // address.
-        JavascriptException(JavascriptExceptionObject** addressOfException)
+        JavascriptException(Field(JavascriptExceptionObject*)* addressOfException)
             : addressOfException(addressOfException)
             : addressOfException(addressOfException)
         {
         {
             Assert(addressOfException && *addressOfException);
             Assert(addressOfException && *addressOfException);

+ 139 - 16
lib/Common/Memory/RecyclerPointers.h

@@ -14,6 +14,12 @@ class RecyclerNonLeafAllocator;
 struct _write_barrier_policy {};
 struct _write_barrier_policy {};
 struct _no_write_barrier_policy {};
 struct _no_write_barrier_policy {};
 
 
+// ----------------------------------------------------------------------------
+// Field write barrier
+//
+//      Determines if a field needs to be wrapped in WriteBarrierPtr
+// ----------------------------------------------------------------------------
+
 // Type write barrier policy
 // Type write barrier policy
 //
 //
 // By default following potentially contains GC pointers and use write barrier policy:
 // By default following potentially contains GC pointers and use write barrier policy:
@@ -75,6 +81,13 @@ template <class T,
           class Policy = typename AllocatorWriteBarrierPolicy<Allocator, T>::Policy>
           class Policy = typename AllocatorWriteBarrierPolicy<Allocator, T>::Policy>
 struct WriteBarrierFieldTypeTraits { typedef typename _WriteBarrierFieldType<T, Policy>::Type Type; };
 struct WriteBarrierFieldTypeTraits { typedef typename _WriteBarrierFieldType<T, Policy>::Type Type; };
 
 
+
+// ----------------------------------------------------------------------------
+// Array write barrier
+//
+//      Determines if an array operation needs to trigger write barrier
+// ----------------------------------------------------------------------------
+
 // ArrayWriteBarrier behavior
 // ArrayWriteBarrier behavior
 //
 //
 template <class Policy>
 template <class Policy>
@@ -96,34 +109,97 @@ struct _ArrayWriteBarrier<_write_barrier_policy>
 };
 };
 #endif
 #endif
 
 
-// Trigger write barrier on changing array content if Allocator and element type
-// determines write barrier is needed. Ignore otherwise.
+// Determines array write barrier policy based on array item type.
+//
+// Note: If individual array item needs write barrier, we choose to use
+// WriteBarrierPtr with the item type. Thus we only specialize on
+// WriteBarrierPtr (and _write_barrier_policy if user wants to force write
+// barrier).
 //
 //
-template <class T, class Allocator = Recycler, class PolicyType = T>
-void WriteBarrier(T * address, size_t count)
+template <class T>
+struct _ArrayItemWriteBarrierPolicy
+    { typedef _no_write_barrier_policy Policy; };
+template <class T>
+struct _ArrayItemWriteBarrierPolicy<WriteBarrierPtr<T>>
+    { typedef _write_barrier_policy Policy; };
+template <>
+struct _ArrayItemWriteBarrierPolicy<_write_barrier_policy>
+    { typedef _write_barrier_policy Policy; };
+
+// Trigger write barrier on changing array content if element type determines
+// write barrier is needed. Ignore otherwise.
+//
+template <class T, class PolicyType = T>
+void ArrayWriteBarrier(T * address, size_t count)
 {
 {
-    typedef typename AllocatorWriteBarrierPolicy<Allocator, PolicyType>::Policy Policy;
+    typedef typename _ArrayItemWriteBarrierPolicy<PolicyType>::Policy Policy;
     return _ArrayWriteBarrier<Policy>::WriteBarrier(address, count);
     return _ArrayWriteBarrier<Policy>::WriteBarrier(address, count);
 }
 }
 
 
 // Copy array content. Triggers write barrier on the dst array content if if
 // Copy array content. Triggers write barrier on the dst array content if if
 // Allocator and element type determines write barrier is needed.
 // Allocator and element type determines write barrier is needed.
 //
 //
-template <class Allocator, class T, class PolicyType = T>
+template <class T, class PolicyType = T>
 void CopyArray(T* dst, size_t dstCount, const T* src, size_t srcCount)
 void CopyArray(T* dst, size_t dstCount, const T* src, size_t srcCount)
 {
 {
-    js_memcpy_s(dst, sizeof(T) * dstCount, src, sizeof(T) * srcCount);
-    WriteBarrier<T, Allocator, PolicyType>(dst, dstCount);
+    js_memcpy_s(reinterpret_cast<void*>(dst), sizeof(T) * dstCount,
+                reinterpret_cast<const void*>(src), sizeof(T) * srcCount);
+    ArrayWriteBarrier<T, PolicyType>(dst, dstCount);
 }
 }
-template <class Allocator, class T, class PolicyType = T>
-void CopyArray(NoWriteBarrierPtr<T>& dst, size_t dstCount, const NoWriteBarrierPtr<T>& src, size_t srcCount)
+template <class T, class PolicyType = T>
+void CopyArray(WriteBarrierPtr<T>& dst, size_t dstCount,
+               const WriteBarrierPtr<T>& src, size_t srcCount)
 {
 {
-    return CopyArray<Allocator, T, PolicyType>((T*)dst, dstCount, (const T*)src, srcCount);
+    return CopyArray<T, PolicyType>(
+        static_cast<T*>(dst), dstCount, static_cast<const T*>(src), srcCount);
 }
 }
-template <class Allocator, class T, class PolicyType = T>
-void CopyArray(WriteBarrierPtr<T>& dst, size_t dstCount, const WriteBarrierPtr<T>& src, size_t srcCount)
+template <class T, class PolicyType = T>
+void CopyArray(T* dst, size_t dstCount,
+               const WriteBarrierPtr<T>& src, size_t srcCount)
 {
 {
-    return CopyArray<Allocator, T, PolicyType>((T*)dst, dstCount, (const T*)src, srcCount);
+    return CopyArray<T, PolicyType>(
+        dst, dstCount, static_cast<const T*>(src), srcCount);
+}
+template <class T, class PolicyType = T>
+void CopyArray(WriteBarrierPtr<T>& dst, size_t dstCount,
+               const T* src, size_t srcCount)
+{
+    return CopyArray<T, PolicyType>(
+        static_cast<T*>(dst), dstCount, src, srcCount);
+}
+
+// Copy pointer array to WriteBarrierPtr array
+//
+template <class T, class PolicyType = WriteBarrierPtr<T>>
+void CopyArray(WriteBarrierPtr<T>* dst, size_t dstCount,
+               T* const * src, size_t srcCount)
+{
+    CompileAssert(sizeof(WriteBarrierPtr<T>) == sizeof(T*));
+    return CopyArray<T*, PolicyType>(
+        reinterpret_cast<T**>(dst), dstCount, src, srcCount);
+}
+
+// Move Array content (memmove)
+//
+template <class T, class PolicyType = T>
+void MoveArray(T* dst, const T* src, size_t count)
+{
+    memmove(reinterpret_cast<void*>(dst),
+            reinterpret_cast<const void*>(src),
+            sizeof(T) * count);
+    ArrayWriteBarrier<T, PolicyType>(dst, count);
+}
+
+template <class T>
+void ClearArray(T* dst, size_t count)
+{
+    // assigning NULL don't need write barrier, just cast it and null it out
+    memset(reinterpret_cast<void*>(dst), 0, sizeof(T) * count);
+}
+template <class T>
+void ClearArray(WriteBarrierPtr<T>& dst, size_t count)
+{
+    ClearArray(static_cast<T*>(dst), count);
 }
 }
 
 
 
 
@@ -216,8 +292,8 @@ public:
     T * operator->() const { return ptr; }
     T * operator->() const { return ptr; }
     operator T* const & () const { return ptr; }
     operator T* const & () const { return ptr; }
 
 
-    T* const * AddressOf() const { return &ptr; }
-    T** AddressOf() { return &ptr; }
+    const WriteBarrierPtr* AddressOf() const { return this; }
+    WriteBarrierPtr* AddressOf() { return this; }
 
 
     // Taking immutable address is ok
     // Taking immutable address is ok
     //
     //
@@ -239,6 +315,11 @@ public:
         WriteBarrierSet(ptr);
         WriteBarrierSet(ptr);
         return *this;
         return *this;
     }
     }
+    WriteBarrierPtr& operator=(const std::nullptr_t& ptr)
+    {
+        NoWriteBarrierSet(ptr);
+        return *this;
+    }
     void NoWriteBarrierSet(T * ptr)
     void NoWriteBarrierSet(T * ptr)
     {
     {
         this->ptr = ptr;
         this->ptr = ptr;
@@ -257,6 +338,22 @@ public:
         return *this;
         return *this;
     }
     }
 
 
+    WriteBarrierPtr& operator++()  // prefix ++
+    {
+        ++ptr;
+#ifdef RECYCLER_WRITE_BARRIER
+        RecyclerWriteBarrierManager::WriteBarrier(this);
+#endif
+        return *this;
+    }
+
+    WriteBarrierPtr operator++(int)  // postfix ++
+    {
+        WriteBarrierPtr result(*this);
+        ++(*this);
+        return result;
+    }
+
     static void MoveArray(WriteBarrierPtr * dst, WriteBarrierPtr * src, size_t count)
     static void MoveArray(WriteBarrierPtr * dst, WriteBarrierPtr * src, size_t count)
     {
     {
         memmove((void *)dst, src, sizeof(WriteBarrierPtr) * count);
         memmove((void *)dst, src, sizeof(WriteBarrierPtr) * count);
@@ -280,6 +377,32 @@ public:
 private:
 private:
     T * ptr;
     T * ptr;
 };
 };
+
+
+template <class T>
+struct _AddressOfType
+{
+    inline static T* AddressOf(T& val) { return &val; }
+    inline static const T* AddressOf(const T& val) { return &val; }
+};
+
+template <class T>
+struct _AddressOfType< WriteBarrierPtr<T> >
+{
+    inline static WriteBarrierPtr<T>* AddressOf(WriteBarrierPtr<T>& val)
+    {
+        return val.AddressOf();
+    }
+    inline static const WriteBarrierPtr<T>* AddressOf(const WriteBarrierPtr<T>& val)
+    {
+        return val.AddressOf();
+    }
+};
+
+template <class T>
+inline T* AddressOf(T& val) { return _AddressOfType<T>::AddressOf(val); }
+template <class T>
+inline const T* AddressOf(const T& val) { return _AddressOfType<T>::AddressOf(val); }
 }  // namespace Memory
 }  // namespace Memory
 
 
 
 

+ 5 - 5
lib/Common/Memory/RecyclerWeakReference.h

@@ -35,15 +35,15 @@ public:
 
 
 protected:
 protected:
 
 
-    char* strongRef;
-    HeapBlock * strongRefHeapBlock;
-    HeapBlock * weakRefHeapBlock;
-    RecyclerWeakReferenceBase* next;
+    FieldNoBarrier(char*) strongRef;
+    FieldNoBarrier(HeapBlock *) strongRefHeapBlock;
+    FieldNoBarrier(HeapBlock *) weakRefHeapBlock;
+    FieldNoBarrier(RecyclerWeakReferenceBase*) next;
 #if DBG
 #if DBG
 #if ENABLE_RECYCLER_TYPE_TRACKING
 #if ENABLE_RECYCLER_TYPE_TRACKING
     type_info const * typeInfo;
     type_info const * typeInfo;
 #endif
 #endif
-    
+
 #if defined TRACK_ALLOC && defined(PERF_COUNTERS)
 #if defined TRACK_ALLOC && defined(PERF_COUNTERS)
     PerfCounter::Counter * counter;
     PerfCounter::Counter * counter;
 #endif
 #endif

+ 8 - 11
lib/Common/Memory/WriteBarrierMacros.h

@@ -22,18 +22,15 @@
 #if !defined(__WRITE_BARRIER_MACROS__) || defined(FORCE_USE_WRITE_BARRIER)
 #if !defined(__WRITE_BARRIER_MACROS__) || defined(FORCE_USE_WRITE_BARRIER)
 
 
 #ifndef __WRITE_BARRIER_MACROS__
 #ifndef __WRITE_BARRIER_MACROS__
+#define __WRITE_BARRIER_MACROS__ 1
 #define PopMacro(x) __pragma(pop_macro( #x ))
 #define PopMacro(x) __pragma(pop_macro( #x ))
-
 #define PushMacro(x) __pragma(push_macro( #x ))
 #define PushMacro(x) __pragma(push_macro( #x ))
-
 #define SAVE_WRITE_BARRIER_MACROS() \
 #define SAVE_WRITE_BARRIER_MACROS() \
-    PushMacro("Field") \
-    PushMacro("FieldNoBarrier")
-
+    PushMacro(Field) \
+    PushMacro(FieldNoBarrier)
 #define RESTORE_WRITE_BARRIER_MACROS() \
 #define RESTORE_WRITE_BARRIER_MACROS() \
-    PopMacro("Field") \
-    PopMacro("FieldNoBarrier")
-
+    PopMacro(Field) \
+    PopMacro(FieldNoBarrier)
 #endif
 #endif
 
 
 #ifdef FORCE_USE_WRITE_BARRIER
 #ifdef FORCE_USE_WRITE_BARRIER
@@ -42,8 +39,7 @@ SAVE_WRITE_BARRIER_MACROS()
 #undef FieldNoBarrier
 #undef FieldNoBarrier
 #endif
 #endif
 
 
-// TODO: Turn off these annotations on Win32
-#if defined(__clang__) || defined(FORCE_USE_WRITE_BARRIER)
+#if defined(GLOBAL_FORCE_USE_WRITE_BARRIER) || defined(FORCE_USE_WRITE_BARRIER)
 // Various macros for defining field attributes
 // Various macros for defining field attributes
 #define Field(type, ...) \
 #define Field(type, ...) \
     typename WriteBarrierFieldTypeTraits<type, ##__VA_ARGS__>::Type
     typename WriteBarrierFieldTypeTraits<type, ##__VA_ARGS__>::Type
@@ -54,7 +50,8 @@ SAVE_WRITE_BARRIER_MACROS()
 #define FieldNoBarrier(type) type
 #define FieldNoBarrier(type) type
 #endif
 #endif
 
 
+#ifdef FORCE_USE_WRITE_BARRIER
 #undef FORCE_USE_WRITE_BARRIER
 #undef FORCE_USE_WRITE_BARRIER
-#define __WRITE_BARRIER_MACROS__ 1
+#endif
 
 
 #endif
 #endif

+ 13 - 5
lib/JITIDL/JITTypes.h

@@ -51,6 +51,14 @@ typedef unsigned char boolean;
 #endif
 #endif
 #endif
 #endif
 
 
+#ifdef __midl
+#define IDL_Field(type)             type
+#define IDL_FieldNoBarrier(type)    type
+#else
+#define IDL_Field(type)             Field(type)
+#define IDL_FieldNoBarrier(type)    FieldNoBarrier(type)
+#endif
+
 // TODO: OOP JIT, how do we make this better?
 // TODO: OOP JIT, how do we make this better?
 const int VTABLE_COUNT = 47;
 const int VTABLE_COUNT = 47;
 const int EQUIVALENT_TYPE_CACHE_SIZE = 8;
 const int EQUIVALENT_TYPE_CACHE_SIZE = 8;
@@ -633,12 +641,12 @@ typedef struct PolymorphicInlineCacheIDL
 
 
 typedef struct PolymorphicInlineCacheInfoIDL
 typedef struct PolymorphicInlineCacheInfoIDL
 {
 {
-    unsigned int polymorphicInlineCacheCount;
-    unsigned int bogus1;
-    IDL_DEF([size_is(polymorphicInlineCacheCount)]) byte * polymorphicCacheUtilizationArray;
-    IDL_DEF([size_is(polymorphicInlineCacheCount)]) PolymorphicInlineCacheIDL * polymorphicInlineCaches;
+    IDL_Field(unsigned int) polymorphicInlineCacheCount;
+    IDL_Field(unsigned int) bogus1;
+    IDL_DEF([size_is(polymorphicInlineCacheCount)]) IDL_Field(byte *) polymorphicCacheUtilizationArray;
+    IDL_DEF([size_is(polymorphicInlineCacheCount)]) IDL_Field(PolymorphicInlineCacheIDL *) polymorphicInlineCaches;
 
 
-    CHAKRA_PTR functionBodyAddr;
+    IDL_Field(CHAKRA_PTR) functionBodyAddr;
 } PolymorphicInlineCacheInfoIDL;
 } PolymorphicInlineCacheInfoIDL;
 
 
 // CodeGenWorkItem fields, read only in JIT
 // CodeGenWorkItem fields, read only in JIT

+ 10 - 10
lib/Parser/OctoquadIdentifier.h

@@ -22,13 +22,13 @@ namespace UnifiedRegex
     struct TrigramInfo {
     struct TrigramInfo {
         static const int PatternLength=8;
         static const int PatternLength=8;
         static const int MaxResults=32;
         static const int MaxResults=32;
-        bool isTrigramPattern;
-        bool hasCachedResultString;
-        int triPat1;
-        int triPat2;
-        int resultCount;
-        int offsets[MaxResults];
-        Js::JavascriptString * cachedResult[MaxResults];
+        Field(bool) isTrigramPattern;
+        Field(bool) hasCachedResultString;
+        Field(int) triPat1;
+        Field(int) triPat2;
+        Field(int) resultCount;
+        Field(int ) offsets[MaxResults];
+        Field(Js::JavascriptString *) cachedResult[MaxResults];
 
 
         TrigramInfo(__in_ecount(PatternLength) char* pat1,__in_ecount(PatternLength) char* pat2, Recycler* recycler);
         TrigramInfo(__in_ecount(PatternLength) char* pat1,__in_ecount(PatternLength) char* pat2, Recycler* recycler);
     };
     };
@@ -133,13 +133,13 @@ namespace UnifiedRegex
     private:
     private:
         OctoquadMatcher(const StandardChars<Char>* standardChars, CaseInsensitive::MappingSource mappingSource, OctoquadIdentifier* identifier);
         OctoquadMatcher(const StandardChars<Char>* standardChars, CaseInsensitive::MappingSource mappingSource, OctoquadIdentifier* identifier);
 
 
-        Char codeToChar[TrigramAlphabet::AlphaCount];
+        Field(Char) codeToChar[TrigramAlphabet::AlphaCount];
 
 
         // Maps characters (0..AsciTableSize-1) to 0 if not in alphabet, or 0x1, 0x2, 0x4 or 0x8.
         // Maps characters (0..AsciTableSize-1) to 0 if not in alphabet, or 0x1, 0x2, 0x4 or 0x8.
         // Allocated and filled only if invoke Match below.
         // Allocated and filled only if invoke Match below.
-        uint8 charToBits[TrigramAlphabet::AsciiTableSize];
+        Field(uint8 ) charToBits[TrigramAlphabet::AsciiTableSize];
 
 
-        uint32 patterns[OctoquadIdentifier::NumPatterns];
+        Field(uint32 ) patterns[OctoquadIdentifier::NumPatterns];
 
 
     public:
     public:
         static OctoquadMatcher *New(Recycler* recycler, const StandardChars<Char>* standardChars, CaseInsensitive::MappingSource mappingSource, OctoquadIdentifier* identifier);
         static OctoquadMatcher *New(Recycler* recycler, const StandardChars<Char>* standardChars, CaseInsensitive::MappingSource mappingSource, OctoquadIdentifier* identifier);

+ 3 - 3
lib/Runtime/Base/FunctionBody.cpp

@@ -1449,7 +1449,7 @@ namespace Js
         AssertMsg(index < this->GetNestedCount(), "Trying to write past the nested func array");
         AssertMsg(index < this->GetNestedCount(), "Trying to write past the nested func array");
 
 
         FunctionProxyArray nested = this->GetNestedFuncArray();
         FunctionProxyArray nested = this->GetNestedFuncArray();
-        return &nested[index];
+        return nested + index;
     }
     }
 
 
     ParseableFunctionInfo* ParseableFunctionInfo::GetNestedFunctionForExecution(uint index)
     ParseableFunctionInfo* ParseableFunctionInfo::GetNestedFunctionForExecution(uint index)
@@ -1602,7 +1602,7 @@ namespace Js
     {
     {
         this->m_displayNameLength = displayNameLength;
         this->m_displayNameLength = displayNameLength;
         this->m_displayShortNameOffset = displayShortNameOffset;
         this->m_displayShortNameOffset = displayShortNameOffset;
-        FunctionProxy::SetDisplayName(pszDisplayName, &this->m_displayName, displayNameLength, m_scriptContext, flags);
+        FunctionProxy::SetDisplayName(pszDisplayName, AddressOf(this->m_displayName), displayNameLength, m_scriptContext, flags);
     }
     }
 
 
     LPCWSTR DeferDeserializeFunctionInfo::GetSourceInfo(int& lineNumber, int& columnNumber) const
     LPCWSTR DeferDeserializeFunctionInfo::GetSourceInfo(int& lineNumber, int& columnNumber) const
@@ -2213,7 +2213,7 @@ namespace Js
     {
     {
         this->m_displayNameLength = displayNameLength;
         this->m_displayNameLength = displayNameLength;
         this->m_displayShortNameOffset = displayShortNameOffset;
         this->m_displayShortNameOffset = displayShortNameOffset;
-        FunctionProxy::SetDisplayName(pszDisplayName, this->m_displayName.AddressOf(), displayNameLength, m_scriptContext, flags);
+        FunctionProxy::SetDisplayName(pszDisplayName, AddressOf(this->m_displayName), displayNameLength, m_scriptContext, flags);
     }
     }
 
 
     // SourceInfo methods
     // SourceInfo methods

+ 3 - 3
lib/Runtime/Base/ScriptContext.cpp

@@ -2258,13 +2258,13 @@ if (!sourceList)
         EnsureDynamicSourceContextInfoMap();
         EnsureDynamicSourceContextInfoMap();
         if (this->GetSourceContextInfo(hash) != nullptr)
         if (this->GetSourceContextInfo(hash) != nullptr)
         {
         {
-            return const_cast<SourceContextInfo*>(this->cache->noContextSourceContextInfo);
+            return this->cache->noContextSourceContextInfo;
         }
         }
 
 
         if (this->cache->dynamicSourceContextInfoMap->Count() > INMEMORY_CACHE_MAX_PROFILE_MANAGER)
         if (this->cache->dynamicSourceContextInfoMap->Count() > INMEMORY_CACHE_MAX_PROFILE_MANAGER)
         {
         {
             OUTPUT_TRACE(Js::DynamicProfilePhase, _u("Max of dynamic script profile info reached.\n"));
             OUTPUT_TRACE(Js::DynamicProfilePhase, _u("Max of dynamic script profile info reached.\n"));
-            return const_cast<SourceContextInfo*>(this->cache->noContextSourceContextInfo);
+            return this->cache->noContextSourceContextInfo;
         }
         }
 
 
         // This is capped so we can continue allocating in the arena
         // This is capped so we can continue allocating in the arena
@@ -2340,7 +2340,7 @@ if (!sourceList)
     {
     {
         if (sourceContext == Js::Constants::NoHostSourceContext)
         if (sourceContext == Js::Constants::NoHostSourceContext)
         {
         {
-            return const_cast<SourceContextInfo*>(this->cache->noContextSourceContextInfo);
+            return this->cache->noContextSourceContextInfo;
         }
         }
 
 
         // We only init sourceContextInfoMap, don't need to lock.
         // We only init sourceContextInfoMap, don't need to lock.

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

@@ -461,9 +461,9 @@ private:
         // (the code) is responsible for keeping it alive.
         // (the code) is responsible for keeping it alive.
         // Each unique guard, is weakly referenced, such that it can be reclaimed if not referenced elsewhere even without being
         // Each unique guard, is weakly referenced, such that it can be reclaimed if not referenced elsewhere even without being
         // invalidated.  The entry of a unique guard is removed from the table once the corresponding cache is invalidated.
         // invalidated.  The entry of a unique guard is removed from the table once the corresponding cache is invalidated.
-        Js::PropertyGuard* sharedGuard;
-        PropertyGuardHashSet uniqueGuards;
-        EntryPointDictionary* entryPoints;
+        Field(Js::PropertyGuard*) sharedGuard;
+        Field(PropertyGuardHashSet) uniqueGuards;
+        Field(EntryPointDictionary*) entryPoints;
 
 
         PropertyGuardEntry(Recycler* recycler) : sharedGuard(nullptr), uniqueGuards(recycler), entryPoints(nullptr) {}
         PropertyGuardEntry(Recycler* recycler) : sharedGuard(nullptr), uniqueGuards(recycler), entryPoints(nullptr) {}
     };
     };
@@ -519,11 +519,11 @@ private:
     public:
     public:
         SourceDynamicProfileManagerCache() : refCount(0), sourceProfileManagerMap(nullptr) {}
         SourceDynamicProfileManagerCache() : refCount(0), sourceProfileManagerMap(nullptr) {}
 
 
-        SourceDynamicProfileManagerMap* sourceProfileManagerMap;
+        Field(SourceDynamicProfileManagerMap*) sourceProfileManagerMap;
         void AddRef() { refCount++; }
         void AddRef() { refCount++; }
         uint Release() { Assert(refCount > 0); return --refCount; }
         uint Release() { Assert(refCount > 0); return --refCount; }
     private:
     private:
-        uint refCount;              // For every script context using this cache, there is a ref count added.
+        Field(uint) refCount;              // For every script context using this cache, there is a ref count added.
     };
     };
 
 
     typedef JsUtil::BaseDictionary<const WCHAR*, SourceDynamicProfileManagerCache*, Recycler, PowerOf2SizePolicy> SourceProfileManagersByUrlMap;
     typedef JsUtil::BaseDictionary<const WCHAR*, SourceDynamicProfileManagerCache*, Recycler, PowerOf2SizePolicy> SourceProfileManagersByUrlMap;
@@ -531,29 +531,29 @@ private:
     struct RecyclableData
     struct RecyclableData
     {
     {
         RecyclableData(Recycler *const recycler);
         RecyclableData(Recycler *const recycler);
-        Js::TempArenaAllocatorObject * temporaryArenaAllocators[MaxTemporaryArenaAllocators];
-        Js::TempGuestArenaAllocatorObject * temporaryGuestArenaAllocators[MaxTemporaryArenaAllocators];
+        Field(Js::TempArenaAllocatorObject * ) temporaryArenaAllocators[MaxTemporaryArenaAllocators];
+        Field(Js::TempGuestArenaAllocatorObject * ) temporaryGuestArenaAllocators[MaxTemporaryArenaAllocators];
 
 
-        Js::JavascriptExceptionObject * exceptionObject;
-        bool propagateException;
+        Field(Js::JavascriptExceptionObject *) exceptionObject;
+        Field(bool) propagateException;
 
 
         // We throw a JS catchable SO exception if we detect we might overflow the stack. Allocating this (JS)
         // We throw a JS catchable SO exception if we detect we might overflow the stack. Allocating this (JS)
         // object though might really overflow the stack. So use this thread global to identify them from the throw point
         // object though might really overflow the stack. So use this thread global to identify them from the throw point
         // to where they are caught; where the stack has been unwound and it is safer to allocate the real exception
         // to where they are caught; where the stack has been unwound and it is safer to allocate the real exception
         // object and throw.
         // object and throw.
-        Js::JavascriptExceptionObject soErrorObject;
+        Field(Js::JavascriptExceptionObject) soErrorObject;
 
 
         // We can't allocate an out of memory object...  So use this static as a way to identify
         // We can't allocate an out of memory object...  So use this static as a way to identify
         // them from the throw point to where they are caught.
         // them from the throw point to where they are caught.
-        Js::JavascriptExceptionObject oomErrorObject;
+        Field(Js::JavascriptExceptionObject) oomErrorObject;
 
 
         // This is for JsRT scenario where a runtime is not usable after a suspend request, before a resume runtime call is made
         // This is for JsRT scenario where a runtime is not usable after a suspend request, before a resume runtime call is made
-        Js::JavascriptExceptionObject terminatedErrorObject;
+        Field(Js::JavascriptExceptionObject) terminatedErrorObject;
 
 
-        Js::JavascriptExceptionObject* unhandledExceptionObject;
+        Field(Js::JavascriptExceptionObject*) unhandledExceptionObject;
 
 
         // Used to temporarily keep throwing exception object alive (thrown but not yet caught)
         // Used to temporarily keep throwing exception object alive (thrown but not yet caught)
-        Js::JavascriptExceptionObject* tempUncaughtException;
+        Field(Js::JavascriptExceptionObject*) tempUncaughtException;
 
 
         // Contains types that have property caches that need to be tracked, as the caches may need to be cleared. Types that
         // Contains types that have property caches that need to be tracked, as the caches may need to be cleared. Types that
         // contain a property cache for a property that is on a prototype object will be tracked in this map since those caches
         // contain a property cache for a property that is on a prototype object will be tracked in this map since those caches
@@ -563,7 +563,7 @@ private:
         // they're searching through a bucket while registering a type or enumerating types to invalidate, or when a property ID
         // they're searching through a bucket while registering a type or enumerating types to invalidate, or when a property ID
         // is reclaimed. If none of those happen, then this collection may contain weak reference handles to deleted objects
         // is reclaimed. If none of those happen, then this collection may contain weak reference handles to deleted objects
         // that would not get removed, but it would also not get any bigger.
         // that would not get removed, but it would also not get any bigger.
-        PropertyIdToTypeHashSetDictionary typesWithProtoPropertyCache;
+        Field(PropertyIdToTypeHashSetDictionary) typesWithProtoPropertyCache;
 
 
         // The property guard dictionary contains property guards which need to be invalidated in response to properties changing
         // The property guard dictionary contains property guards which need to be invalidated in response to properties changing
         // from writable to read-only and vice versa, properties being shadowed or unshadowed on prototypes, etc.  The dictionary
         // from writable to read-only and vice versa, properties being shadowed or unshadowed on prototypes, etc.  The dictionary
@@ -571,33 +571,33 @@ private:
         // When a guard is no longer needed it is garbage collected, but the weak references and dictionary entries remain, until
         // When a guard is no longer needed it is garbage collected, but the weak references and dictionary entries remain, until
         // the guards for a given property get invalidated.
         // the guards for a given property get invalidated.
         // TODO: Create and use a self-cleaning weak reference dictionary, which would periodically remove any unused weak references.
         // TODO: Create and use a self-cleaning weak reference dictionary, which would periodically remove any unused weak references.
-        PropertyGuardDictionary propertyGuards;
+        Field(PropertyGuardDictionary) propertyGuards;
 
 
 
 
-        PropertyNoCaseSetType * caseInvariantPropertySet;
+        Field(PropertyNoCaseSetType *) caseInvariantPropertySet;
 
 
-        JsUtil::List<Js::PropertyRecord const*>* boundPropertyStrings; // Recycler allocated list of property strings that we need to strongly reference so that they're not reclaimed
+        Field(JsUtil::List<Js::PropertyRecord const*>*) boundPropertyStrings; // Recycler allocated list of property strings that we need to strongly reference so that they're not reclaimed
 
 
-        SourceProfileManagersByUrlMap* sourceProfileManagersByUrl;
+        Field(SourceProfileManagersByUrlMap*) sourceProfileManagersByUrl;
 
 
         // Used to register recyclable data that needs to be kept alive while jitting
         // Used to register recyclable data that needs to be kept alive while jitting
-        JsUtil::DoublyLinkedList<Js::CodeGenRecyclableData> codeGenRecyclableDatas;
+        Field(JsUtil::DoublyLinkedList<Js::CodeGenRecyclableData>) codeGenRecyclableDatas;
 
 
         // Used to root old entry points so that they're not prematurely collected
         // Used to root old entry points so that they're not prematurely collected
-        Js::FunctionEntryPointInfo* oldEntryPointInfo;
+        Field(Js::FunctionEntryPointInfo*) oldEntryPointInfo;
 
 
         // Used to store a mapping of string to Symbol for cross-realm Symbol registration
         // Used to store a mapping of string to Symbol for cross-realm Symbol registration
         // See ES6 (draft 22) 19.4.2.2
         // See ES6 (draft 22) 19.4.2.2
-        SymbolRegistrationMap* symbolRegistrationMap;
+        Field(SymbolRegistrationMap*) symbolRegistrationMap;
 
 
         // Just holding the reference to the returnedValueList of the stepController. This way that list will not get recycled prematurely.
         // Just holding the reference to the returnedValueList of the stepController. This way that list will not get recycled prematurely.
-        Js::ReturnedValueList *returnedValueList;
+        Field(Js::ReturnedValueList *) returnedValueList;
 
 
-        uint constructorCacheInvalidationCount;
+        Field(uint) constructorCacheInvalidationCount;
 
 
 #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
 #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
         // use for autoProxy called from Debug.setAutoProxyName. we need to keep the buffer from GetSz() alive.
         // use for autoProxy called from Debug.setAutoProxyName. we need to keep the buffer from GetSz() alive.
-        LPCWSTR autoProxyName;
+        Field(LPCWSTR) autoProxyName;
 #endif
 #endif
     };
     };
 
 
@@ -1322,13 +1322,13 @@ public:
     Js::JavascriptExceptionObject* GetUnhandledExceptionObject() const  { return recyclableData->unhandledExceptionObject; };
     Js::JavascriptExceptionObject* GetUnhandledExceptionObject() const  { return recyclableData->unhandledExceptionObject; };
 
 
     // To temporarily keep throwing exception object alive (thrown but not yet caught)
     // To temporarily keep throwing exception object alive (thrown but not yet caught)
-    Js::JavascriptExceptionObject** SaveTempUncaughtException(Js::JavascriptExceptionObject* exceptionObject)
+    Field(Js::JavascriptExceptionObject*)* SaveTempUncaughtException(Js::JavascriptExceptionObject* exceptionObject)
     {
     {
         // Previous save should have been caught and cleared
         // Previous save should have been caught and cleared
         Assert(recyclableData->tempUncaughtException == nullptr);
         Assert(recyclableData->tempUncaughtException == nullptr);
 
 
         recyclableData->tempUncaughtException = exceptionObject;
         recyclableData->tempUncaughtException = exceptionObject;
-        return &recyclableData->tempUncaughtException;
+        return AddressOf(recyclableData->tempUncaughtException);
     }
     }
 
 
     bool HasCatchHandler() const { return hasCatchHandler; }
     bool HasCatchHandler() const { return hasCatchHandler; }

+ 8 - 2
lib/Runtime/Language/DynamicProfileInfo.cpp

@@ -1493,7 +1493,7 @@ namespace Js
             {
             {
                 DumpProfiledValuesGroupedByValue(
                 DumpProfiledValuesGroupedByValue(
                     _u("Element load"),
                     _u("Element load"),
-                    this->ldElemInfo,
+                    static_cast<LdElemInfo*>(this->ldElemInfo),
                     this->functionBody->GetProfiledLdElemCount(),
                     this->functionBody->GetProfiledLdElemCount(),
                     [](const LdElemInfo *const ldElemInfo, const uint i) -> ValueType
                     [](const LdElemInfo *const ldElemInfo, const uint i) -> ValueType
                 {
                 {
@@ -1502,7 +1502,7 @@ namespace Js
                     dynamicProfileInfoAllocator);
                     dynamicProfileInfoAllocator);
                 DumpProfiledValuesGroupedByValue(
                 DumpProfiledValuesGroupedByValue(
                     _u("Fld"),
                     _u("Fld"),
-                    this->fldInfo,
+                    static_cast<FldInfo *>(this->fldInfo),
                     functionBody->GetProfiledFldCount(),
                     functionBody->GetProfiledFldCount(),
                     [](const FldInfo *const fldInfos, const uint i) -> ValueType
                     [](const FldInfo *const fldInfos, const uint i) -> ValueType
                 {
                 {
@@ -2104,6 +2104,12 @@ namespace Js
         }
         }
     }
     }
 
 
+    template <typename T>
+    void DynamicProfileInfo::WriteArray(uint count, WriteBarrierPtr<T> arr, FILE * file)
+    {
+        WriteArray(count, static_cast<T*>(arr), file);
+    }
+
     template <>
     template <>
     void DynamicProfileInfo::WriteData<FunctionBody *>(FunctionBody * functionBody, FILE * file)
     void DynamicProfileInfo::WriteData<FunctionBody *>(FunctionBody * functionBody, FILE * file)
     {
     {

+ 54 - 37
lib/Runtime/Language/DynamicProfileInfo.h

@@ -52,17 +52,17 @@ namespace Js
     class DynamicProfileFunctionInfo
     class DynamicProfileFunctionInfo
     {
     {
     public:
     public:
-        Js::ArgSlot paramInfoCount;
-        ProfileId ldElemInfoCount;
-        ProfileId stElemInfoCount;
-        ProfileId arrayCallSiteCount;
-        ProfileId slotInfoCount;
-        ProfileId callSiteInfoCount;
-        ProfileId returnTypeInfoCount;
-        ProfileId divCount;
-        ProfileId switchCount;
-        uint loopCount;
-        uint fldInfoCount;
+        Field(Js::ArgSlot) paramInfoCount;
+        Field(ProfileId) ldElemInfoCount;
+        Field(ProfileId) stElemInfoCount;
+        Field(ProfileId) arrayCallSiteCount;
+        Field(ProfileId) slotInfoCount;
+        Field(ProfileId) callSiteInfoCount;
+        Field(ProfileId) returnTypeInfoCount;
+        Field(ProfileId) divCount;
+        Field(ProfileId) switchCount;
+        Field(uint) loopCount;
+        Field(uint) fldInfoCount;
     };
     };
 
 
     enum ThisType : BYTE
     enum ThisType : BYTE
@@ -452,21 +452,21 @@ namespace Js
     private:
     private:
         // Have the dynamicProfileFunctionInfo after loaded from cache.
         // Have the dynamicProfileFunctionInfo after loaded from cache.
         // Replaced with the function body it is verified and matched (See DynamicProfileInfo::MatchFunctionBody)
         // Replaced with the function body it is verified and matched (See DynamicProfileInfo::MatchFunctionBody)
-        DynamicProfileFunctionInfo * dynamicProfileFunctionInfo;
-        CallSiteInfo *callSiteInfo;
-        ValueType * returnTypeInfo; // return type of calls for non inline call sites
-        ValueType * divideTypeInfo;
-        ValueType * switchTypeInfo;
-        LdElemInfo * ldElemInfo;
-        StElemInfo * stElemInfo;
-        ArrayCallSiteInfo *arrayCallSiteInfo;
-        ValueType * parameterInfo;
-        FldInfo * fldInfo;
-        ValueType * slotInfo;
-        ImplicitCallFlags * loopImplicitCallFlags;
-        ImplicitCallFlags implicitCallFlags;
-        BVFixed* loopFlags;
-        ThisInfo thisInfo;
+        Field(DynamicProfileFunctionInfo *) dynamicProfileFunctionInfo;
+        Field(CallSiteInfo *) callSiteInfo;
+        Field(ValueType *) returnTypeInfo; // return type of calls for non inline call sites
+        Field(ValueType *) divideTypeInfo;
+        Field(ValueType *) switchTypeInfo;
+        Field(LdElemInfo *) ldElemInfo;
+        Field(StElemInfo *) stElemInfo;
+        Field(ArrayCallSiteInfo *) arrayCallSiteInfo;
+        Field(ValueType *) parameterInfo;
+        Field(FldInfo *) fldInfo;
+        Field(ValueType *) slotInfo;
+        Field(ImplicitCallFlags *) loopImplicitCallFlags;
+        Field(ImplicitCallFlags) implicitCallFlags;
+        Field(BVFixed*) loopFlags;
+        Field(ThisInfo) thisInfo;
 
 
         // TODO (jedmiad): Consider storing a pair of property ID bit vectors indicating which properties are
         // TODO (jedmiad): Consider storing a pair of property ID bit vectors indicating which properties are
         // known to be non-fixed or non-equivalent. We could turn these on if we bailed out of fixed field type
         // known to be non-fixed or non-equivalent. We could turn these on if we bailed out of fixed field type
@@ -513,16 +513,17 @@ namespace Js
             bool disableLoopImplicitCallInfo : 1;
             bool disableLoopImplicitCallInfo : 1;
             bool disableStackArgOpt : 1;
             bool disableStackArgOpt : 1;
             bool disableTagCheck : 1;
             bool disableTagCheck : 1;
-        } bits;
+        };
+        Field(Bits) bits;
 
 
-        uint32 m_recursiveInlineInfo; // Bit is set for each callsites where the function is called recursively
-        uint32 polymorphicCacheState;
-        uint16 rejitCount;
-        BYTE currentInlinerVersion; // Used to detect when inlining profile changes
-        bool hasFunctionBody;
+        Field(uint32) m_recursiveInlineInfo; // Bit is set for each callsites where the function is called recursively
+        Field(uint32) polymorphicCacheState;
+        Field(uint16) rejitCount;
+        Field(BYTE) currentInlinerVersion; // Used to detect when inlining profile changes
+        Field(bool) hasFunctionBody;
 
 
 #if DBG
 #if DBG
-        bool persistsAcrossScriptContexts;
+        Field(bool) persistsAcrossScriptContexts;
 #endif
 #endif
         static JavascriptMethod EnsureDynamicProfileInfo(Js::ScriptFunction * function);
         static JavascriptMethod EnsureDynamicProfileInfo(Js::ScriptFunction * function);
 #if DBG_DUMP
 #if DBG_DUMP
@@ -558,9 +559,11 @@ namespace Js
 #endif
 #endif
         template <typename T>
         template <typename T>
         static void WriteArray(uint count, T * arr, FILE * file);
         static void WriteArray(uint count, T * arr, FILE * file);
+        template <typename T>
+        static void WriteArray(uint count, WriteBarrierPtr<T> arr, FILE * file);
 #endif
 #endif
 #if DBG_DUMP || defined(DYNAMIC_PROFILE_STORAGE) || defined(RUNTIME_DATA_COLLECTION)
 #if DBG_DUMP || defined(DYNAMIC_PROFILE_STORAGE) || defined(RUNTIME_DATA_COLLECTION)
-        FunctionBody * functionBody; // This will only be populated if NeedProfileInfoList is true
+        Field(FunctionBody *) functionBody; // This will only be populated if NeedProfileInfoList is true
 #endif
 #endif
 #ifdef DYNAMIC_PROFILE_STORAGE
 #ifdef DYNAMIC_PROFILE_STORAGE
         // Used by de-serialize
         // Used by de-serialize
@@ -820,9 +823,9 @@ namespace Js
 
 
     struct PolymorphicCallSiteInfo
     struct PolymorphicCallSiteInfo
     {
     {
-        Js::LocalFunctionId functionIds[DynamicProfileInfo::maxPolymorphicInliningSize];
-        Js::SourceId sourceIds[DynamicProfileInfo::maxPolymorphicInliningSize];
-        PolymorphicCallSiteInfo *next;
+        Field(Js::LocalFunctionId) functionIds[DynamicProfileInfo::maxPolymorphicInliningSize];
+        Field(Js::SourceId) sourceIds[DynamicProfileInfo::maxPolymorphicInliningSize];
+        Field(PolymorphicCallSiteInfo *) next;
         bool GetFunction(uint index, Js::LocalFunctionId *functionId, Js::SourceId *sourceId)
         bool GetFunction(uint index, Js::LocalFunctionId *functionId, Js::SourceId *sourceId)
         {
         {
             Assert(index < DynamicProfileInfo::maxPolymorphicInliningSize);
             Assert(index < DynamicProfileInfo::maxPolymorphicInliningSize);
@@ -907,6 +910,13 @@ namespace Js
             count += sizeof(T) * len;
             count += sizeof(T) * len;
             return true;
             return true;
         }
         }
+
+        template <typename T>
+        bool WriteArray(WriteBarrierPtr<T> data, size_t len)
+        {
+            return WriteArray(static_cast<T*>(data), len);
+        }
+
     private:
     private:
         size_t count;
         size_t count;
     };
     };
@@ -938,6 +948,13 @@ namespace Js
             lengthLeft -= size;
             lengthLeft -= size;
             return true;
             return true;
         }
         }
+
+        template <typename T>
+        bool WriteArray(WriteBarrierPtr<T> data, size_t len)
+        {
+            return WriteArray(static_cast<T*>(data), len);
+        }
+
     private:
     private:
         char * current;
         char * current;
         size_t lengthLeft;
         size_t lengthLeft;

+ 2 - 12
lib/Runtime/Language/FunctionCodeGenJitTimeData.cpp

@@ -59,11 +59,6 @@ namespace Js
         return inlinees ? inlinees[profiledCallSiteId] : nullptr;
         return inlinees ? inlinees[profiledCallSiteId] : nullptr;
     }
     }
 
 
-    FunctionCodeGenJitTimeData ** FunctionCodeGenJitTimeData::GetInlinees()
-    {
-        return inlinees;
-    }
-
     const FunctionCodeGenJitTimeData *FunctionCodeGenJitTimeData::GetJitTimeDataFromFunctionInfo(FunctionInfo *polyFunctionInfo) const
     const FunctionCodeGenJitTimeData *FunctionCodeGenJitTimeData::GetJitTimeDataFromFunctionInfo(FunctionInfo *polyFunctionInfo) const
     {
     {
         const FunctionCodeGenJitTimeData *next = this;
         const FunctionCodeGenJitTimeData *next = this;
@@ -82,11 +77,6 @@ namespace Js
         return ldFldInlinees ? ldFldInlinees[inlineCacheIndex] : nullptr;
         return ldFldInlinees ? ldFldInlinees[inlineCacheIndex] : nullptr;
     }
     }
 
 
-    FunctionCodeGenJitTimeData ** FunctionCodeGenJitTimeData::GetLdFldInlinees()
-    {
-        return ldFldInlinees;
-    }
-
     FunctionCodeGenJitTimeData *FunctionCodeGenJitTimeData::AddInlinee(
     FunctionCodeGenJitTimeData *FunctionCodeGenJitTimeData::AddInlinee(
         Recycler *const recycler,
         Recycler *const recycler,
         const ProfileId profiledCallSiteId,
         const ProfileId profiledCallSiteId,
@@ -101,7 +91,7 @@ namespace Js
 
 
         if (!inlinees)
         if (!inlinees)
         {
         {
-            inlinees = RecyclerNewArrayZ(recycler, FunctionCodeGenJitTimeData *, functionBody->GetProfiledCallSiteCount());
+            inlinees = RecyclerNewArrayZ(recycler, Field(FunctionCodeGenJitTimeData *), functionBody->GetProfiledCallSiteCount());
         }
         }
 
 
         FunctionCodeGenJitTimeData *inlineeData = nullptr;
         FunctionCodeGenJitTimeData *inlineeData = nullptr;
@@ -137,7 +127,7 @@ namespace Js
 
 
         if (!ldFldInlinees)
         if (!ldFldInlinees)
         {
         {
-            ldFldInlinees = RecyclerNewArrayZ(recycler, FunctionCodeGenJitTimeData *, GetFunctionBody()->GetInlineCacheCount());
+            ldFldInlinees = RecyclerNewArrayZ(recycler, Field(FunctionCodeGenJitTimeData*), GetFunctionBody()->GetInlineCacheCount());
         }
         }
 
 
         const auto inlineeData = RecyclerNew(recycler, FunctionCodeGenJitTimeData, inlinee, nullptr);
         const auto inlineeData = RecyclerNew(recycler, FunctionCodeGenJitTimeData, inlinee, nullptr);

+ 2 - 2
lib/Runtime/Language/InterpreterStackFrame.cpp

@@ -1460,8 +1460,8 @@ namespace Js
             int excess = this->inSlotsCount - executeFunction->GetInParamsCount();
             int excess = this->inSlotsCount - executeFunction->GetInParamsCount();
             *dest = JavascriptArray::OP_NewScArray(excess, executeFunction->GetScriptContext());
             *dest = JavascriptArray::OP_NewScArray(excess, executeFunction->GetScriptContext());
             JavascriptArray *array = static_cast<JavascriptArray *>(*dest);
             JavascriptArray *array = static_cast<JavascriptArray *>(*dest);
-            Var *elements = ((SparseArraySegment<Var>*)array->GetHead())->elements;
-            js_memcpy_s(elements, excess * sizeof(Var), src, excess * sizeof(Var));
+            Field(Var)* elements = ((SparseArraySegment<Var>*)array->GetHead())->elements;
+            CopyArray(elements, excess, src, excess);
         }
         }
         else
         else
         {
         {

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

@@ -870,7 +870,7 @@ namespace Js
         ThreadContext* threadContext = scriptContext? scriptContext->GetThreadContext() : ThreadContext::GetContextForCurrentThread();
         ThreadContext* threadContext = scriptContext? scriptContext->GetThreadContext() : ThreadContext::GetContextForCurrentThread();
 
 
         // Temporarily keep throwing exception object alive (thrown but not yet caught)
         // Temporarily keep throwing exception object alive (thrown but not yet caught)
-        JavascriptExceptionObject** addr = threadContext->SaveTempUncaughtException(exceptionObject);
+        Field(JavascriptExceptionObject*)* addr = threadContext->SaveTempUncaughtException(exceptionObject);
 
 
         // Throw a wrapper JavascriptException. catch handler must GetAndClear() the exception object.
         // Throw a wrapper JavascriptException. catch handler must GetAndClear() the exception object.
         throw JavascriptException(addr);
         throw JavascriptException(addr);

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

@@ -5608,7 +5608,7 @@ CommonNumber:
         {
         {
             segment->length = count;
             segment->length = count;
         }
         }
-        js_memcpy_s(segment->elements, sizeof(Var) * segment->length, vars->elements, sizeof(Var) * count);
+        CopyArray(segment->elements, segment->length, vars->elements, count);
 
 
         return segment;
         return segment;
     }
     }

+ 5 - 1
lib/Runtime/Language/SourceTextModuleRecord.cpp

@@ -115,9 +115,13 @@ namespace Js
 
 
                 LoadScriptFlag loadScriptFlag = (LoadScriptFlag)(LoadScriptFlag_Expression | LoadScriptFlag_Module |
                 LoadScriptFlag loadScriptFlag = (LoadScriptFlag)(LoadScriptFlag_Expression | LoadScriptFlag_Module |
                     (isUtf8 ? LoadScriptFlag_Utf8Source : LoadScriptFlag_None));
                     (isUtf8 ? LoadScriptFlag_Utf8Source : LoadScriptFlag_None));
+
+                Utf8SourceInfo* pResultSourceInfo = nullptr;
                 this->parseTree = scriptContext->ParseScript(parser, sourceText,
                 this->parseTree = scriptContext->ParseScript(parser, sourceText,
-                    sourceLength, srcInfo, &se, &pSourceInfo, _u("module"),
+                    sourceLength, srcInfo, &se, &pResultSourceInfo, _u("module"),
                     loadScriptFlag, &sourceIndex, nullptr);
                     loadScriptFlag, &sourceIndex, nullptr);
+                this->pSourceInfo = pResultSourceInfo;
+
                 if (parseTree == nullptr)
                 if (parseTree == nullptr)
                 {
                 {
                     hr = E_FAIL;
                     hr = E_FAIL;

+ 8 - 7
lib/Runtime/Library/ConcatString.cpp

@@ -164,7 +164,7 @@ namespace Js
         ConcatStringBuilder* current = this;
         ConcatStringBuilder* current = this;
         while (current != NULL)
         while (current != NULL)
         {
         {
-            memset(current->m_slots, 0, current->m_count * sizeof(JavascriptString*));
+            ClearArray(current->m_slots, current->m_count);
             current = current->m_prevChunk;
             current = current->m_prevChunk;
         }
         }
 
 
@@ -194,8 +194,9 @@ namespace Js
             if (newSlotCount <= c_maxChunkSlotCount)
             if (newSlotCount <= c_maxChunkSlotCount)
             {
             {
                 // While we fit into MAX chunk size, realloc/grow current chunk.
                 // While we fit into MAX chunk size, realloc/grow current chunk.
-                JavascriptString** newSlots = RecyclerNewArray(this->GetScriptContext()->GetRecycler(), JavascriptString*, newSlotCount);
-                memcpy_s(newSlots, newSlotCount * sizeof(JavascriptString*), m_slots, m_slotCount * sizeof(JavascriptString*));
+                Field(JavascriptString*)* newSlots = RecyclerNewArray(
+                    this->GetScriptContext()->GetRecycler(), Field(JavascriptString*), newSlotCount);
+                CopyArray(newSlots, newSlotCount, m_slots, m_slotCount);
                 m_slots = newSlots;
                 m_slots = newSlots;
                 m_slotCount = newSlotCount;
                 m_slotCount = newSlotCount;
             }
             }
@@ -226,12 +227,12 @@ namespace Js
         if (requestedSlotCount > 0)
         if (requestedSlotCount > 0)
         {
         {
             m_slotCount = min(requestedSlotCount, this->c_maxChunkSlotCount);
             m_slotCount = min(requestedSlotCount, this->c_maxChunkSlotCount);
-            m_slots = RecyclerNewArray(this->GetScriptContext()->GetRecycler(), JavascriptString*, m_slotCount);
+            m_slots = RecyclerNewArray(this->GetScriptContext()->GetRecycler(), Field(JavascriptString*), m_slotCount);
         }
         }
         else
         else
         {
         {
             m_slotCount = 0;
             m_slotCount = 0;
-            m_slots = 0;
+            m_slots = nullptr;
         }
         }
     }
     }
 
 
@@ -303,7 +304,7 @@ namespace Js
         ConcatStringBase(stringTypeStatic), slotCount(slotCount)
         ConcatStringBase(stringTypeStatic), slotCount(slotCount)
     {
     {
 #if DBG
 #if DBG
-        memset(m_slots, 0, slotCount * sizeof(JavascriptString* ));
+        ClearArray(m_slots, slotCount);
 #endif
 #endif
         m_slots[0] = CompoundString::GetImmutableOrScriptUnreferencedString(a1);
         m_slots[0] = CompoundString::GetImmutableOrScriptUnreferencedString(a1);
         m_slots[1] = CompoundString::GetImmutableOrScriptUnreferencedString(a2);
         m_slots[1] = CompoundString::GetImmutableOrScriptUnreferencedString(a2);
@@ -345,7 +346,7 @@ namespace Js
         const char16 * sz = GetSzImpl<ConcatStringMulti>();
         const char16 * sz = GetSzImpl<ConcatStringMulti>();
 
 
         // Allow slots to be garbage collected if no more refs.
         // Allow slots to be garbage collected if no more refs.
-        memset(m_slots, 0, slotCount * sizeof(JavascriptString*));
+        ClearArray(m_slots, slotCount);
 
 
         return sz;
         return sz;
     }
     }

+ 11 - 11
lib/Runtime/Library/ConcatString.h

@@ -59,11 +59,11 @@ namespace Js
 
 
         virtual void CopyVirtual(_Out_writes_(m_charLength) char16 *const buffer, StringCopyInfoStack &nestedStringTreeCopyInfos, const byte recursionDepth) override
         virtual void CopyVirtual(_Out_writes_(m_charLength) char16 *const buffer, StringCopyInfoStack &nestedStringTreeCopyInfos, const byte recursionDepth) override
         {
         {
-            __super::CopyImpl(buffer, N, m_slots, nestedStringTreeCopyInfos, recursionDepth);
+            __super::CopyImpl(buffer, N, &m_slots[0], nestedStringTreeCopyInfos, recursionDepth);
         }
         }
         virtual int GetRandomAccessItemsFromConcatString(Js::JavascriptString * const *& items) const
         virtual int GetRandomAccessItemsFromConcatString(Js::JavascriptString * const *& items) const
         {
         {
-            items = m_slots;
+            items = &m_slots[0];
             return N;
             return N;
         }
         }
 
 
@@ -73,7 +73,7 @@ namespace Js
         void SetItem(_In_range_(0, N - 1) int index, JavascriptString* value);
         void SetItem(_In_range_(0, N - 1) int index, JavascriptString* value);
 
 
     protected:
     protected:
-        JavascriptString* m_slots[N];   // These contain the child nodes. 1 slot is per 1 item (JavascriptString*).
+        Field(JavascriptString* ) m_slots[N];   // These contain the child nodes. 1 slot is per 1 item (JavascriptString*).
     };
     };
 
 
     // Concat string that uses binary tree, each node has 2 children.
     // Concat string that uses binary tree, each node has 2 children.
@@ -129,10 +129,10 @@ namespace Js
         static const int c_maxChunkSlotCount = 1024;
         static const int c_maxChunkSlotCount = 1024;
         int GetItemCount() const;
         int GetItemCount() const;
 
 
-        JavascriptString** m_slots; // Array of child nodes.
-        int m_slotCount;   // Number of allocated slots (1 slot holds 1 item) in this chunk.
-        int m_count;       // Actual number of items in this chunk.
-        ConcatStringBuilder* m_prevChunk;
+        Field(Field(JavascriptString*)*) m_slots; // Array of child nodes.
+        Field(int) m_slotCount;   // Number of allocated slots (1 slot holds 1 item) in this chunk.
+        Field(int) m_count;       // Actual number of items in this chunk.
+        Field(ConcatStringBuilder*) m_prevChunk;
     };
     };
 
 
     // Concat string that wraps another string.
     // Concat string that wraps another string.
@@ -202,12 +202,12 @@ namespace Js
         virtual void CopyVirtual(_Out_writes_(m_charLength) char16 *const buffer, StringCopyInfoStack &nestedStringTreeCopyInfos, const byte recursionDepth) override
         virtual void CopyVirtual(_Out_writes_(m_charLength) char16 *const buffer, StringCopyInfoStack &nestedStringTreeCopyInfos, const byte recursionDepth) override
         {
         {
             Assert(IsFilled());
             Assert(IsFilled());
-            __super::CopyImpl(buffer, slotCount, m_slots, nestedStringTreeCopyInfos, recursionDepth);
+            __super::CopyImpl(buffer, slotCount, &m_slots[0], nestedStringTreeCopyInfos, recursionDepth);
         }
         }
         virtual int GetRandomAccessItemsFromConcatString(Js::JavascriptString * const *& items) const
         virtual int GetRandomAccessItemsFromConcatString(Js::JavascriptString * const *& items) const
         {
         {
             Assert(IsFilled());
             Assert(IsFilled());
-            items = m_slots;
+            items = &m_slots[0];
             return slotCount;
             return slotCount;
         }
         }
 
 
@@ -222,8 +222,8 @@ namespace Js
         static uint32 GetOffsetOfSlotCount() { return offsetof(ConcatStringMulti, slotCount); }
         static uint32 GetOffsetOfSlotCount() { return offsetof(ConcatStringMulti, slotCount); }
         static uint32 GetOffsetOfSlots() { return offsetof(ConcatStringMulti, m_slots); }
         static uint32 GetOffsetOfSlots() { return offsetof(ConcatStringMulti, m_slots); }
     protected:
     protected:
-        uint slotCount;
-        JavascriptString* m_slots[];   // These contain the child nodes.
+        Field(uint) slotCount;
+        Field(JavascriptString*) m_slots[];   // These contain the child nodes.
 
 
 #if DBG
 #if DBG
         bool IsFilled() const;
         bool IsFilled() const;

+ 4 - 1
lib/Runtime/Library/ES5ArrayIndexEnumerator.cpp

@@ -26,7 +26,10 @@ namespace Js
                 }
                 }
                 if (index == descriptorIndex || !GetArray()->IsValidDescriptorToken(descriptorValidationToken))
                 if (index == descriptorIndex || !GetArray()->IsValidDescriptorToken(descriptorValidationToken))
                 {
                 {
-                    descriptorIndex = GetArray()->GetNextDescriptor(index, &descriptor, &descriptorValidationToken);
+                    Js::IndexPropertyDescriptor * pResultDescriptor = nullptr;
+                    descriptorIndex = GetArray()->GetNextDescriptor(
+                        index, &pResultDescriptor, &descriptorValidationToken);
+                    this->descriptor = pResultDescriptor;
                 }
                 }
 
 
                 index = min(dataIndex, descriptorIndex);
                 index = min(dataIndex, descriptorIndex);

+ 4 - 2
lib/Runtime/Library/IteratorObjectEnumerator.cpp

@@ -23,8 +23,10 @@ namespace Js
     Var IteratorObjectEnumerator::MoveAndGetNext(PropertyId& propertyId, PropertyAttributes* attributes)
     Var IteratorObjectEnumerator::MoveAndGetNext(PropertyId& propertyId, PropertyAttributes* attributes)
     {
     {
         ScriptContext* scriptContext = GetScriptContext();
         ScriptContext* scriptContext = GetScriptContext();
-        if (JavascriptOperators::IteratorStepAndValue(iteratorObject, scriptContext, &value))
+        Var resultValue = nullptr;
+        if (JavascriptOperators::IteratorStepAndValue(iteratorObject, scriptContext, &resultValue))
         {
         {
+            this->value = resultValue;
             if (attributes != nullptr)
             if (attributes != nullptr)
             {
             {
                 *attributes = PropertyEnumerable;
                 *attributes = PropertyEnumerable;
@@ -44,7 +46,7 @@ namespace Js
             else
             else
             {
             {
                 JavascriptString* propertyName = JavascriptConversion::ToString(currentIndex, scriptContext);
                 JavascriptString* propertyName = JavascriptConversion::ToString(currentIndex, scriptContext);
-                GetScriptContext()->GetOrAddPropertyRecord(propertyName->GetString(), propertyName->GetLength(), &propertyRecord);
+                scriptContext->GetOrAddPropertyRecord(propertyName->GetString(), propertyName->GetLength(), &propertyRecord);
             }
             }
 
 
             propertyId = propertyRecord->GetPropertyId();
             propertyId = propertyRecord->GetPropertyId();

+ 23 - 22
lib/Runtime/Library/JavascriptArray.cpp

@@ -15,7 +15,7 @@ namespace Js
     const SparseArraySegmentBase *JavascriptArray::EmptySegment = (SparseArraySegmentBase *)&EmptySegmentData;
     const SparseArraySegmentBase *JavascriptArray::EmptySegment = (SparseArraySegmentBase *)&EmptySegmentData;
 
 
     // col0 : allocation bucket
     // col0 : allocation bucket
-    // col1 : No. of missing items to set during initialization depending on bucket. 
+    // col1 : No. of missing items to set during initialization depending on bucket.
     // col2 : allocation size for elements in given bucket.
     // col2 : allocation size for elements in given bucket.
     // col1 and col2 is calculated at runtime
     // col1 and col2 is calculated at runtime
     uint JavascriptNativeFloatArray::allocationBuckets[][AllocationBucketsInfoSize] =
     uint JavascriptNativeFloatArray::allocationBuckets[][AllocationBucketsInfoSize] =
@@ -771,7 +771,7 @@ namespace Js
 
 
         SparseArraySegment<Var> *head = (SparseArraySegment<Var>*)arr->head;
         SparseArraySegment<Var> *head = (SparseArraySegment<Var>*)arr->head;
         Assert(elementCount <= head->length);
         Assert(elementCount <= head->length);
-        js_memcpy_s(head->elements, sizeof(Var) * head->length, elements, sizeof(Var) * elementCount);
+        CopyArray(head->elements, head->length, elements, elementCount);
 
 
 #ifdef VALIDATE_ARRAY
 #ifdef VALIDATE_ARRAY
         arr->ValidateArray();
         arr->ValidateArray();
@@ -850,7 +850,7 @@ namespace Js
                 arr = scriptContext->GetLibrary()->CreateNativeIntArrayLiteral(count);
                 arr = scriptContext->GetLibrary()->CreateNativeIntArrayLiteral(count);
                 SparseArraySegment<int32> *head = static_cast<SparseArraySegment<int32>*>(arr->head);
                 SparseArraySegment<int32> *head = static_cast<SparseArraySegment<int32>*>(arr->head);
                 Assert(count > 0 && count == head->length);
                 Assert(count > 0 && count == head->length);
-                js_memcpy_s(head->elements, sizeof(int32)* head->length, ints->elements, sizeof(int32)* count);
+                CopyArray(head->elements, head->length, ints->elements, count);
             }
             }
 
 
             arr->SetArrayProfileInfo(weakFuncRef, arrayInfo);
             arr->SetArrayProfileInfo(weakFuncRef, arrayInfo);
@@ -909,7 +909,7 @@ namespace Js
             JavascriptNativeFloatArray *arr = scriptContext->GetLibrary()->CreateNativeFloatArrayLiteral(count);
             JavascriptNativeFloatArray *arr = scriptContext->GetLibrary()->CreateNativeFloatArrayLiteral(count);
             SparseArraySegment<double> *head = (SparseArraySegment<double>*)arr->head;
             SparseArraySegment<double> *head = (SparseArraySegment<double>*)arr->head;
             Assert(count > 0 && count == head->length);
             Assert(count > 0 && count == head->length);
-            js_memcpy_s(head->elements, sizeof(double) * head->length, doubles->elements, sizeof(double) * count);
+            CopyArray(head->elements, head->length, doubles->elements, count);
             arr->SetArrayProfileInfo(weakFuncRef, arrayInfo);
             arr->SetArrayProfileInfo(weakFuncRef, arrayInfo);
 
 
             return arr;
             return arr;
@@ -4010,7 +4010,7 @@ namespace Js
     }
     }
 
 
     template<>
     template<>
-    void JavascriptArray::CopyValueToSegmentBuferNoCheck(double* buffer, uint32 length, double value)
+    void JavascriptArray::CopyValueToSegmentBuferNoCheck(Field(double)* buffer, uint32 length, double value)
     {
     {
         if (JavascriptNumber::IsZero(value) && !JavascriptNumber::IsNegZero(value))
         if (JavascriptNumber::IsZero(value) && !JavascriptNumber::IsNegZero(value))
         {
         {
@@ -4026,7 +4026,7 @@ namespace Js
     }
     }
 
 
     template<>
     template<>
-    void JavascriptArray::CopyValueToSegmentBuferNoCheck(int32* buffer, uint32 length, int32 value)
+    void JavascriptArray::CopyValueToSegmentBuferNoCheck(Field(int32)* buffer, uint32 length, int32 value)
     {
     {
         if (value == 0 || AreAllBytesEqual(value))
         if (value == 0 || AreAllBytesEqual(value))
         {
         {
@@ -4042,7 +4042,7 @@ namespace Js
     }
     }
 
 
     template<>
     template<>
-    void JavascriptArray::CopyValueToSegmentBuferNoCheck(Js::Var* buffer, uint32 length, Js::Var value)
+    void JavascriptArray::CopyValueToSegmentBuferNoCheck(Field(Js::Var)* buffer, uint32 length, Js::Var value)
     {
     {
         for (uint32 i = 0; i < length; i++)
         for (uint32 i = 0; i < length; i++)
         {
         {
@@ -5451,7 +5451,7 @@ Case0:
                 {
                 {
                     head = head->GrowByMin(recycler, next->length - 1); //-1 is to account for unshift
                     head = head->GrowByMin(recycler, next->length - 1); //-1 is to account for unshift
                 }
                 }
-                memmove(head->elements + offset, next->elements, next->length * sizeof(T));
+                MoveArray(head->elements + offset, next->elements, next->length);
                 head->length = offset + next->length;
                 head->length = offset + next->length;
                 pArr->head = head;
                 pArr->head = head;
             }
             }
@@ -5688,7 +5688,7 @@ Case0:
         SparseArraySegment<T>* pnewHeadSeg = (SparseArraySegment<T>*)pnewArr->head;
         SparseArraySegment<T>* pnewHeadSeg = (SparseArraySegment<T>*)pnewArr->head;
 
 
         // Fill the newly created sliced array
         // Fill the newly created sliced array
-        js_memcpy_s(pnewHeadSeg->elements, sizeof(T) * newLen, headSeg->elements + start, sizeof(T) * newLen);
+        CopyArray(pnewHeadSeg->elements, newLen, headSeg->elements + start, newLen);
         pnewHeadSeg->length = newLen;
         pnewHeadSeg->length = newLen;
 
 
         Assert(pnewHeadSeg->length <= pnewHeadSeg->size);
         Assert(pnewHeadSeg->length <= pnewHeadSeg->size);
@@ -6165,13 +6165,13 @@ Case0:
         }
         }
     }
     }
 
 
-    static void hybridSort(__inout_ecount(length) Var *elements, uint32 length, CompareVarsInfo* compareInfo)
+    static void hybridSort(__inout_ecount(length) Field(Var) *elements, uint32 length, CompareVarsInfo* compareInfo)
     {
     {
         // The cost of memory moves starts to be more expensive than additional comparer calls (given a simple comparer)
         // The cost of memory moves starts to be more expensive than additional comparer calls (given a simple comparer)
         // for arrays of more than 512 elements.
         // for arrays of more than 512 elements.
         if (length > 512)
         if (length > 512)
         {
         {
-            qsort_s(elements, length, sizeof(Var), compareVars, compareInfo);
+            qsort_s(elements, length, sizeof(Field(Var)), compareVars, compareInfo);
             return;
             return;
         }
         }
 
 
@@ -6196,7 +6196,7 @@ Case0:
 
 
                 // insert value right before first:
                 // insert value right before first:
                 Var value = elements[i];
                 Var value = elements[i];
-                memmove(elements + first + 1, elements + first, (i - first) * sizeof(Var));
+                MoveArray(elements + first + 1, elements + first, (i - first));
                 elements[first] = value;
                 elements[first] = value;
             }
             }
         }
         }
@@ -6341,7 +6341,7 @@ Case0:
         return;
         return;
     }
     }
 
 
-    uint32 JavascriptArray::sort(__inout_ecount(*len) Var *orig, uint32 *len, ScriptContext *scriptContext)
+    uint32 JavascriptArray::sort(__inout_ecount(*len) Field(Var) *orig, uint32 *len, ScriptContext *scriptContext)
     {
     {
         uint32 count = 0, countUndefined = 0;
         uint32 count = 0, countUndefined = 0;
         Element *elements = RecyclerNewArrayZ(scriptContext->GetRecycler(), Element, *len);
         Element *elements = RecyclerNewArrayZ(scriptContext->GetRecycler(), Element, *len);
@@ -6899,9 +6899,9 @@ Case0:
             if (headDeleteLen != insertLen)
             if (headDeleteLen != insertLen)
             {
             {
                 uint32 noElementsToMove = seg->length - (relativeStart + headDeleteLen);
                 uint32 noElementsToMove = seg->length - (relativeStart + headDeleteLen);
-                memmove(seg->elements + relativeStart + insertLen,
-                                     seg->elements + relativeStart + headDeleteLen,
-                                     sizeof(T) * noElementsToMove);
+                MoveArray(seg->elements + relativeStart + insertLen,
+                            seg->elements + relativeStart + headDeleteLen,
+                            noElementsToMove);
                 if (newHeadLen < seg->length) // truncate if necessary
                 if (newHeadLen < seg->length) // truncate if necessary
                 {
                 {
                     seg->Truncate(seg->left + newHeadLen); // set end elements to null so that when we introduce null elements we are safe
                     seg->Truncate(seg->left + newHeadLen); // set end elements to null so that when we introduce null elements we are safe
@@ -6915,7 +6915,8 @@ Case0:
                    !VirtualTableInfo<JavascriptNativeFloatArray>::HasVirtualTable(pnewArr));
                    !VirtualTableInfo<JavascriptNativeFloatArray>::HasVirtualTable(pnewArr));
 
 
                 // inserted elements starts at argument 3 of splice(start, deleteNumber, insertelem1, insertelem2, insertelem3, ...);
                 // inserted elements starts at argument 3 of splice(start, deleteNumber, insertelem1, insertelem2, insertelem3, ...);
-                js_memcpy_s(seg->elements + relativeStart, sizeof(Var) * insertLen, insertArgs, sizeof(Var) * insertLen);
+                CopyArray(seg->elements + relativeStart, insertLen,
+                          reinterpret_cast<const T*>(insertArgs), insertLen);
             }
             }
             *prev = seg;
             *prev = seg;
         }
         }
@@ -7132,7 +7133,7 @@ Case0:
                     prevNewHeadSeg = &newHeadSeg->next;
                     prevNewHeadSeg = &newHeadSeg->next;
 
 
                     // move the last segment
                     // move the last segment
-                    memmove(startSeg->elements, startSeg->elements + headDeleteLen, sizeof(T) * (startSeg->length - headDeleteLen));
+                    MoveArray(startSeg->elements, startSeg->elements + headDeleteLen, startSeg->length - headDeleteLen);
                     startSeg->left = startSeg->left + headDeleteLen; // We are moving the left ahead to point to the right index
                     startSeg->left = startSeg->left + headDeleteLen; // We are moving the left ahead to point to the right index
                     startSeg->length = startSeg->length - headDeleteLen;
                     startSeg->length = startSeg->length - headDeleteLen;
                     startSeg->Truncate(startSeg->left + startSeg->length);
                     startSeg->Truncate(startSeg->left + startSeg->length);
@@ -7205,7 +7206,8 @@ Case0:
 
 
             uint32 relativeStart = start - segInsert->left;
             uint32 relativeStart = start - segInsert->left;
             // inserted elements starts at argument 3 of splice(start, deleteNumber, insertelem1, insertelem2, insertelem3, ...);
             // inserted elements starts at argument 3 of splice(start, deleteNumber, insertelem1, insertelem2, insertelem3, ...);
-            js_memcpy_s(segInsert->elements + relativeStart, sizeof(T) * insertLen, insertArgs, sizeof(T) * insertLen);
+            CopyArray(segInsert->elements + relativeStart, insertLen,
+                      reinterpret_cast<const T*>(insertArgs), insertLen);
         }
         }
     }
     }
 
 
@@ -7425,7 +7427,7 @@ Case0:
     {
     {
         SparseArraySegment<T>* head = (SparseArraySegment<T>*)pArr->head;
         SparseArraySegment<T>* head = (SparseArraySegment<T>*)pArr->head;
         // Make enough room in the head segment to insert new elements at the front
         // Make enough room in the head segment to insert new elements at the front
-        memmove(head->elements + unshiftElements, head->elements, sizeof(T) * pArr->head->length);
+        MoveArray(head->elements + unshiftElements, head->elements, pArr->head->length);
         uint32 oldHeadLength = head->length;
         uint32 oldHeadLength = head->length;
         head->length += unshiftElements;
         head->length += unshiftElements;
 
 
@@ -11290,8 +11292,7 @@ Case0:
         dst->size = src->size;
         dst->size = src->size;
         dst->next = src->next;
         dst->next = src->next;
 
 
-        js_memcpy_s(dst->elements, sizeof(T) * dst->size, src->elements, sizeof(T) * src->size);
-
+        CopyArray(dst->elements, dst->size, src->elements, src->size);
     }
     }
 
 
     JavascriptArray::JavascriptArray(JavascriptArray * instance, bool boxHead)
     JavascriptArray::JavascriptArray(JavascriptArray * instance, bool boxHead)

+ 8 - 6
lib/Runtime/Library/JavascriptArray.h

@@ -81,7 +81,7 @@ namespace Js
         void Add(Recycler* recycler, SparseArraySegmentBase* newSeg);
         void Add(Recycler* recycler, SparseArraySegmentBase* newSeg);
         void Find(uint itemIndex, SparseArraySegmentBase*& prevOrMatch, SparseArraySegmentBase*& matchOrNext);
         void Find(uint itemIndex, SparseArraySegmentBase*& prevOrMatch, SparseArraySegmentBase*& matchOrNext);
 
 
-        SparseArraySegmentBase * lastUsedSegment;
+        FieldNoBarrier(SparseArraySegmentBase *) lastUsedSegment;
     };
     };
 
 
     class JavascriptArray : public ArrayObject
     class JavascriptArray : public ArrayObject
@@ -102,11 +102,13 @@ namespace Js
         bool isInitialized;
         bool isInitialized;
     protected:
     protected:
         SparseArraySegmentBase* head;
         SparseArraySegmentBase* head;
-        union
+        union SegmentUnionType
         {
         {
             SparseArraySegmentBase* lastUsedSegment;
             SparseArraySegmentBase* lastUsedSegment;
             SegmentBTreeRoot* segmentBTreeRoot;
             SegmentBTreeRoot* segmentBTreeRoot;
-        }segmentUnion;
+        };
+        // SWB-TODO: How to handle write barrier inside union?
+        SegmentUnionType segmentUnion;
     public:
     public:
         typedef Var TElement;
         typedef Var TElement;
 
 
@@ -123,7 +125,7 @@ namespace Js
         static const uint8 AllocationBucketIndex = 0;
         static const uint8 AllocationBucketIndex = 0;
         // 1st column in allocationBuckets that stores no. of missing elements to initialize for given bucket
         // 1st column in allocationBuckets that stores no. of missing elements to initialize for given bucket
         static const uint8 MissingElementsCountIndex = 1;
         static const uint8 MissingElementsCountIndex = 1;
-        // 2nd column in allocationBuckets that stores allocation size for given bucket 
+        // 2nd column in allocationBuckets that stores allocation size for given bucket
         static const uint8 AllocationSizeIndex = 2;
         static const uint8 AllocationSizeIndex = 2;
 #if defined(_M_X64_OR_ARM64)
 #if defined(_M_X64_OR_ARM64)
         static const uint8 AllocationBucketsCount = 3;
         static const uint8 AllocationBucketsCount = 3;
@@ -182,7 +184,7 @@ namespace Js
 #if ENABLE_PROFILE_INFO
 #if ENABLE_PROFILE_INFO
         template<typename T> inline void DirectProfiledSetItemInHeadSegmentAt(const uint32 offset, const T newValue, StElemInfo *const stElemInfo);
         template<typename T> inline void DirectProfiledSetItemInHeadSegmentAt(const uint32 offset, const T newValue, StElemInfo *const stElemInfo);
 #endif
 #endif
-        template<typename T> static void CopyValueToSegmentBuferNoCheck(T* buffer, uint32 length, T value);
+        template<typename T> static void CopyValueToSegmentBuferNoCheck(Field(T)* buffer, uint32 length, T value);
         template<typename T> void DirectSetItem_Full(uint32 itemIndex, T newValue);
         template<typename T> void DirectSetItem_Full(uint32 itemIndex, T newValue);
         template<typename T> SparseArraySegment<T>* PrepareSegmentForMemOp(uint32 startIndex, uint32 length);
         template<typename T> SparseArraySegment<T>* PrepareSegmentForMemOp(uint32 startIndex, uint32 length);
         template<typename T> bool DirectSetItemAtRange(uint32 startIndex, uint32 length, T newValue);
         template<typename T> bool DirectSetItemAtRange(uint32 startIndex, uint32 length, T newValue);
@@ -559,7 +561,7 @@ namespace Js
         template<typename T> void AllocateHead();
         template<typename T> void AllocateHead();
         template<typename T> void EnsureHead();
         template<typename T> void EnsureHead();
 
 
-        uint32 sort(__inout_ecount(*length) Var *orig, uint32 *length, ScriptContext *scriptContext);
+        uint32 sort(__inout_ecount(*length) Field(Var) *orig, uint32 *length, ScriptContext *scriptContext);
 
 
         BOOL GetPropertyBuiltIns(PropertyId propertyId, Var* value);
         BOOL GetPropertyBuiltIns(PropertyId propertyId, Var* value);
         bool GetSetterBuiltIns(PropertyId propertyId, PropertyValueInfo* info, DescriptorFlags* descriptorFlags);
         bool GetSetterBuiltIns(PropertyId propertyId, PropertyValueInfo* info, DescriptorFlags* descriptorFlags);

+ 17 - 15
lib/Runtime/Library/JavascriptArray.inl

@@ -108,7 +108,7 @@ namespace Js
         }
         }
         Recycler *recycler = this->GetScriptContext()->GetRecycler();
         Recycler *recycler = this->GetScriptContext()->GetRecycler();
         SparseArraySegment<T> *newSeg = SparseArraySegment<T>::AllocateSegment(recycler, seg->left, seg->length, nextSeg);
         SparseArraySegment<T> *newSeg = SparseArraySegment<T>::AllocateSegment(recycler, seg->left, seg->length, nextSeg);
-        js_memcpy_s(newSeg->elements, sizeof(T) * seg->length, seg->elements, sizeof(T) * seg->length);
+        CopyArray(newSeg->elements, seg->length, seg->elements, seg->length);
 
 
         LinkSegmentsCommon(prior, newSeg);
         LinkSegmentsCommon(prior, newSeg);
         LinkSegmentsCommon(newSeg, nextSeg);
         LinkSegmentsCommon(newSeg, nextSeg);
@@ -517,7 +517,7 @@ SECOND_PASS:
             uint32 limit =  nextSeg->left + nextSeg->length;
             uint32 limit =  nextSeg->left + nextSeg->length;
             if (index < limit)
             if (index < limit)
             {
             {
-                T* v = &((SparseArraySegment<T>*)nextSeg)->elements[index - nextSeg->left];
+                const T * v = &((SparseArraySegment<T>*)nextSeg)->elements[index - nextSeg->left];
 
 
                 this->SetLastUsedSegment(nextSeg);
                 this->SetLastUsedSegment(nextSeg);
 
 
@@ -849,8 +849,9 @@ SECOND_PASS:
                         {
                         {
                             // we have some leftover items on endseg
                             // we have some leftover items on endseg
                             growby = (endSeg->length - endOffset - 1);
                             growby = (endSeg->length - endOffset - 1);
-                            current = ((Js::SparseArraySegment<T>*)current)->GrowByMin(recycler, growby);
-                            js_memcpy_s(((Js::SparseArraySegment<T>*)current)->elements + startOffset + length, sizeof(T)* growby, ((Js::SparseArraySegment<T>*)endSeg)->elements + endOffset + 1, sizeof(T)* growby);
+                            current = current->GrowByMin(recycler, growby);
+                            CopyArray(current->elements + startOffset + length, growby,
+                                ((Js::SparseArraySegment<T>*)endSeg)->elements + endOffset + 1, growby);
                             LinkSegments((Js::SparseArraySegment<T>*)startPrev, current);
                             LinkSegments((Js::SparseArraySegment<T>*)startPrev, current);
                             current->length = startOffset + length + growby;
                             current->length = startOffset + length + growby;
                         }
                         }
@@ -872,8 +873,9 @@ SECOND_PASS:
 
 
                         // extend current to hold endSeg
                         // extend current to hold endSeg
                         growby = endSeg->length;
                         growby = endSeg->length;
-                        current = ((Js::SparseArraySegment<T>*)current)->GrowByMin(recycler, growby);
-                        js_memcpy_s(((Js::SparseArraySegment<T>*)current)->elements + endIndex + 1, sizeof(T)* endSeg->length, ((Js::SparseArraySegment<T>*)endSeg)->elements, sizeof(T)* endSeg->length);
+                        current = current->GrowByMin(recycler, growby);
+                        CopyArray(current->elements + endIndex + 1, endSeg->length,
+                            ((Js::SparseArraySegment<T>*)endSeg)->elements, endSeg->length);
                         LinkSegments((Js::SparseArraySegment<T>*)startPrev, current);
                         LinkSegments((Js::SparseArraySegment<T>*)startPrev, current);
                         if (HasNoMissingValues())
                         if (HasNoMissingValues())
                         {
                         {
@@ -984,11 +986,11 @@ SECOND_PASS:
         int fromStartOffset = fromStartIndex - fromSegment->left;
         int fromStartOffset = fromStartIndex - fromSegment->left;
         Assert((fromStartOffset + length) <= fromSegment->length);
         Assert((fromStartOffset + length) <= fromSegment->length);
 
 
-        js_memcpy_s(
+        CopyArray(
             toSegment->elements + toStartOffset,
             toSegment->elements + toStartOffset,
-            (toSegment->size - toStartOffset) * sizeof(T),
+            toSegment->size - toStartOffset,
             fromSegment->elements + fromStartOffset,
             fromSegment->elements + fromStartOffset,
-            memcopySize * sizeof(T)
+            memcopySize
         );
         );
 
 
         fromArray->SetLastUsedSegment(fromSegment);
         fromArray->SetLastUsedSegment(fromSegment);
@@ -1087,7 +1089,7 @@ SECOND_PASS:
             return false;
             return false;
         }
         }
         Assert(current->left + current->length >= startIndex + length);
         Assert(current->left + current->length >= startIndex + length);
-        T* segmentCopyStart = current->elements + (startIndex - current->left);
+        Field(T)* segmentCopyStart = current->elements + (startIndex - current->left);
         CopyValueToSegmentBuferNoCheck(segmentCopyStart, length, newValue);
         CopyValueToSegmentBuferNoCheck(segmentCopyStart, length, newValue);
         this->SetLastUsedSegment(current);
         this->SetLastUsedSegment(current);
 #if DBG
 #if DBG
@@ -1446,7 +1448,7 @@ SECOND_PASS:
 
 
         SparseArraySegment<T> *const segment = (SparseArraySegment<T>*)head;
         SparseArraySegment<T> *const segment = (SparseArraySegment<T>*)head;
         const uint segmentLength = segment->length;
         const uint segmentLength = segment->length;
-        const T *const segmentElements = segment->elements;
+        const Field(T) * const segmentElements = segment->elements;
         for(uint i = startIndex; i < segmentLength; ++i)
         for(uint i = startIndex; i < segmentLength; ++i)
         {
         {
             if(SparseArraySegment<T>::IsMissingItem(&segmentElements[i]))
             if(SparseArraySegment<T>::IsMissingItem(&segmentElements[i]))
@@ -1465,7 +1467,7 @@ SECOND_PASS:
         //Assert(!HasNoMissingValues());
         //Assert(!HasNoMissingValues());
 
 
         SparseArraySegment<T> *const segment = (SparseArraySegment<T>*)head;
         SparseArraySegment<T> *const segment = (SparseArraySegment<T>*)head;
-        const T *const segmentElements = segment->elements;
+        const Field(T) *const segmentElements = segment->elements;
         for (uint i = startIndex; i < endIndex; ++i)
         for (uint i = startIndex; i < endIndex; ++i)
         {
         {
             if (SparseArraySegment<T>::IsMissingItem(&segmentElements[i]))
             if (SparseArraySegment<T>::IsMissingItem(&segmentElements[i]))
@@ -1667,7 +1669,7 @@ SECOND_PASS:
         return totalSize;
         return totalSize;
     }
     }
 
 
-    template<class ArrayType> 
+    template<class ArrayType>
     void JavascriptArray::EnsureCalculationOfAllocationBuckets()
     void JavascriptArray::EnsureCalculationOfAllocationBuckets()
     {
     {
         uint temp;
         uint temp;
@@ -1685,7 +1687,7 @@ SECOND_PASS:
         uint *const alignedInlineElementSlotsRef)
         uint *const alignedInlineElementSlotsRef)
     {
     {
         uint8 bucketsCount = ArrayType::AllocationBucketsCount;
         uint8 bucketsCount = ArrayType::AllocationBucketsCount;
-        
+
         EnsureCalculationOfAllocationBuckets<ArrayType>();
         EnsureCalculationOfAllocationBuckets<ArrayType>();
 
 
         if (inlineElementSlots >= 0 && inlineElementSlots <= ArrayType::allocationBuckets[bucketsCount - 1][AllocationBucketIndex])
         if (inlineElementSlots >= 0 && inlineElementSlots <= ArrayType::allocationBuckets[bucketsCount - 1][AllocationBucketIndex])
@@ -1716,7 +1718,7 @@ SECOND_PASS:
 
 
         return DetermineAllocationSize<ArrayType, InlinePropertySlots>(inlineElementSlots, allocationPlusSizeRef, alignedInlineElementSlotsRef);
         return DetermineAllocationSize<ArrayType, InlinePropertySlots>(inlineElementSlots, allocationPlusSizeRef, alignedInlineElementSlotsRef);
     }
     }
-    
+
 
 
     template<class T, uint InlinePropertySlots>
     template<class T, uint InlinePropertySlots>
     inline uint JavascriptArray::DetermineAvailableInlineElementSlots(
     inline uint JavascriptArray::DetermineAvailableInlineElementSlots(

+ 15 - 13
lib/Runtime/Library/JavascriptLibrary.cpp

@@ -78,7 +78,7 @@ namespace Js
         typesEnsuredToHaveOnlyWritableDataPropertiesInItAndPrototypeChain = RecyclerNew(recycler, JsUtil::List<Type *>, recycler);
         typesEnsuredToHaveOnlyWritableDataPropertiesInItAndPrototypeChain = RecyclerNew(recycler, JsUtil::List<Type *>, recycler);
 
 
         // Library is not zero-initialized. memset the memory occupied by builtinFunctions array to 0.
         // Library is not zero-initialized. memset the memory occupied by builtinFunctions array to 0.
-        memset(builtinFunctions, 0, sizeof(JavascriptFunction *) * BuiltinFunction::Count);
+        ClearArray(builtinFunctions, BuiltinFunction::Count);
 
 
         // Note: InitializePrototypes and InitializeTypes must be called first.
         // Note: InitializePrototypes and InitializeTypes must be called first.
         InitializePrototypes();
         InitializePrototypes();
@@ -1208,7 +1208,7 @@ namespace Js
 
 
         // Note: Any global function added/removed/changed here should also be updated in JavascriptLibrary::ProfilerRegisterBuiltinFunctions
         // Note: Any global function added/removed/changed here should also be updated in JavascriptLibrary::ProfilerRegisterBuiltinFunctions
         // so that the new functions show up in the profiler too.
         // so that the new functions show up in the profiler too.
-        JavascriptFunction ** builtinFuncs = this->GetBuiltinFunctions();
+        Field(JavascriptFunction*)* builtinFuncs = this->GetBuiltinFunctions();
 
 
         evalFunctionObject = AddFunctionToLibraryObject(globalObject, PropertyIds::eval, &GlobalObject::EntryInfo::Eval, 1);
         evalFunctionObject = AddFunctionToLibraryObject(globalObject, PropertyIds::eval, &GlobalObject::EntryInfo::Eval, 1);
         parseIntFunctionObject = AddFunctionToLibraryObject(globalObject, PropertyIds::parseInt, &GlobalObject::EntryInfo::ParseInt, 2);
         parseIntFunctionObject = AddFunctionToLibraryObject(globalObject, PropertyIds::parseInt, &GlobalObject::EntryInfo::ParseInt, 2);
@@ -1591,7 +1591,7 @@ namespace Js
         // so that the update is in sync with profiler
         // so that the update is in sync with profiler
         ScriptContext* scriptContext = arrayConstructor->GetScriptContext();
         ScriptContext* scriptContext = arrayConstructor->GetScriptContext();
         JavascriptLibrary* library = arrayConstructor->GetLibrary();
         JavascriptLibrary* library = arrayConstructor->GetLibrary();
-        JavascriptFunction ** builtinFuncs = library->GetBuiltinFunctions();
+        Field(JavascriptFunction*)* builtinFuncs = library->GetBuiltinFunctions();
 
 
         library->AddMember(arrayConstructor, PropertyIds::length, TaggedInt::ToVarUnchecked(1), PropertyNone);
         library->AddMember(arrayConstructor, PropertyIds::length, TaggedInt::ToVarUnchecked(1), PropertyNone);
         library->AddMember(arrayConstructor, PropertyIds::prototype, scriptContext->GetLibrary()->arrayPrototype, PropertyNone);
         library->AddMember(arrayConstructor, PropertyIds::prototype, scriptContext->GetLibrary()->arrayPrototype, PropertyNone);
@@ -1634,7 +1634,7 @@ namespace Js
         JavascriptLibrary* library = arrayPrototype->GetLibrary();
         JavascriptLibrary* library = arrayPrototype->GetLibrary();
         library->AddMember(arrayPrototype, PropertyIds::constructor, library->arrayConstructor);
         library->AddMember(arrayPrototype, PropertyIds::constructor, library->arrayConstructor);
 
 
-        JavascriptFunction ** builtinFuncs = library->GetBuiltinFunctions();
+        Field(JavascriptFunction*)* builtinFuncs = library->GetBuiltinFunctions();
 
 
         builtinFuncs[BuiltinFunction::JavascriptArray_Push]               = library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::push,            &JavascriptArray::EntryInfo::Push,              1);
         builtinFuncs[BuiltinFunction::JavascriptArray_Push]               = library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::push,            &JavascriptArray::EntryInfo::Push,              1);
         builtinFuncs[BuiltinFunction::JavascriptArray_Concat]             = library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::concat,          &JavascriptArray::EntryInfo::Concat,            1);
         builtinFuncs[BuiltinFunction::JavascriptArray_Concat]             = library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::concat,          &JavascriptArray::EntryInfo::Concat,            1);
@@ -2556,7 +2556,7 @@ namespace Js
         // so that the update is in sync with profiler
         // so that the update is in sync with profiler
         ScriptContext* scriptContext = functionPrototype->GetScriptContext();
         ScriptContext* scriptContext = functionPrototype->GetScriptContext();
         JavascriptLibrary* library = functionPrototype->GetLibrary();
         JavascriptLibrary* library = functionPrototype->GetLibrary();
-        JavascriptFunction ** builtinFuncs = library->GetBuiltinFunctions();
+        Field(JavascriptFunction*)* builtinFuncs = library->GetBuiltinFunctions();
 
 
         library->AddMember(functionPrototype, PropertyIds::constructor, library->functionConstructor);
         library->AddMember(functionPrototype, PropertyIds::constructor, library->functionConstructor);
         library->AddMember(functionPrototype, PropertyIds::length, TaggedInt::ToVarUnchecked(0), PropertyConfigurable);
         library->AddMember(functionPrototype, PropertyIds::length, TaggedInt::ToVarUnchecked(0), PropertyConfigurable);
@@ -2637,7 +2637,7 @@ namespace Js
         library->AddMember(mathObject, PropertyIds::SQRT1_2, JavascriptNumber::New(Math::SQRT1_2, scriptContext), PropertyNone);
         library->AddMember(mathObject, PropertyIds::SQRT1_2, JavascriptNumber::New(Math::SQRT1_2, scriptContext), PropertyNone);
         library->AddMember(mathObject, PropertyIds::SQRT2,   JavascriptNumber::New(Math::SQRT2,   scriptContext), PropertyNone);
         library->AddMember(mathObject, PropertyIds::SQRT2,   JavascriptNumber::New(Math::SQRT2,   scriptContext), PropertyNone);
 
 
-        JavascriptFunction ** builtinFuncs = library->GetBuiltinFunctions();
+        Field(JavascriptFunction*)* builtinFuncs = library->GetBuiltinFunctions();
 
 
         builtinFuncs[BuiltinFunction::Math_Abs]    = library->AddFunctionToLibraryObject(mathObject, PropertyIds::abs,    &Math::EntryInfo::Abs,    1);
         builtinFuncs[BuiltinFunction::Math_Abs]    = library->AddFunctionToLibraryObject(mathObject, PropertyIds::abs,    &Math::EntryInfo::Abs,    1);
         builtinFuncs[BuiltinFunction::Math_Acos]   = library->AddFunctionToLibraryObject(mathObject, PropertyIds::acos,   &Math::EntryInfo::Acos,   1);
         builtinFuncs[BuiltinFunction::Math_Acos]   = library->AddFunctionToLibraryObject(mathObject, PropertyIds::acos,   &Math::EntryInfo::Acos,   1);
@@ -3626,7 +3626,8 @@ namespace Js
 
 
 #if DBG
 #if DBG
     /*static*/
     /*static*/
-    void JavascriptLibrary::CheckRegisteredBuiltIns(JavascriptFunction** builtInFuncs, ScriptContext *scriptContext)
+    void JavascriptLibrary::CheckRegisteredBuiltIns(
+        Field(JavascriptFunction*)* builtInFuncs, ScriptContext *scriptContext)
     {
     {
         byte count = BuiltinFunction::Count;
         byte count = BuiltinFunction::Count;
         for (byte index = 0; index < count; index++)
         for (byte index = 0; index < count; index++)
@@ -4113,7 +4114,7 @@ namespace Js
         // so that the update is in sync with profiler
         // so that the update is in sync with profiler
         JavascriptFunction * func;
         JavascriptFunction * func;
         JavascriptLibrary* library = regexPrototype->GetLibrary();
         JavascriptLibrary* library = regexPrototype->GetLibrary();
-        JavascriptFunction ** builtinFuncs = library->GetBuiltinFunctions();
+        Field(JavascriptFunction*)* builtinFuncs = library->GetBuiltinFunctions();
 
 
         library->AddMember(regexPrototype, PropertyIds::constructor, library->regexConstructor);
         library->AddMember(regexPrototype, PropertyIds::constructor, library->regexConstructor);
         library->regexConstructorSlotIndex = 0;
         library->regexConstructorSlotIndex = 0;
@@ -4209,7 +4210,7 @@ namespace Js
         JavascriptLibrary* library = stringConstructor->GetLibrary();
         JavascriptLibrary* library = stringConstructor->GetLibrary();
         ScriptContext* scriptContext = stringConstructor->GetScriptContext();
         ScriptContext* scriptContext = stringConstructor->GetScriptContext();
 
 
-        JavascriptFunction ** builtinFuncs = library->GetBuiltinFunctions();
+        Field(JavascriptFunction*)* builtinFuncs = library->GetBuiltinFunctions();
         library->AddMember(stringConstructor, PropertyIds::length, TaggedInt::ToVarUnchecked(1), PropertyNone);
         library->AddMember(stringConstructor, PropertyIds::length, TaggedInt::ToVarUnchecked(1), PropertyNone);
         library->AddMember(stringConstructor, PropertyIds::prototype, library->stringPrototype, PropertyNone);
         library->AddMember(stringConstructor, PropertyIds::prototype, library->stringPrototype, PropertyNone);
 
 
@@ -4239,7 +4240,7 @@ namespace Js
         // so that the update is in sync with profiler
         // so that the update is in sync with profiler
         ScriptContext* scriptContext = stringPrototype->GetScriptContext();
         ScriptContext* scriptContext = stringPrototype->GetScriptContext();
         JavascriptLibrary* library = stringPrototype->GetLibrary();
         JavascriptLibrary* library = stringPrototype->GetLibrary();
-        JavascriptFunction ** builtinFuncs = library->GetBuiltinFunctions();
+        Field(JavascriptFunction*)* builtinFuncs = library->GetBuiltinFunctions();
         library->AddMember(stringPrototype, PropertyIds::constructor, library->stringConstructor);
         library->AddMember(stringPrototype, PropertyIds::constructor, library->stringConstructor);
 
 
         builtinFuncs[BuiltinFunction::JavascriptString_IndexOf]       = library->AddFunctionToLibraryObject(stringPrototype, PropertyIds::indexOf,            &JavascriptString::EntryInfo::IndexOf,              1);
         builtinFuncs[BuiltinFunction::JavascriptString_IndexOf]       = library->AddFunctionToLibraryObject(stringPrototype, PropertyIds::indexOf,            &JavascriptString::EntryInfo::IndexOf,              1);
@@ -4581,7 +4582,7 @@ namespace Js
         }
         }
 
 
         ConstructorCache* ctorCache = ((functionInfo->GetAttributes() & FunctionInfo::Attributes::SkipDefaultNewObject) != 0) ?
         ConstructorCache* ctorCache = ((functionInfo->GetAttributes() & FunctionInfo::Attributes::SkipDefaultNewObject) != 0) ?
-            this->builtInConstructorCache : &ConstructorCache::DefaultInstance;
+            static_cast<ConstructorCache*>(this->builtInConstructorCache) : &ConstructorCache::DefaultInstance;
 
 
         DynamicType* type = DynamicType::New(scriptContext, TypeIds_Function, prototype, functionInfo->GetOriginalEntryPoint(), typeHandler);
         DynamicType* type = DynamicType::New(scriptContext, TypeIds_Function, prototype, functionInfo->GetOriginalEntryPoint(), typeHandler);
 
 
@@ -6744,7 +6745,7 @@ namespace Js
             || constructor == library->GetFloat64ArrayConstructor();
             || constructor == library->GetFloat64ArrayConstructor();
     }
     }
 
 
-    JavascriptFunction ** JavascriptLibrary::GetBuiltinFunctions()
+    Field(JavascriptFunction*)* JavascriptLibrary::GetBuiltinFunctions()
     {
     {
         AssertMsg(this->builtinFunctions, "builtinFunctions table must've been initialized as part of library initialization!");
         AssertMsg(this->builtinFunctions, "builtinFunctions table must've been initialized as part of library initialization!");
         return this->builtinFunctions;
         return this->builtinFunctions;
@@ -6903,7 +6904,8 @@ namespace Js
         // The last void* is the linklist connecting to next block.
         // The last void* is the linklist connecting to next block.
         if (bindRefChunkCurrent == bindRefChunkEnd)
         if (bindRefChunkCurrent == bindRefChunkEnd)
         {
         {
-            void** tmpBindRefChunk = RecyclerNewArrayZ(recycler, void *, HeapConstants::ObjectGranularity / sizeof(void *));
+            Field(void*)* tmpBindRefChunk = RecyclerNewArrayZ(recycler,
+                Field(void*), HeapConstants::ObjectGranularity / sizeof(void *));
             // reserve the last void* as the linklist node.
             // reserve the last void* as the linklist node.
             bindRefChunkEnd = tmpBindRefChunk + (HeapConstants::ObjectGranularity / sizeof(void *) -1 );
             bindRefChunkEnd = tmpBindRefChunk + (HeapConstants::ObjectGranularity / sizeof(void *) -1 );
             if (bindRefChunkBegin == nullptr)
             if (bindRefChunkBegin == nullptr)

+ 238 - 238
lib/Runtime/Library/JavascriptLibrary.h

@@ -136,7 +136,7 @@ namespace Js
 
 
     public:
     public:
 #if ENABLE_COPYONACCESS_ARRAY
 #if ENABLE_COPYONACCESS_ARRAY
-        CacheForCopyOnAccessArraySegments *cacheForCopyOnAccessArraySegments;
+        Field(CacheForCopyOnAccessArraySegments *) cacheForCopyOnAccessArraySegments;
 #endif
 #endif
 
 
         static DWORD GetScriptContextOffset() { return offsetof(JavascriptLibrary, scriptContext); }
         static DWORD GetScriptContextOffset() { return offsetof(JavascriptLibrary, scriptContext); }
@@ -180,89 +180,89 @@ namespace Js
         static bool IsTypedArrayConstructor(Var constructor, ScriptContext* scriptContext);
         static bool IsTypedArrayConstructor(Var constructor, ScriptContext* scriptContext);
 
 
     private:
     private:
-        Recycler * recycler;
-        ExternalLibraryBase* externalLibraryList;
+        FieldNoBarrier(Recycler *) recycler;
+        Field(ExternalLibraryBase*) externalLibraryList;
 
 
-        UndeclaredBlockVariable* undeclBlockVarSentinel;
+        Field(UndeclaredBlockVariable*) undeclBlockVarSentinel;
 
 
-        DynamicType * generatorConstructorPrototypeObjectType;
-        DynamicType * constructorPrototypeObjectType;
-        DynamicType * heapArgumentsType;
-        DynamicType * activationObjectType;
-        DynamicType * arrayType;
-        DynamicType * nativeIntArrayType;
+        Field(DynamicType *) generatorConstructorPrototypeObjectType;
+        Field(DynamicType *) constructorPrototypeObjectType;
+        Field(DynamicType *) heapArgumentsType;
+        Field(DynamicType *) activationObjectType;
+        Field(DynamicType *) arrayType;
+        Field(DynamicType *) nativeIntArrayType;
 #if ENABLE_COPYONACCESS_ARRAY
 #if ENABLE_COPYONACCESS_ARRAY
-        DynamicType * copyOnAccessNativeIntArrayType;
+        Field(DynamicType *) copyOnAccessNativeIntArrayType;
 #endif
 #endif
-        DynamicType * nativeFloatArrayType;
-        DynamicType * arrayBufferType;
-        DynamicType * sharedArrayBufferType;
-        DynamicType * dataViewType;
-        DynamicType * typedArrayType;
-        DynamicType * int8ArrayType;
-        DynamicType * uint8ArrayType;
-        DynamicType * uint8ClampedArrayType;
-        DynamicType * int16ArrayType;
-        DynamicType * uint16ArrayType;
-        DynamicType * int32ArrayType;
-        DynamicType * uint32ArrayType;
-        DynamicType * float32ArrayType;
-        DynamicType * float64ArrayType;
-        DynamicType * int64ArrayType;
-        DynamicType * uint64ArrayType;
-        DynamicType * boolArrayType;
-        DynamicType * charArrayType;
-        StaticType * booleanTypeStatic;
-        DynamicType * booleanTypeDynamic;
-        DynamicType * dateType;
-        StaticType * variantDateType;
-        DynamicType * symbolTypeDynamic;
-        StaticType * symbolTypeStatic;
-        DynamicType * iteratorResultType;
-        DynamicType * arrayIteratorType;
-        DynamicType * mapIteratorType;
-        DynamicType * setIteratorType;
-        DynamicType * stringIteratorType;
-        DynamicType * promiseType;
-        DynamicType * listIteratorType;
-
-        JavascriptFunction* builtinFunctions[BuiltinFunction::Count];
-
-        INT_PTR vtableAddresses[VTableValue::Count];
-        ConstructorCache *constructorCacheDefaultInstance;
-        __declspec(align(16)) const BYTE *absDoubleCst;
-        double const *uintConvertConst;
+        Field(DynamicType *) nativeFloatArrayType;
+        Field(DynamicType *) arrayBufferType;
+        Field(DynamicType *) sharedArrayBufferType;
+        Field(DynamicType *) dataViewType;
+        Field(DynamicType *) typedArrayType;
+        Field(DynamicType *) int8ArrayType;
+        Field(DynamicType *) uint8ArrayType;
+        Field(DynamicType *) uint8ClampedArrayType;
+        Field(DynamicType *) int16ArrayType;
+        Field(DynamicType *) uint16ArrayType;
+        Field(DynamicType *) int32ArrayType;
+        Field(DynamicType *) uint32ArrayType;
+        Field(DynamicType *) float32ArrayType;
+        Field(DynamicType *) float64ArrayType;
+        Field(DynamicType *) int64ArrayType;
+        Field(DynamicType *) uint64ArrayType;
+        Field(DynamicType *) boolArrayType;
+        Field(DynamicType *) charArrayType;
+        Field(StaticType *) booleanTypeStatic;
+        Field(DynamicType *) booleanTypeDynamic;
+        Field(DynamicType *) dateType;
+        Field(StaticType *) variantDateType;
+        Field(DynamicType *) symbolTypeDynamic;
+        Field(StaticType *) symbolTypeStatic;
+        Field(DynamicType *) iteratorResultType;
+        Field(DynamicType *) arrayIteratorType;
+        Field(DynamicType *) mapIteratorType;
+        Field(DynamicType *) setIteratorType;
+        Field(DynamicType *) stringIteratorType;
+        Field(DynamicType *) promiseType;
+        Field(DynamicType *) listIteratorType;
+
+        Field(JavascriptFunction* ) builtinFunctions[BuiltinFunction::Count];
+
+        Field(INT_PTR ) vtableAddresses[VTableValue::Count];
+        Field(ConstructorCache *) constructorCacheDefaultInstance;
+        __declspec(align(16)) Field(const BYTE *) absDoubleCst;
+        Field(double const *) uintConvertConst;
 
 
         // Function Types
         // Function Types
-        DynamicTypeHandler * anonymousFunctionTypeHandler;
-        DynamicTypeHandler * anonymousFunctionWithPrototypeTypeHandler;
-        DynamicTypeHandler * functionTypeHandler;
-        DynamicTypeHandler * functionWithPrototypeTypeHandler;
-        DynamicType * externalFunctionWithDeferredPrototypeType;
-        DynamicType * wrappedFunctionWithDeferredPrototypeType;
-        DynamicType * stdCallFunctionWithDeferredPrototypeType;
-        DynamicType * idMappedFunctionWithPrototypeType;
-        DynamicType * externalConstructorFunctionWithDeferredPrototypeType;
-        DynamicType * defaultExternalConstructorFunctionWithDeferredPrototypeType;
-        DynamicType * boundFunctionType;
-        DynamicType * regexConstructorType;
-        DynamicType * crossSiteDeferredPrototypeFunctionType;
-        DynamicType * crossSiteIdMappedFunctionWithPrototypeType;
-        DynamicType * crossSiteExternalConstructFunctionWithPrototypeType;
-
-        StaticType  * enumeratorType;
-        DynamicType * errorType;
-        DynamicType * evalErrorType;
-        DynamicType * rangeErrorType;
-        DynamicType * referenceErrorType;
-        DynamicType * syntaxErrorType;
-        DynamicType * typeErrorType;
-        DynamicType * uriErrorType;
+        Field(DynamicTypeHandler *) anonymousFunctionTypeHandler;
+        Field(DynamicTypeHandler *) anonymousFunctionWithPrototypeTypeHandler;
+        Field(DynamicTypeHandler *) functionTypeHandler;
+        Field(DynamicTypeHandler *) functionWithPrototypeTypeHandler;
+        Field(DynamicType *) externalFunctionWithDeferredPrototypeType;
+        Field(DynamicType *) wrappedFunctionWithDeferredPrototypeType;
+        Field(DynamicType *) stdCallFunctionWithDeferredPrototypeType;
+        Field(DynamicType *) idMappedFunctionWithPrototypeType;
+        Field(DynamicType *) externalConstructorFunctionWithDeferredPrototypeType;
+        Field(DynamicType *) defaultExternalConstructorFunctionWithDeferredPrototypeType;
+        Field(DynamicType *) boundFunctionType;
+        Field(DynamicType *) regexConstructorType;
+        Field(DynamicType *) crossSiteDeferredPrototypeFunctionType;
+        Field(DynamicType *) crossSiteIdMappedFunctionWithPrototypeType;
+        Field(DynamicType *) crossSiteExternalConstructFunctionWithPrototypeType;
+
+        Field(StaticType  *) enumeratorType;
+        Field(DynamicType *) errorType;
+        Field(DynamicType *) evalErrorType;
+        Field(DynamicType *) rangeErrorType;
+        Field(DynamicType *) referenceErrorType;
+        Field(DynamicType *) syntaxErrorType;
+        Field(DynamicType *) typeErrorType;
+        Field(DynamicType *) uriErrorType;
         DynamicType * webAssemblyCompileErrorType;
         DynamicType * webAssemblyCompileErrorType;
         DynamicType * webAssemblyRuntimeErrorType;
         DynamicType * webAssemblyRuntimeErrorType;
-        StaticType  * numberTypeStatic;
-        StaticType  * int64NumberTypeStatic;
-        StaticType  * uint64NumberTypeStatic;
+        Field(StaticType  *) numberTypeStatic;
+        Field(StaticType  *) int64NumberTypeStatic;
+        Field(StaticType  *) uint64NumberTypeStatic;
 
 
         DynamicType * webAssemblyModuleType;
         DynamicType * webAssemblyModuleType;
         DynamicType * webAssemblyInstanceType;
         DynamicType * webAssemblyInstanceType;
@@ -270,155 +270,155 @@ namespace Js
         DynamicType * webAssemblyTableType;
         DynamicType * webAssemblyTableType;
 
 
         // SIMD_JS
         // SIMD_JS
-        DynamicType * simdBool8x16TypeDynamic;
-        DynamicType * simdBool16x8TypeDynamic;
-        DynamicType * simdBool32x4TypeDynamic;
-        DynamicType * simdInt8x16TypeDynamic;
-        DynamicType * simdInt16x8TypeDynamic;
-        DynamicType * simdInt32x4TypeDynamic;
-        DynamicType * simdUint8x16TypeDynamic;
-        DynamicType * simdUint16x8TypeDynamic;
-        DynamicType * simdUint32x4TypeDynamic;
-        DynamicType * simdFloat32x4TypeDynamic;
-
-        StaticType * simdFloat32x4TypeStatic;
-        StaticType * simdInt32x4TypeStatic;
-        StaticType * simdInt8x16TypeStatic;
-        StaticType * simdFloat64x2TypeStatic;
-        StaticType * simdInt16x8TypeStatic;
-        StaticType * simdBool32x4TypeStatic;
-        StaticType * simdBool16x8TypeStatic;
-        StaticType * simdBool8x16TypeStatic;
-        StaticType * simdUint32x4TypeStatic;
-        StaticType * simdUint16x8TypeStatic;
-        StaticType * simdUint8x16TypeStatic;
-
-        DynamicType * numberTypeDynamic;
-        DynamicType * objectTypes[PreInitializedObjectTypeCount];
-        DynamicType * objectHeaderInlinedTypes[PreInitializedObjectTypeCount];
-        DynamicType * regexPrototypeType;
-        DynamicType * regexType;
-        DynamicType * regexResultType;
-        StaticType  * stringTypeStatic;
-        DynamicType * stringTypeDynamic;
-        DynamicType * mapType;
-        DynamicType * setType;
-        DynamicType * weakMapType;
-        DynamicType * weakSetType;
-        DynamicType * proxyType;
-        StaticType  * withType;
-        DynamicType * SpreadArgumentType;
-        DynamicType * moduleNamespaceType;
-        PropertyDescriptor defaultPropertyDescriptor;
-
-        JavascriptString* nullString;
-        JavascriptString* emptyString;
-        JavascriptString* quotesString;
-        JavascriptString* whackString;
-        JavascriptString* objectDisplayString;
-        JavascriptString* stringTypeDisplayString;
-        JavascriptString* errorDisplayString;
-        JavascriptString* functionPrefixString;
-        JavascriptString* generatorFunctionPrefixString;
-        JavascriptString* asyncFunctionPrefixString;
-        JavascriptString* functionDisplayString;
-        JavascriptString* xDomainFunctionDisplayString;
-        JavascriptString* undefinedDisplayString;
-        JavascriptString* nanDisplayString;
-        JavascriptString* nullDisplayString;
-        JavascriptString* unknownDisplayString;
-        JavascriptString* commaDisplayString;
-        JavascriptString* commaSpaceDisplayString;
-        JavascriptString* trueDisplayString;
-        JavascriptString* falseDisplayString;
-        JavascriptString* lengthDisplayString;
-        JavascriptString* invalidDateString;
-        JavascriptString* objectTypeDisplayString;
-        JavascriptString* functionTypeDisplayString;
-        JavascriptString* booleanTypeDisplayString;
-        JavascriptString* numberTypeDisplayString;
-        JavascriptString* moduleTypeDisplayString;
+        Field(DynamicType *) simdBool8x16TypeDynamic;
+        Field(DynamicType *) simdBool16x8TypeDynamic;
+        Field(DynamicType *) simdBool32x4TypeDynamic;
+        Field(DynamicType *) simdInt8x16TypeDynamic;
+        Field(DynamicType *) simdInt16x8TypeDynamic;
+        Field(DynamicType *) simdInt32x4TypeDynamic;
+        Field(DynamicType *) simdUint8x16TypeDynamic;
+        Field(DynamicType *) simdUint16x8TypeDynamic;
+        Field(DynamicType *) simdUint32x4TypeDynamic;
+        Field(DynamicType *) simdFloat32x4TypeDynamic;
+
+        Field(StaticType *) simdFloat32x4TypeStatic;
+        Field(StaticType *) simdInt32x4TypeStatic;
+        Field(StaticType *) simdInt8x16TypeStatic;
+        Field(StaticType *) simdFloat64x2TypeStatic;
+        Field(StaticType *) simdInt16x8TypeStatic;
+        Field(StaticType *) simdBool32x4TypeStatic;
+        Field(StaticType *) simdBool16x8TypeStatic;
+        Field(StaticType *) simdBool8x16TypeStatic;
+        Field(StaticType *) simdUint32x4TypeStatic;
+        Field(StaticType *) simdUint16x8TypeStatic;
+        Field(StaticType *) simdUint8x16TypeStatic;
+
+        Field(DynamicType *) numberTypeDynamic;
+        Field(DynamicType * ) objectTypes[PreInitializedObjectTypeCount];
+        Field(DynamicType * ) objectHeaderInlinedTypes[PreInitializedObjectTypeCount];
+        Field(DynamicType *) regexPrototypeType;
+        Field(DynamicType *) regexType;
+        Field(DynamicType *) regexResultType;
+        Field(StaticType  *) stringTypeStatic;
+        Field(DynamicType *) stringTypeDynamic;
+        Field(DynamicType *) mapType;
+        Field(DynamicType *) setType;
+        Field(DynamicType *) weakMapType;
+        Field(DynamicType *) weakSetType;
+        Field(DynamicType *) proxyType;
+        Field(StaticType  *) withType;
+        Field(DynamicType *) SpreadArgumentType;
+        Field(DynamicType *) moduleNamespaceType;
+        Field(PropertyDescriptor) defaultPropertyDescriptor;
+
+        Field(JavascriptString*) nullString;
+        Field(JavascriptString*) emptyString;
+        Field(JavascriptString*) quotesString;
+        Field(JavascriptString*) whackString;
+        Field(JavascriptString*) objectDisplayString;
+        Field(JavascriptString*) stringTypeDisplayString;
+        Field(JavascriptString*) errorDisplayString;
+        Field(JavascriptString*) functionPrefixString;
+        Field(JavascriptString*) generatorFunctionPrefixString;
+        Field(JavascriptString*) asyncFunctionPrefixString;
+        Field(JavascriptString*) functionDisplayString;
+        Field(JavascriptString*) xDomainFunctionDisplayString;
+        Field(JavascriptString*) undefinedDisplayString;
+        Field(JavascriptString*) nanDisplayString;
+        Field(JavascriptString*) nullDisplayString;
+        Field(JavascriptString*) unknownDisplayString;
+        Field(JavascriptString*) commaDisplayString;
+        Field(JavascriptString*) commaSpaceDisplayString;
+        Field(JavascriptString*) trueDisplayString;
+        Field(JavascriptString*) falseDisplayString;
+        Field(JavascriptString*) lengthDisplayString;
+        Field(JavascriptString*) invalidDateString;
+        Field(JavascriptString*) objectTypeDisplayString;
+        Field(JavascriptString*) functionTypeDisplayString;
+        Field(JavascriptString*) booleanTypeDisplayString;
+        Field(JavascriptString*) numberTypeDisplayString;
+        Field(JavascriptString*) moduleTypeDisplayString;
 
 
         // SIMD_JS
         // SIMD_JS
-        JavascriptString* simdFloat32x4DisplayString;
-        JavascriptString* simdFloat64x2DisplayString;
-        JavascriptString* simdInt32x4DisplayString;
-        JavascriptString* simdInt16x8DisplayString;
-        JavascriptString* simdInt8x16DisplayString;
-        JavascriptString* simdBool32x4DisplayString;
-        JavascriptString* simdBool16x8DisplayString;
-        JavascriptString* simdBool8x16DisplayString;
-        JavascriptString* simdUint32x4DisplayString;
-        JavascriptString* simdUint16x8DisplayString;
-        JavascriptString* simdUint8x16DisplayString;
+        Field(JavascriptString*) simdFloat32x4DisplayString;
+        Field(JavascriptString*) simdFloat64x2DisplayString;
+        Field(JavascriptString*) simdInt32x4DisplayString;
+        Field(JavascriptString*) simdInt16x8DisplayString;
+        Field(JavascriptString*) simdInt8x16DisplayString;
+        Field(JavascriptString*) simdBool32x4DisplayString;
+        Field(JavascriptString*) simdBool16x8DisplayString;
+        Field(JavascriptString*) simdBool8x16DisplayString;
+        Field(JavascriptString*) simdUint32x4DisplayString;
+        Field(JavascriptString*) simdUint16x8DisplayString;
+        Field(JavascriptString*) simdUint8x16DisplayString;
 
 
 
 
 
 
-        JavascriptString* symbolTypeDisplayString;
-        JavascriptString* debuggerDeadZoneBlockVariableString;
+        Field(JavascriptString*) symbolTypeDisplayString;
+        Field(JavascriptString*) debuggerDeadZoneBlockVariableString;
 
 
-        DynamicObject* missingPropertyHolder;
+        Field(DynamicObject*) missingPropertyHolder;
 
 
-        StaticType* throwErrorObjectType;
+        Field(StaticType*) throwErrorObjectType;
 
 
-        PropertyStringCacheMap* propertyStringMap;
+        Field(PropertyStringCacheMap*) propertyStringMap;
 
 
-        ConstructorCache* builtInConstructorCache;
+        Field(ConstructorCache*) builtInConstructorCache;
 
 
 #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
 #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
-        JavascriptFunction* debugObjectFaultInjectionCookieGetterFunction;
-        JavascriptFunction* debugObjectFaultInjectionCookieSetterFunction;
+        Field(JavascriptFunction*) debugObjectFaultInjectionCookieGetterFunction;
+        Field(JavascriptFunction*) debugObjectFaultInjectionCookieSetterFunction;
 #endif
 #endif
 
 
-        JavascriptFunction* evalFunctionObject;
-        JavascriptFunction* arrayPrototypeValuesFunction;
-        JavascriptFunction* parseIntFunctionObject;
-        JavascriptFunction* parseFloatFunctionObject;
-        JavascriptFunction* arrayPrototypeToStringFunction;
-        JavascriptFunction* arrayPrototypeToLocaleStringFunction;
-        JavascriptFunction* identityFunction;
-        JavascriptFunction* throwerFunction;
-        JavascriptFunction* promiseResolveFunction;
-        JavascriptFunction* generatorNextFunction;
-        JavascriptFunction* generatorThrowFunction;
-
-        JavascriptFunction* objectValueOfFunction;
-        JavascriptFunction* objectToStringFunction;
+        Field(JavascriptFunction*) evalFunctionObject;
+        Field(JavascriptFunction*) arrayPrototypeValuesFunction;
+        Field(JavascriptFunction*) parseIntFunctionObject;
+        Field(JavascriptFunction*) parseFloatFunctionObject;
+        Field(JavascriptFunction*) arrayPrototypeToStringFunction;
+        Field(JavascriptFunction*) arrayPrototypeToLocaleStringFunction;
+        Field(JavascriptFunction*) identityFunction;
+        Field(JavascriptFunction*) throwerFunction;
+        Field(JavascriptFunction*) promiseResolveFunction;
+        Field(JavascriptFunction*) generatorNextFunction;
+        Field(JavascriptFunction*) generatorThrowFunction;
+
+        Field(JavascriptFunction*) objectValueOfFunction;
+        Field(JavascriptFunction*) objectToStringFunction;
 
 
 #ifdef ENABLE_WASM
 #ifdef ENABLE_WASM
         DynamicObject* webAssemblyObject;
         DynamicObject* webAssemblyObject;
 #endif
 #endif
 
 
         // SIMD_JS
         // SIMD_JS
-        JavascriptFunction* simdFloat32x4ToStringFunction;
-        JavascriptFunction* simdFloat64x2ToStringFunction;
-        JavascriptFunction* simdInt32x4ToStringFunction;
-        JavascriptFunction* simdInt16x8ToStringFunction;
-        JavascriptFunction* simdInt8x16ToStringFunction;
-        JavascriptFunction* simdBool32x4ToStringFunction;
-        JavascriptFunction* simdBool16x8ToStringFunction;
-        JavascriptFunction* simdBool8x16ToStringFunction;
-        JavascriptFunction* simdUint32x4ToStringFunction;
-        JavascriptFunction* simdUint16x8ToStringFunction;
-        JavascriptFunction* simdUint8x16ToStringFunction;
-
-
-
-        JavascriptSymbol* symbolMatch;
-        JavascriptSymbol* symbolReplace;
-        JavascriptSymbol* symbolSearch;
-        JavascriptSymbol* symbolSplit;
-
-        UnifiedRegex::RegexPattern * emptyRegexPattern;
-        JavascriptFunction* regexExecFunction;
-        JavascriptFunction* regexFlagsGetterFunction;
-        JavascriptFunction* regexGlobalGetterFunction;
-        JavascriptFunction* regexStickyGetterFunction;
-        JavascriptFunction* regexUnicodeGetterFunction;
-
-        RuntimeFunction* sharedArrayBufferConstructor;
-        DynamicObject* sharedArrayBufferPrototype;
-        DynamicObject* atomicsObject;
+        Field(JavascriptFunction*) simdFloat32x4ToStringFunction;
+        Field(JavascriptFunction*) simdFloat64x2ToStringFunction;
+        Field(JavascriptFunction*) simdInt32x4ToStringFunction;
+        Field(JavascriptFunction*) simdInt16x8ToStringFunction;
+        Field(JavascriptFunction*) simdInt8x16ToStringFunction;
+        Field(JavascriptFunction*) simdBool32x4ToStringFunction;
+        Field(JavascriptFunction*) simdBool16x8ToStringFunction;
+        Field(JavascriptFunction*) simdBool8x16ToStringFunction;
+        Field(JavascriptFunction*) simdUint32x4ToStringFunction;
+        Field(JavascriptFunction*) simdUint16x8ToStringFunction;
+        Field(JavascriptFunction*) simdUint8x16ToStringFunction;
+
+
+
+        Field(JavascriptSymbol*) symbolMatch;
+        Field(JavascriptSymbol*) symbolReplace;
+        Field(JavascriptSymbol*) symbolSearch;
+        Field(JavascriptSymbol*) symbolSplit;
+
+        Field(UnifiedRegex::RegexPattern *) emptyRegexPattern;
+        Field(JavascriptFunction*) regexExecFunction;
+        Field(JavascriptFunction*) regexFlagsGetterFunction;
+        Field(JavascriptFunction*) regexGlobalGetterFunction;
+        Field(JavascriptFunction*) regexStickyGetterFunction;
+        Field(JavascriptFunction*) regexUnicodeGetterFunction;
+
+        Field(RuntimeFunction*) sharedArrayBufferConstructor;
+        Field(DynamicObject*) sharedArrayBufferPrototype;
+        Field(DynamicObject*) atomicsObject;
 
 
         DynamicObject* webAssemblyCompileErrorPrototype;
         DynamicObject* webAssemblyCompileErrorPrototype;
         RuntimeFunction* webAssemblyCompileErrorConstructor;
         RuntimeFunction* webAssemblyCompileErrorConstructor;
@@ -434,37 +434,37 @@ namespace Js
         DynamicObject* webAssemblyTablePrototype;
         DynamicObject* webAssemblyTablePrototype;
         RuntimeFunction* webAssemblyTableConstructor;
         RuntimeFunction* webAssemblyTableConstructor;
 
 
-        int regexConstructorSlotIndex;
-        int regexExecSlotIndex;
-        int regexFlagsGetterSlotIndex;
-        int regexGlobalGetterSlotIndex;
-        int regexStickyGetterSlotIndex;
-        int regexUnicodeGetterSlotIndex;
+        Field(int) regexConstructorSlotIndex;
+        Field(int) regexExecSlotIndex;
+        Field(int) regexFlagsGetterSlotIndex;
+        Field(int) regexGlobalGetterSlotIndex;
+        Field(int) regexStickyGetterSlotIndex;
+        Field(int) regexUnicodeGetterSlotIndex;
 
 
-        mutable CharStringCache charStringCache;
+        mutable Field(CharStringCache) charStringCache;
 
 
-        PromiseContinuationCallback nativeHostPromiseContinuationFunction;
-        void *nativeHostPromiseContinuationFunctionState;
+        FieldNoBarrier(PromiseContinuationCallback) nativeHostPromiseContinuationFunction;
+        Field(void *) nativeHostPromiseContinuationFunctionState;
 
 
         typedef SList<Js::FunctionProxy*, Recycler> FunctionReferenceList;
         typedef SList<Js::FunctionProxy*, Recycler> FunctionReferenceList;
 
 
-        void * bindRefChunkBegin;
-        void ** bindRefChunkCurrent;
-        void ** bindRefChunkEnd;
-        TypePath* rootPath;         // this should be in library instead of ScriptContext::Cache
-        void* scriptContextCache;   // forward declaration for point to ScriptContext::Cache such that we don't need to hard pin it.
-        FunctionReferenceList* dynamicFunctionReference;
-        uint dynamicFunctionReferenceDepth;
-        FinalizableObject* jsrtContextObject;
+        Field(void *) bindRefChunkBegin;
+        Field(Field(void*)*) bindRefChunkCurrent;
+        Field(Field(void*)*) bindRefChunkEnd;
+        Field(TypePath*) rootPath;         // this should be in library instead of ScriptContext::Cache
+        Field(void*) scriptContextCache;   // forward declaration for point to ScriptContext::Cache such that we don't need to hard pin it.
+        Field(FunctionReferenceList*) dynamicFunctionReference;
+        Field(uint) dynamicFunctionReferenceDepth;
+        Field(FinalizableObject*) jsrtContextObject;
 
 
         typedef JsUtil::BaseHashSet<RecyclerWeakReference<RecyclableObject>*, Recycler, PowerOf2SizePolicy, RecyclerWeakReference<RecyclableObject>*, StringTemplateCallsiteObjectComparer> StringTemplateCallsiteObjectList;
         typedef JsUtil::BaseHashSet<RecyclerWeakReference<RecyclableObject>*, Recycler, PowerOf2SizePolicy, RecyclerWeakReference<RecyclableObject>*, StringTemplateCallsiteObjectComparer> StringTemplateCallsiteObjectList;
 
 
         // Used to store a list of template callsite objects.
         // Used to store a list of template callsite objects.
         // We use the raw strings in the callsite object (or a string template parse node) to identify unique callsite objects in the list.
         // We use the raw strings in the callsite object (or a string template parse node) to identify unique callsite objects in the list.
         // See abstract operation GetTemplateObject in ES6 Spec (RC1) 12.2.8.3
         // See abstract operation GetTemplateObject in ES6 Spec (RC1) 12.2.8.3
-        StringTemplateCallsiteObjectList* stringTemplateCallsiteObjectList;
+        Field(StringTemplateCallsiteObjectList*) stringTemplateCallsiteObjectList;
 
 
-        ModuleRecordList* moduleRecordList;
+        Field(ModuleRecordList*) moduleRecordList;
 
 
         // This list contains types ensured to have only writable data properties in it and all objects in its prototype chain
         // This list contains types ensured to have only writable data properties in it and all objects in its prototype chain
         // (i.e., no readonly properties or accessors). Only prototype objects' types are stored in the list. When something
         // (i.e., no readonly properties or accessors). Only prototype objects' types are stored in the list. When something
@@ -480,13 +480,13 @@ namespace Js
         //
         //
         // This list is only used to invalidate the status of types. The type itself contains a boolean indicating whether it
         // This list is only used to invalidate the status of types. The type itself contains a boolean indicating whether it
         // and prototypes contain only writable data properties, which is reset upon invalidating the status.
         // and prototypes contain only writable data properties, which is reset upon invalidating the status.
-        JsUtil::List<Type *> *typesEnsuredToHaveOnlyWritableDataPropertiesInItAndPrototypeChain;
+        Field(JsUtil::List<Type *> *) typesEnsuredToHaveOnlyWritableDataPropertiesInItAndPrototypeChain;
 
 
-        uint64 randSeed0, randSeed1;
-        bool isPRNGSeeded;
-        bool inProfileMode;
-        bool inDispatchProfileMode;
-        bool arrayObjectHasUserDefinedSpecies;
+        Field(uint64) randSeed0, randSeed1;
+        Field(bool) isPRNGSeeded;
+        Field(bool) inProfileMode;
+        Field(bool) inDispatchProfileMode;
+        Field(bool) arrayObjectHasUserDefinedSpecies;
 
 
         JavascriptFunction * AddFunctionToLibraryObjectWithPrototype(DynamicObject * object, PropertyId propertyId, FunctionInfo * functionInfo, int length, DynamicObject * prototype = nullptr, DynamicType * functionType = nullptr);
         JavascriptFunction * AddFunctionToLibraryObjectWithPrototype(DynamicObject * object, PropertyId propertyId, FunctionInfo * functionInfo, int length, DynamicObject * prototype = nullptr, DynamicType * functionType = nullptr);
         JavascriptFunction * AddFunctionToLibraryObject(DynamicObject* object, PropertyId propertyId, FunctionInfo * functionInfo, int length, PropertyAttributes attributes = PropertyBuiltInMethodDefaults);
         JavascriptFunction * AddFunctionToLibraryObject(DynamicObject* object, PropertyId propertyId, FunctionInfo * functionInfo, int length, PropertyAttributes attributes = PropertyBuiltInMethodDefaults);
@@ -767,7 +767,7 @@ namespace Js
         DynamicType * GetSIMDUint16x8TypeDynamic()  const { return simdUint16x8TypeDynamic;  }
         DynamicType * GetSIMDUint16x8TypeDynamic()  const { return simdUint16x8TypeDynamic;  }
         DynamicType * GetSIMDUint32x4TypeDynamic()  const { return simdUint32x4TypeDynamic;  }
         DynamicType * GetSIMDUint32x4TypeDynamic()  const { return simdUint32x4TypeDynamic;  }
         DynamicType * GetSIMDFloat32x4TypeDynamic() const { return simdFloat32x4TypeDynamic; }
         DynamicType * GetSIMDFloat32x4TypeDynamic() const { return simdFloat32x4TypeDynamic; }
-        
+
         StaticType* GetSIMDFloat32x4TypeStatic() const { return simdFloat32x4TypeStatic; }
         StaticType* GetSIMDFloat32x4TypeStatic() const { return simdFloat32x4TypeStatic; }
         StaticType* GetSIMDFloat64x2TypeStatic() const { return simdFloat64x2TypeStatic; }
         StaticType* GetSIMDFloat64x2TypeStatic() const { return simdFloat64x2TypeStatic; }
         StaticType* GetSIMDInt32x4TypeStatic()   const { return simdInt32x4TypeStatic; }
         StaticType* GetSIMDInt32x4TypeStatic()   const { return simdInt32x4TypeStatic; }
@@ -1104,12 +1104,12 @@ namespace Js
         static const char16* GetStringTemplateCallsiteObjectKey(Var callsite);
         static const char16* GetStringTemplateCallsiteObjectKey(Var callsite);
 #endif
 #endif
 
 
-        JavascriptFunction** GetBuiltinFunctions();
+        Field(JavascriptFunction*)* GetBuiltinFunctions();
         INT_PTR* GetVTableAddresses();
         INT_PTR* GetVTableAddresses();
         static BuiltinFunction GetBuiltinFunctionForPropId(PropertyId id);
         static BuiltinFunction GetBuiltinFunctionForPropId(PropertyId id);
         static BuiltinFunction GetBuiltInForFuncInfo(intptr_t funcInfoAddr, ThreadContextInfo *context);
         static BuiltinFunction GetBuiltInForFuncInfo(intptr_t funcInfoAddr, ThreadContextInfo *context);
 #if DBG
 #if DBG
-        static void CheckRegisteredBuiltIns(JavascriptFunction** builtInFuncs, ScriptContext *scriptContext);
+        static void CheckRegisteredBuiltIns(Field(JavascriptFunction*)* builtInFuncs, ScriptContext *scriptContext);
 #endif
 #endif
         static BOOL CanFloatPreferenceFunc(BuiltinFunction index);
         static BOOL CanFloatPreferenceFunc(BuiltinFunction index);
         static BOOL IsFltFunc(BuiltinFunction index);
         static BOOL IsFltFunc(BuiltinFunction index);
@@ -1164,8 +1164,8 @@ namespace Js
         // Declare fretest/debug properties here since otherwise it can cause
         // Declare fretest/debug properties here since otherwise it can cause
         // a mismatch between fre mshtml and fretest jscript9 causing undefined behavior
         // a mismatch between fre mshtml and fretest jscript9 causing undefined behavior
 
 
-        DynamicType * debugDisposableObjectType;
-        DynamicType * debugFuncExecutorInDisposeObjectType;
+        Field(DynamicType *) debugDisposableObjectType;
+        Field(DynamicType *) debugFuncExecutorInDisposeObjectType;
 #endif
 #endif
 
 
         void InitializePrototypes();
         void InitializePrototypes();
@@ -1296,7 +1296,7 @@ namespace Js
 #endif
 #endif
 
 
         JavascriptFunction* EnsureArrayPrototypeValuesFunction();
         JavascriptFunction* EnsureArrayPrototypeValuesFunction();
-        
+
 
 
     public:
     public:
         virtual void Finalize(bool isShutdown) override
         virtual void Finalize(bool isShutdown) override
@@ -1313,7 +1313,7 @@ namespace Js
 #endif
 #endif
     private:
     private:
         typedef JsUtil::BaseHashSet<Js::PropertyRecord const *, Recycler, PowerOf2SizePolicy> ReferencedPropertyRecordHashSet;
         typedef JsUtil::BaseHashSet<Js::PropertyRecord const *, Recycler, PowerOf2SizePolicy> ReferencedPropertyRecordHashSet;
-        ReferencedPropertyRecordHashSet* referencedPropertyRecords;
+        Field(ReferencedPropertyRecordHashSet*) referencedPropertyRecords;
 
 
         ReferencedPropertyRecordHashSet * EnsureReferencedPropertyRecordList()
         ReferencedPropertyRecordHashSet * EnsureReferencedPropertyRecordList()
         {
         {

+ 4 - 3
lib/Runtime/Library/RegexHelper.cpp

@@ -474,7 +474,8 @@ namespace Js
                     {
                     {
                         for (int k = 0; k < trigramInfo->resultCount; k++)
                         for (int k = 0; k < trigramInfo->resultCount; k++)
                         {
                         {
-                            arrayResult->DirectSetItemAt(k, trigramInfo->cachedResult[k]);
+                            arrayResult->DirectSetItemAt(k,
+                                static_cast<Js::JavascriptString*>(trigramInfo->cachedResult[k]));
                         }
                         }
                     }
                     }
                     else
                     else
@@ -565,7 +566,7 @@ namespace Js
             {
             {
                 // Overall match already captured in index 0 by above, so just grab the groups
                 // Overall match already captured in index 0 by above, so just grab the groups
                 Var nonMatchValue = NonMatchValue(scriptContext, false);
                 Var nonMatchValue = NonMatchValue(scriptContext, false);
-                Var *elements = ((SparseArraySegment<Var>*)arrayResult->GetHead())->elements;
+                Field(Var) *elements = ((SparseArraySegment<Var>*)arrayResult->GetHead())->elements;
                 for (uint groupId = 1; groupId < (uint)numGroups; groupId++)
                 for (uint groupId = 1; groupId < (uint)numGroups; groupId++)
                 {
                 {
                     Assert(groupId < arrayResult->GetHead()->left + arrayResult->GetHead()->length);
                     Assert(groupId < arrayResult->GetHead()->left + arrayResult->GetHead()->length);
@@ -619,7 +620,7 @@ namespace Js
         Assert(numGroups >= 0);
         Assert(numGroups >= 0);
         JavascriptArray* result = CreateExecResult(stackAllocationPointer, scriptContext, numGroups, input, match);
         JavascriptArray* result = CreateExecResult(stackAllocationPointer, scriptContext, numGroups, input, match);
         Var nonMatchValue = NonMatchValue(scriptContext, false);
         Var nonMatchValue = NonMatchValue(scriptContext, false);
-        Var *elements = ((SparseArraySegment<Var>*)result->GetHead())->elements;
+        Field(Var) *elements = ((SparseArraySegment<Var>*)result->GetHead())->elements;
         for (uint groupId = 0; groupId < (uint)numGroups; groupId++)
         for (uint groupId = 0; groupId < (uint)numGroups; groupId++)
         {
         {
             Assert(groupId < result->GetHead()->left + result->GetHead()->length);
             Assert(groupId < result->GetHead()->left + result->GetHead()->length);

+ 2 - 2
lib/Runtime/Library/SparseArraySegment.h

@@ -48,7 +48,7 @@ namespace Js
         SparseArraySegment(uint32 left, uint32 length, uint32 size) :
         SparseArraySegment(uint32 left, uint32 length, uint32 size) :
             SparseArraySegmentBase(left, length, size) {}
             SparseArraySegmentBase(left, length, size) {}
 
 
-        T elements[]; // actual elements will follow this determined by size
+        Field(T) elements[]; // actual elements will follow this determined by size
 
 
         void FillSegmentBuffer(uint start, uint size);
         void FillSegmentBuffer(uint start, uint size);
         T GetElement(uint32 index);
         T GetElement(uint32 index);
@@ -83,7 +83,7 @@ namespace Js
         template<bool isLeaf>
         template<bool isLeaf>
         static SparseArraySegment<T> *AllocateLiteralHeadSegmentImpl(Recycler *const recycler, const uint32 length);
         static SparseArraySegment<T> *AllocateLiteralHeadSegmentImpl(Recycler *const recycler, const uint32 length);
 
 
-        static void ClearElements(__out_ecount(len) T* elements, uint32 len);
+        static void ClearElements(__out_ecount(len) Field(T)* elements, uint32 len);
         static SparseArraySegment<T>* CopySegment(Recycler *recycler, SparseArraySegment<T>* dst, uint32 dstIndex, SparseArraySegment<T>* src, uint32 srcIndex, uint32 inputLen);
         static SparseArraySegment<T>* CopySegment(Recycler *recycler, SparseArraySegment<T>* dst, uint32 dstIndex, SparseArraySegment<T>* src, uint32 srcIndex, uint32 inputLen);
 
 
         static T GetMissingItem();
         static T GetMissingItem();

+ 5 - 5
lib/Runtime/Library/SparseArraySegment.inl

@@ -332,7 +332,7 @@ namespace Js
         AssertMsg(index >= left && index < left + length, "Index is out of the segment range");
         AssertMsg(index >= left && index < left + length, "Index is out of the segment range");
         if (index + 1 < left + length)
         if (index + 1 < left + length)
         {
         {
-            memmove(elements + index - left, elements + index + 1 - left, sizeof(T) * (length - (index - left) - 1));
+            MoveArray(elements + index - left, elements + index + 1 - left, length - (index - left) - 1);
         }
         }
         Assert(length);
         Assert(length);
         length--;
         length--;
@@ -353,7 +353,7 @@ namespace Js
         dst->length = newLen;
         dst->length = newLen;
         Assert(dst->length <= dst->size);
         Assert(dst->length <= dst->size);
         AssertMsg(srcIndex >= src->left,"src->left > srcIndex resulting in negative indexing of src->elements");
         AssertMsg(srcIndex >= src->left,"src->left > srcIndex resulting in negative indexing of src->elements");
-        js_memcpy_s(dst->elements + dstIndex - dst->left, sizeof(T) * inputLen, src->elements + srcIndex - src->left, sizeof(T) * inputLen);
+        CopyArray(dst->elements + dstIndex - dst->left, inputLen, src->elements + srcIndex - src->left, inputLen);
         return dst;
         return dst;
     }
     }
 
 
@@ -432,7 +432,7 @@ namespace Js
         SparseArraySegment<T> *newSeg = Allocate<isLeaf>(recycler, left, length, newSize);
         SparseArraySegment<T> *newSeg = Allocate<isLeaf>(recycler, left, length, newSize);
         newSeg->next = this->next;
         newSeg->next = this->next;
         // (sizeof(T) * newSize) will throw OOM in Allocate if it overflows.
         // (sizeof(T) * newSize) will throw OOM in Allocate if it overflows.
-        js_memcpy_s(newSeg->elements, sizeof(T) * newSize, this->elements, sizeof(T) * length);
+        CopyArray(newSeg->elements, newSize, this->elements, length);
 
 
         return newSeg;
         return newSeg;
     }
     }
@@ -484,13 +484,13 @@ namespace Js
 
 
         SparseArraySegment<T> *newSeg = Allocate<isLeaf>(recycler, left - n, length + n, size + n);
         SparseArraySegment<T> *newSeg = Allocate<isLeaf>(recycler, left - n, length + n, size + n);
         newSeg->next = this->next;
         newSeg->next = this->next;
-        js_memcpy_s(&newSeg->elements[n], sizeof(T) * length, this->elements, sizeof(T) * length);
+        CopyArray(newSeg->elements + n, length, this->elements, length);
 
 
         return newSeg;
         return newSeg;
     }
     }
 
 
     template<typename T>
     template<typename T>
-    void SparseArraySegment<T>::ClearElements(__out_ecount(len) T* elements, uint32 len)
+    void SparseArraySegment<T>::ClearElements(__out_ecount(len) Field(T)* elements, uint32 len)
     {
     {
         T fill = SparseArraySegment<T>::GetMissingItem();
         T fill = SparseArraySegment<T>::GetMissingItem();
         for (uint i = 0; i < len; i++)
         for (uint i = 0; i < len; i++)

+ 1 - 1
lib/Runtime/SerializableFunctionFields.h

@@ -9,7 +9,7 @@
 
 
 // Default declaration for FunctionBody.h
 // Default declaration for FunctionBody.h
 #ifndef DECLARE_SERIALIZABLE_FIELD
 #ifndef DECLARE_SERIALIZABLE_FIELD
-#define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) type name
+#define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) Field(type) name
 #endif
 #endif
 
 
 #ifndef DECLARE_SERIALIZABLE_ACCESSOR_FIELD
 #ifndef DECLARE_SERIALIZABLE_ACCESSOR_FIELD