Title: [161230] trunk/Source/_javascript_Core
Revision
161230
Author
mhahnenb...@apple.com
Date
2014-01-02 14:57:14 -0800 (Thu, 02 Jan 2014)

Log Message

Storing new CopiedSpace memory into a JSObject should fire a write barrier
https://bugs.webkit.org/show_bug.cgi?id=126025

Reviewed by Filip Pizlo.

Technically this is creating a pointer between a (potentially) old generation object and a young
generation chunk of memory, thus there needs to be a barrier.

* _javascript_Core.xcodeproj/project.pbxproj:
* dfg/DFGOperations.cpp:
* heap/CopyWriteBarrier.h: Added. This class functions similarly to the WriteBarrier class. It
acts as a proxy for pointers to CopiedSpace. Assignments to the field cause a write barrier to
fire for the object that is the owner of the CopiedSpace memory. This is to ensure during nursery
collections that objects with new backing stores are visited, even if they are old generation objects.
(JSC::CopyWriteBarrier::CopyWriteBarrier):
(JSC::CopyWriteBarrier::operator!):
(JSC::CopyWriteBarrier::operator UnspecifiedBoolType*):
(JSC::CopyWriteBarrier::get):
(JSC::CopyWriteBarrier::operator*):
(JSC::CopyWriteBarrier::operator->):
(JSC::CopyWriteBarrier::set):
(JSC::CopyWriteBarrier::setWithoutWriteBarrier):
(JSC::CopyWriteBarrier::clear):
* heap/Heap.h:
* runtime/JSArray.cpp:
(JSC::JSArray::unshiftCountSlowCase):
(JSC::JSArray::shiftCountWithArrayStorage):
(JSC::JSArray::unshiftCountWithArrayStorage):
* runtime/JSCell.h:
(JSC::JSCell::unvalidatedStructure):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView<Adaptor>::slowDownAndWasteMemory):
* runtime/JSObject.cpp:
(JSC::JSObject::copyButterfly):
(JSC::JSObject::getOwnPropertySlotByIndex):
(JSC::JSObject::putByIndex):
(JSC::JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists):
(JSC::JSObject::createInitialIndexedStorage):
(JSC::JSObject::createArrayStorage):
(JSC::JSObject::deletePropertyByIndex):
(JSC::JSObject::getOwnPropertyNames):
(JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
(JSC::JSObject::countElements):
(JSC::JSObject::increaseVectorLength):
(JSC::JSObject::ensureLengthSlow):
* runtime/JSObject.h:
(JSC::JSObject::butterfly):
(JSC::JSObject::setStructureAndButterfly):
(JSC::JSObject::setButterflyWithoutChangingStructure):
(JSC::JSObject::JSObject):
(JSC::JSObject::putDirectInternal):
(JSC::JSObject::putDirectWithoutTransition):
* runtime/MapData.cpp:
(JSC::MapData::ensureSpaceForAppend):
* runtime/Structure.cpp:
(JSC::Structure::materializePropertyMap):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (161229 => 161230)


--- trunk/Source/_javascript_Core/ChangeLog	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-01-02 22:57:14 UTC (rev 161230)
@@ -1,3 +1,62 @@
+2014-01-02  Mark Hahnenberg  <mhahnenb...@apple.com>
+
+        Storing new CopiedSpace memory into a JSObject should fire a write barrier
+        https://bugs.webkit.org/show_bug.cgi?id=126025
+
+        Reviewed by Filip Pizlo.
+
+        Technically this is creating a pointer between a (potentially) old generation object and a young 
+        generation chunk of memory, thus there needs to be a barrier.
+
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * dfg/DFGOperations.cpp:
+        * heap/CopyWriteBarrier.h: Added. This class functions similarly to the WriteBarrier class. It 
+        acts as a proxy for pointers to CopiedSpace. Assignments to the field cause a write barrier to 
+        fire for the object that is the owner of the CopiedSpace memory. This is to ensure during nursery 
+        collections that objects with new backing stores are visited, even if they are old generation objects. 
+        (JSC::CopyWriteBarrier::CopyWriteBarrier):
+        (JSC::CopyWriteBarrier::operator!):
+        (JSC::CopyWriteBarrier::operator UnspecifiedBoolType*):
+        (JSC::CopyWriteBarrier::get):
+        (JSC::CopyWriteBarrier::operator*):
+        (JSC::CopyWriteBarrier::operator->):
+        (JSC::CopyWriteBarrier::set):
+        (JSC::CopyWriteBarrier::setWithoutWriteBarrier):
+        (JSC::CopyWriteBarrier::clear):
+        * heap/Heap.h:
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::unshiftCountSlowCase):
+        (JSC::JSArray::shiftCountWithArrayStorage):
+        (JSC::JSArray::unshiftCountWithArrayStorage):
+        * runtime/JSCell.h:
+        (JSC::JSCell::unvalidatedStructure):
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView<Adaptor>::slowDownAndWasteMemory):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::copyButterfly):
+        (JSC::JSObject::getOwnPropertySlotByIndex):
+        (JSC::JSObject::putByIndex):
+        (JSC::JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists):
+        (JSC::JSObject::createInitialIndexedStorage):
+        (JSC::JSObject::createArrayStorage):
+        (JSC::JSObject::deletePropertyByIndex):
+        (JSC::JSObject::getOwnPropertyNames):
+        (JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
+        (JSC::JSObject::countElements):
+        (JSC::JSObject::increaseVectorLength):
+        (JSC::JSObject::ensureLengthSlow):
+        * runtime/JSObject.h:
+        (JSC::JSObject::butterfly):
+        (JSC::JSObject::setStructureAndButterfly):
+        (JSC::JSObject::setButterflyWithoutChangingStructure):
+        (JSC::JSObject::JSObject):
+        (JSC::JSObject::putDirectInternal):
+        (JSC::JSObject::putDirectWithoutTransition):
+        * runtime/MapData.cpp:
+        (JSC::MapData::ensureSpaceForAppend):
+        * runtime/Structure.cpp:
+        (JSC::Structure::materializePropertyMap):
+
 2013-12-23  Oliver Hunt  <oli...@apple.com>
 
         Refactor PutPropertySlot to be aware of custom properties

Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (161229 => 161230)


--- trunk/Source/_javascript_Core/GNUmakefile.list.am	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am	2014-01-02 22:57:14 UTC (rev 161230)
@@ -502,6 +502,7 @@
 	Source/_javascript_Core/heap/CopyVisitorInlines.h \
 	Source/_javascript_Core/heap/CopyVisitor.cpp \
 	Source/_javascript_Core/heap/CopyWorkList.h \
+	Source/_javascript_Core/heap/CopyWriteBarrier.h \
 	Source/_javascript_Core/heap/ConservativeRoots.cpp \
 	Source/_javascript_Core/heap/ConservativeRoots.h \
     Source/_javascript_Core/heap/DeferGC.cpp \

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (161229 => 161230)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2014-01-02 22:57:14 UTC (rev 161230)
@@ -984,6 +984,7 @@
     <ClInclude Include="..\heap\CopyVisitor.h" />
     <ClInclude Include="..\heap\CopyVisitorInlines.h" />
     <ClInclude Include="..\heap\CopyWorkList.h" />
+    <ClInclude Include="..\heap\CopyWriteBarrier.h" />
     <ClInclude Include="..\heap\DeferGC.h" />
     <ClInclude Include="..\heap\DelayedReleaseScope.h" />
     <ClInclude Include="..\heap\GCAssertions.h" />

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters (161229 => 161230)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2014-01-02 22:57:14 UTC (rev 161230)
@@ -1628,6 +1628,9 @@
     <ClInclude Include="..\heap\CopyWorkList.h">
       <Filter>heap</Filter>
     </ClInclude>
+    <ClInclude Include="..\heap\CopyWriteBarrier.h">
+      <Filter>heap</Filter>
+    </ClInclude>
     <ClInclude Include="..\heap\DeferGC.h">
       <Filter>heap</Filter>
     </ClInclude>

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (161229 => 161230)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2014-01-02 22:57:14 UTC (rev 161230)
@@ -720,6 +720,7 @@
 		2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = C211B574176A224D000E2A23 /* APICallbackFunction.h */; };
 		2A4EC90B1860D6C20094F782 /* WriteBarrierBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A4EC9091860D6C20094F782 /* WriteBarrierBuffer.cpp */; };
 		2A4EC90C1860D6C20094F782 /* WriteBarrierBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4EC90A1860D6C20094F782 /* WriteBarrierBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		2A68295B1875F80500B6C3E2 /* CopyWriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A68295A1875F80500B6C3E2 /* CopyWriteBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2A6F462617E959CE00C45C98 /* HeapOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A6F462517E959CE00C45C98 /* HeapOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */; };
 		2AAD964A18569417001F93BE /* RecursiveAllocationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AAD964918569417001F93BE /* RecursiveAllocationScope.h */; };
