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();
}