@@ -2027,6 +2028,7 @@
 		2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DelayedReleaseScope.h; sourceTree = "<group>"; };
 		2A4EC9091860D6C20094F782 /* WriteBarrierBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierBuffer.cpp; sourceTree = "<group>"; };
 		2A4EC90A1860D6C20094F782 /* WriteBarrierBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierBuffer.h; sourceTree = "<group>"; };
+		2A68295A1875F80500B6C3E2 /* CopyWriteBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyWriteBarrier.h; sourceTree = "<group>"; };
 		2A6F462517E959CE00C45C98 /* HeapOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapOperation.h; sourceTree = "<group>"; };
 		2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeferGC.cpp; sourceTree = "<group>"; };
 		2AAD964918569417001F93BE /* RecursiveAllocationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecursiveAllocationScope.h; sourceTree = "<group>"; };
@@ -3212,6 +3214,7 @@
 				0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */,
 				2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */,
 				2AAD964918569417001F93BE /* RecursiveAllocationScope.h */,
+				2A68295A1875F80500B6C3E2 /* CopyWriteBarrier.h */,
 			);
 			path = heap;
 			sourceTree = "<group>";
@@ -4373,6 +4376,7 @@
 				86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
 				86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
 				65C0285D1717966800351E35 /* ARMv7DOpcode.h in Headers */,
+				2A68295B1875F80500B6C3E2 /* CopyWriteBarrier.h in Headers */,
 				2A4EC90C1860D6C20094F782 /* WriteBarrierBuffer.h in Headers */,
 				A532439218569709002ED692 /* CodeGeneratorInspector.py in Headers */,
 				A532439318569709002ED692 /* CodeGeneratorInspectorStrings.py in Headers */,

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (161229 => 161230)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2014-01-02 22:57:14 UTC (rev 161230)
@@ -851,7 +851,7 @@
 
     ASSERT(!object->structure()->outOfLineCapacity());
     Butterfly* result = object->growOutOfLineStorage(vm, 0, initialOutOfLineCapacity);
-    object->setButterflyWithoutChangingStructure(result);
+    object->setButterflyWithoutChangingStructure(vm, result);
     return reinterpret_cast<char*>(result);
 }
 
@@ -861,7 +861,7 @@
     NativeCallFrameTracer tracer(&vm, exec);
 
     Butterfly* result = object->growOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize);
-    object->setButterflyWithoutChangingStructure(result);
+    object->setButterflyWithoutChangingStructure(vm, result);
     return reinterpret_cast<char*>(result);
 }
 

Added: trunk/Source/_javascript_Core/heap/CopyWriteBarrier.h (0 => 161230)


--- trunk/Source/_javascript_Core/heap/CopyWriteBarrier.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/heap/CopyWriteBarrier.h	2014-01-02 22:57:14 UTC (rev 161230)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CopyWriteBarrier_h
+#define CopyWriteBarrier_h
+
+#include "Heap.h"
+
+namespace JSC {
+
+template <typename T>
+class CopyWriteBarrier {
+public:
+    CopyWriteBarrier()
+        : m_value(0)
+    {
+    }
+    
+    CopyWriteBarrier(VM& vm, const JSCell* owner, T& value)
+    {
+        this->set(vm, owner, &value);
+    }
+    
+    CopyWriteBarrier(VM& vm, const JSCell* owner, T* value)
+    {
+        this->set(vm, owner, value);
+    }
+    
+    bool operator!() const { return !m_value; }
+    
+    typedef T* (CopyWriteBarrier::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const { return m_value ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+    
+    T* get() const
+    {
+        return m_value;
+    }
+    
+    T* operator*() const
+    {
+        return get();
+    }
+    
+    T* operator->() const
+    {
+        return get();
+    }
+    
+    void set(VM&, const JSCell* owner, T* value)
+    {
+        this->m_value = value;
+        Heap::writeBarrier(owner);
+    }
+    
+    void setWithoutWriteBarrier(T* value)
+    {
+        this->m_value = value;
+    }
+    
+    void clear() { m_value = 0; }
+
+private:
+    T* m_value;
+};
+
+} // namespace JSC
+
+#endif // CopyWriteBarrier_h

Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (161229 => 161230)


--- trunk/Source/_javascript_Core/runtime/JSArray.cpp	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp	2014-01-02 22:57:14 UTC (rev 161230)
@@ -321,9 +321,8 @@
 
     newButterfly->arrayStorage()->setVectorLength(newVectorLength);
     newButterfly->arrayStorage()->m_indexBias = newIndexBias;
+    setButterflyWithoutChangingStructure(vm, newButterfly);
 
-    m_butterfly = newButterfly;
-
     return true;
 }
 
@@ -720,7 +719,7 @@
         // Adjust the Butterfly and the index bias. We only need to do this here because we're changing
         // the start of the Butterfly, which needs to point at the first indexed property in the used
         // portion of the vector.
-        m_butterfly = m_butterfly->shift(structure(), count);
+        m_butterfly.setWithoutWriteBarrier(m_butterfly->shift(structure(), count));
         storage = m_butterfly->arrayStorage();
         storage->m_indexBias += count;
 
@@ -857,10 +856,11 @@
     unsigned vectorLength = storage->vectorLength();
 
     if (moveFront && storage->m_indexBias >= count) {
-        m_butterfly = storage->butterfly()->unshift(structure(), count);
-        storage = m_butterfly->arrayStorage();
+        Butterfly* newButterfly = storage->butterfly()->unshift(structure(), count);
+        storage = newButterfly->arrayStorage();
         storage->m_indexBias -= count;
         storage->setVectorLength(vectorLength + count);
+        setButterflyWithoutChangingStructure(exec->vm(), newButterfly);
     } else if (!moveFront && vectorLength - length >= count)
         storage = storage->butterfly()->arrayStorage();
     else if (unshiftCountSlowCase(exec->vm(), moveFront, count))

Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (161229 => 161230)


--- trunk/Source/_javascript_Core/runtime/JSCell.h	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h	2014-01-02 22:57:14 UTC (rev 161230)
@@ -146,7 +146,7 @@
     }
         
 #if ENABLE(GC_VALIDATION)
-    Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); }
+    Structure* unvalidatedStructure() const { return m_structure.unvalidatedGet(); }
 #endif
         
     static const TypedArrayType TypedArrayStorageType = NotTypedArray;

Modified: trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h (161229 => 161230)


--- trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h	2014-01-02 22:57:14 UTC (rev 161230)
@@ -506,15 +506,16 @@
     size_t size = thisObject->byteSize();
     
     if (thisObject->m_mode == FastTypedArray
-        && !thisObject->m_butterfly && size >= sizeof(IndexingHeader)) {
+        && !thisObject->butterfly() && size >= sizeof(IndexingHeader)) {
         ASSERT(thisObject->m_vector);
         // Reuse already allocated memory if at all possible.
-        thisObject->m_butterfly =
-            static_cast<IndexingHeader*>(thisObject->m_vector)->butterfly();
+        thisObject->m_butterfly.setWithoutWriteBarrier(
+            static_cast<IndexingHeader*>(thisObject->m_vector)->butterfly());
     } else {
-        thisObject->m_butterfly = Butterfly::createOrGrowArrayRight(
-            thisObject->m_butterfly, *heap->vm(), thisObject, thisObject->structure(),
-            thisObject->structure()->outOfLineCapacity(), false, 0, 0);
+        VM& vm = *heap->vm();
+        thisObject->m_butterfly.set(vm, thisObject, Butterfly::createOrGrowArrayRight(
+            thisObject->butterfly(), vm, thisObject, thisObject->structure(),
+            thisObject->structure()->outOfLineCapacity(), false, 0, 0));
     }
 
     RefPtr<ArrayBuffer> buffer;

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (161229 => 161230)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2014-01-02 22:57:14 UTC (rev 161230)
@@ -159,7 +159,7 @@
             memcpy(currentTarget, currentSource, count * sizeof(EncodedJSValue));
         }
         
-        m_butterfly = newButterfly;
+        m_butterfly.setWithoutWriteBarrier(newButterfly);
         visitor.didCopy(butterfly->base(preCapacity, propertyCapacity), capacityInBytes);
     } 
 }
@@ -283,7 +283,7 @@
         
     case ALL_INT32_INDEXING_TYPES:
     case ALL_CONTIGUOUS_INDEXING_TYPES: {
-        Butterfly* butterfly = thisObject->m_butterfly;
+        Butterfly* butterfly = thisObject->butterfly();
         if (i >= butterfly->vectorLength())
             return false;
         
@@ -297,7 +297,7 @@
     }
         
     case ALL_DOUBLE_INDEXING_TYPES: {
-        Butterfly* butterfly = thisObject->m_butterfly;
+        Butterfly* butterfly = thisObject->butterfly();
         if (i >= butterfly->vectorLength())
             return false;
         
@@ -437,7 +437,7 @@
     }
         
     case ALL_CONTIGUOUS_INDEXING_TYPES: {
-        Butterfly* butterfly = thisObject->m_butterfly;
+        Butterfly* butterfly = thisObject->butterfly();
         if (propertyName >= butterfly->vectorLength())
             break;
         butterfly->contiguous()[propertyName].set(exec->vm(), thisObject, value);
@@ -460,7 +460,7 @@
             putByIndex(cell, exec, propertyName, value, shouldThrow);
             return;
         }
-        Butterfly* butterfly = thisObject->m_butterfly;
+        Butterfly* butterfly = thisObject->butterfly();
         if (propertyName >= butterfly->vectorLength())
             break;
         butterfly->contiguousDouble()[propertyName] = valueAsDouble;
@@ -549,11 +549,10 @@
     DeferGC deferGC(vm.heap);
     Butterfly* newButterfly = storage->butterfly()->resizeArray(vm, this, structure(), 0, ArrayStorage::sizeFor(0));
     RELEASE_ASSERT(newButterfly);
-    
-    m_butterfly = newButterfly;
     newButterfly->arrayStorage()->m_indexBias = 0;
     newButterfly->arrayStorage()->setVectorLength(0);
     newButterfly->arrayStorage()->m_sparseMap.set(vm, this, map);
+    setButterflyWithoutChangingStructure(vm, newButterfly);
     
     return newButterfly->arrayStorage();
 }
@@ -601,7 +600,7 @@
     ASSERT(!indexingShouldBeSparse());
     unsigned vectorLength = std::max(length, BASE_VECTOR_LEN);
     Butterfly* newButterfly = Butterfly::createOrGrowArrayRight(
-        m_butterfly, vm, this, structure(), structure()->outOfLineCapacity(), false, 0,
+        m_butterfly.get(), vm, this, structure(), structure()->outOfLineCapacity(), false, 0,
         elementSize * vectorLength);
     newButterfly->setPublicLength(length);
     newButterfly->setVectorLength(vectorLength);
@@ -652,7 +651,7 @@
     IndexingType oldType = structure()->indexingType();
     ASSERT_UNUSED(oldType, !hasIndexedProperties(oldType));
     Butterfly* newButterfly = Butterfly::createOrGrowArrayRight(
-        m_butterfly, vm, this, structure(), structure()->outOfLineCapacity(), false, 0,
+        m_butterfly.get(), vm, this, structure(), structure()->outOfLineCapacity(), false, 0,
         ArrayStorage::sizeFor(vectorLength));
     RELEASE_ASSERT(newButterfly);
 
@@ -1296,7 +1295,7 @@
         
     case ALL_INT32_INDEXING_TYPES:
     case ALL_CONTIGUOUS_INDEXING_TYPES: {
-        Butterfly* butterfly = thisObject->m_butterfly;
+        Butterfly* butterfly = thisObject->butterfly();
         if (i >= butterfly->vectorLength())
             return true;
         butterfly->contiguous()[i].clear();
@@ -1304,7 +1303,7 @@
     }
         
     case ALL_DOUBLE_INDEXING_TYPES: {
-        Butterfly* butterfly = thisObject->m_butterfly;
+        Butterfly* butterfly = thisObject->butterfly();
         if (i >= butterfly->vectorLength())
             return true;
         butterfly->contiguousDouble()[i] = QNaN;
@@ -1480,7 +1479,7 @@
         
     case ALL_INT32_INDEXING_TYPES:
     case ALL_CONTIGUOUS_INDEXING_TYPES: {
-        Butterfly* butterfly = object->m_butterfly;
+        Butterfly* butterfly = object->butterfly();
         unsigned usedLength = butterfly->publicLength();
         for (unsigned i = 0; i < usedLength; ++i) {
             if (!butterfly->contiguous()[i])
@@ -1491,7 +1490,7 @@
     }
         
     case ALL_DOUBLE_INDEXING_TYPES: {
-        Butterfly* butterfly = object->m_butterfly;
+        Butterfly* butterfly = object->butterfly();
         unsigned usedLength = butterfly->publicLength();
         for (unsigned i = 0; i < usedLength; ++i) {
             double value = butterfly->contiguousDouble()[i];
@@ -1875,7 +1874,7 @@
     
     if (i >= MAX_ARRAY_INDEX - 1
         || (i >= MIN_SPARSE_ARRAY_INDEX
-            && !isDenseEnoughForVector(i, countElements<indexingShape>(m_butterfly)))
+            && !isDenseEnoughForVector(i, countElements<indexingShape>(butterfly())))
         || indexIsSufficientlyBeyondLengthForSparseMap(i, m_butterfly->vectorLength())) {
         ASSERT(i <= MAX_ARRAY_INDEX);
         ensureArrayStorageSlow(vm);
@@ -2312,13 +2311,13 @@
         return 0;
         
     case ALL_INT32_INDEXING_TYPES:
-        return countElements<Int32Shape>(m_butterfly);
+        return countElements<Int32Shape>(butterfly());
         
     case ALL_DOUBLE_INDEXING_TYPES:
-        return countElements<DoubleShape>(m_butterfly);
+        return countElements<DoubleShape>(butterfly());
         
     case ALL_CONTIGUOUS_INDEXING_TYPES:
-        return countElements<ContiguousShape>(m_butterfly);
+        return countElements<ContiguousShape>(butterfly());
         
     default:
         CRASH();
@@ -2352,8 +2351,8 @@
             ArrayStorage::sizeFor(vectorLength), ArrayStorage::sizeFor(newVectorLength));
         if (!newButterfly)
             return false;
-        m_butterfly = newButterfly;
         newButterfly->arrayStorage()->setVectorLength(newVectorLength);
+        setButterflyWithoutChangingStructure(vm, newButterfly);
         return true;
     }
     
@@ -2366,10 +2365,9 @@
         newIndexBias, true, ArrayStorage::sizeFor(newVectorLength));
     if (!newButterfly)
         return false;
-    
-    m_butterfly = newButterfly;
     newButterfly->arrayStorage()->setVectorLength(newVectorLength);
     newButterfly->arrayStorage()->m_indexBias = newIndexBias;
+    setButterflyWithoutChangingStructure(vm, newButterfly);
     return true;
 }
 
@@ -2384,15 +2382,17 @@
         MAX_STORAGE_VECTOR_LENGTH);
     unsigned oldVectorLength = m_butterfly->vectorLength();
     DeferGC deferGC(vm.heap);
-    m_butterfly = m_butterfly->growArrayRight(
+    m_butterfly.set(vm, this, m_butterfly->growArrayRight(
         vm, this, structure(), structure()->outOfLineCapacity(), true,
         oldVectorLength * sizeof(EncodedJSValue),
-        newVectorLength * sizeof(EncodedJSValue));
+        newVectorLength * sizeof(EncodedJSValue)));
+
+    m_butterfly->setVectorLength(newVectorLength);
+
     if (hasDouble(structure()->indexingType())) {
         for (unsigned i = oldVectorLength; i < newVectorLength; ++i)
             m_butterfly->contiguousDouble().data()[i] = QNaN;
     }
-    m_butterfly->setVectorLength(newVectorLength);
 }
 
 Butterfly* JSObject::growOutOfLineStorage(VM& vm, size_t oldSize, size_t newSize)

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (161229 => 161230)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2014-01-02 22:57:14 UTC (rev 161230)
@@ -27,10 +27,13 @@
 #include "ArrayConventions.h"
 #include "ArrayStorage.h"
 #include "Butterfly.h"
+#include "CallFrame.h"
 #include "ClassInfo.h"
 #include "CommonIdentifiers.h"
-#include "CallFrame.h"
+#include "CopyWriteBarrier.h"
 #include "DeferGC.h"
+#include "Heap.h"
+#include "IndexingHeaderInlines.h"
 #include "JSCell.h"
 #include "PropertySlot.h"
 #include "PropertyStorage.h"
@@ -539,8 +542,8 @@
         return inlineStorageUnsafe();
     }
         
-    const Butterfly* butterfly() const { return m_butterfly; }
-    Butterfly* butterfly() { return m_butterfly; }
+    const Butterfly* butterfly() const { return m_butterfly.get(); }
+    Butterfly* butterfly() { return m_butterfly.get(); }
         
     ConstPropertyStorage outOfLineStorage() const { return m_butterfly->propertyStorage(); }
     PropertyStorage outOfLineStorage() { return m_butterfly->propertyStorage(); }
@@ -605,7 +608,7 @@
     void reifyStaticFunctionsForDelete(ExecState* exec);
 
     JS_EXPORT_PRIVATE Butterfly* growOutOfLineStorage(VM&, size_t oldSize, size_t newSize);
-    void setButterflyWithoutChangingStructure(Butterfly*); // You probably don't want to call this.
+    void setButterflyWithoutChangingStructure(VM&, Butterfly*);
         
     void setStructure(VM&, Structure*);
     void setStructureAndButterfly(VM&, Structure*, Butterfly*);
@@ -975,7 +978,7 @@
     ContiguousJSValues ensureContiguousSlow(VM&, DoubleToContiguousMode);
     
 protected:
-    Butterfly* m_butterfly;
+    CopyWriteBarrier<Butterfly> m_butterfly;
 };
 
 // JSNonFinalObject is a type of JSObject that has some internal storage,
@@ -1135,7 +1138,9 @@
 
 inline void JSObject::setStructureAndButterfly(VM& vm, Structure* structure, Butterfly* butterfly)
 {
-    m_butterfly = butterfly;
+    ASSERT(structure);
+    ASSERT(!butterfly == (!structure->outOfLineCapacity() && !structure->hasIndexingHeader(this)));
+    m_butterfly.set(vm, this, butterfly);
     setStructure(vm, structure);
 }
 
@@ -1146,9 +1151,9 @@
     JSCell::setStructure(vm, structure);
 }
 
-inline void JSObject::setButterflyWithoutChangingStructure(Butterfly* butterfly)
+inline void JSObject::setButterflyWithoutChangingStructure(VM& vm, Butterfly* butterfly)
 {
-    m_butterfly = butterfly;
+    m_butterfly.set(vm, this, butterfly);
 }
 
 inline CallType getCallData(JSValue value, CallData& callData)
@@ -1178,7 +1183,7 @@
 
 inline JSObject::JSObject(VM& vm, Structure* structure, Butterfly* butterfly)
     : JSCell(vm, structure)
-    , m_butterfly(butterfly)
+    , m_butterfly(vm, this, butterfly)
 {
     vm.heap.ascribeOwner(this, butterfly);
 }
@@ -1302,7 +1307,7 @@
             return false;
 
         DeferGC deferGC(vm.heap);
-        Butterfly* newButterfly = m_butterfly;
+        Butterfly* newButterfly = butterfly();
         if (structure()->putWillGrowOutOfLineStorage())
             newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
         offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes, specificFunction);
@@ -1323,9 +1328,11 @@
     size_t currentCapacity = structure()->outOfLineCapacity();
     if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) {
         DeferGC deferGC(vm.heap);
-        Butterfly* newButterfly = m_butterfly;
-        if (currentCapacity != structure->outOfLineCapacity())
+        Butterfly* newButterfly = butterfly();
+        if (currentCapacity != structure->outOfLineCapacity()) {
+            ASSERT(structure != this->structure());
             newButterfly = growOutOfLineStorage(vm, currentCapacity, structure->outOfLineCapacity());
+        }
 
         validateOffset(offset);
         ASSERT(structure->isValidOffset(offset));
@@ -1436,7 +1443,7 @@
 {
     DeferGC deferGC(vm.heap);
     ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
-    Butterfly* newButterfly = m_butterfly;
+    Butterfly* newButterfly = m_butterfly.get();
     if (structure()->putWillGrowOutOfLineStorage())
         newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
     PropertyOffset offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes, getCallableObject(value));

Modified: trunk/Source/_javascript_Core/runtime/MapData.cpp (161229 => 161230)


--- trunk/Source/_javascript_Core/runtime/MapData.cpp	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/runtime/MapData.cpp	2014-01-02 22:57:14 UTC (rev 161230)
@@ -198,16 +198,17 @@
 
     size_t requiredSize = std::max(m_capacity + (m_capacity / 2) + 1, minimumMapSize);
     void* newStorage = 0;
+    DeferGC defer(*callFrame->heap());
     if (!callFrame->heap()->tryAllocateStorage(this, requiredSize * sizeof(Entry), &newStorage)) {
         throwOutOfMemoryError(callFrame);
         return false;
     }
-    DeferGC defer(*callFrame->heap());
     Entry* newEntries = static_cast<Entry*>(newStorage);
     if (shouldPack())
         replaceAndPackBackingStore(newEntries, requiredSize);
     else
         replaceBackingStore(newEntries, requiredSize);
+    Heap::writeBarrier(this);
     return true;
 }
 

Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (161229 => 161230)


--- trunk/Source/_javascript_Core/runtime/Structure.cpp	2014-01-02 22:43:57 UTC (rev 161229)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp	2014-01-02 22:57:14 UTC (rev 161230)
@@ -273,7 +273,7 @@
     findStructuresAndMapForMaterialization(structures, structure, table);
     
     if (table) {
-        table = table->copy(vm, 0, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
+        table = table->copy(vm, structure, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
         structure->m_lock.unlock();
     }
     
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to