summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSObject.cpp
diff options
context:
space:
mode:
authorMark Hahnenberg <mhahnenberg@apple.com>2014-09-25 11:46:15 +0200
committerAllan Sandfeld Jensen <allan.jensen@digia.com>2014-09-25 18:15:52 +0200
commit3a51e3ee766490fe6f9ab9511d19e16f75e07db8 (patch)
treedd6aac2bd555f718130c07146564957c155d7339 /Source/JavaScriptCore/runtime/JSObject.cpp
parent405022cf7bba9bb702b9385dbcb983c789c838b1 (diff)
downloadqtwebkit-3a51e3ee766490fe6f9ab9511d19e16f75e07db8.tar.gz
<https://webkit.org/b/120079> Flattening a dictionary can cause CopiedSpace corruption
Reviewed by Oliver Hunt. When we flatten an object in dictionary mode, we compact its properties. If the object had out-of-line storage in the form of a Butterfly prior to this compaction, and after compaction its properties fit inline, the object's Structure "forgets" that the object has a non-zero Butterfly pointer. During GC, we check the Butterfly and reportLiveBytes with bytes = 0, which causes all sorts of badness in CopiedSpace. Instead, after we flatten a dictionary, if properties fit inline we should clear the Butterfly pointer so that the GC doesn't get confused later. This patch does this clearing, and it also adds JSObject::checkStructure, which overrides JSCell::checkStructure to add an ASSERT that makes sure that the Structure being assigned agrees with the whether or not the object has a Butterfly. Also added an ASSERT to check that the number of bytes reported to SlotVisitor::copyLater is non-zero. * heap/SlotVisitorInlines.h: (JSC::SlotVisitor::copyLater): * runtime/JSObject.cpp: (JSC::JSObject::notifyPresenceOfIndexedAccessors): (JSC::JSObject::convertUndecidedToInt32): (JSC::JSObject::convertUndecidedToDouble): (JSC::JSObject::convertUndecidedToContiguous): (JSC::JSObject::convertInt32ToDouble): (JSC::JSObject::convertInt32ToContiguous): (JSC::JSObject::genericConvertDoubleToContiguous): (JSC::JSObject::switchToSlowPutArrayStorage): (JSC::JSObject::setPrototype): (JSC::JSObject::putDirectAccessor): (JSC::JSObject::seal): (JSC::JSObject::freeze): (JSC::JSObject::preventExtensions): (JSC::JSObject::reifyStaticFunctionsForDelete): (JSC::JSObject::removeDirect): * runtime/JSObject.h: (JSC::JSObject::setButterfly): (JSC::JSObject::putDirectInternal): (JSC::JSObject::setStructure): (JSC::JSObject::setStructureAndReallocateStorageIfNecessary): * runtime/Structure.cpp: (JSC::Structure::flattenDictionaryStructure): Change-Id: Idfd8c22555f4373c1104316ff1ee28f5f84ef083 git-svn-id: http://svn.webkit.org/repository/webkit/trunk@154366 268f45cc-cd09-0410-ab3c-d52691b4dbfc Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSObject.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp30
1 files changed, 15 insertions, 15 deletions
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index 01dc96333..5637e2090 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -595,7 +595,7 @@ void JSObject::notifyPresenceOfIndexedAccessors(VM& vm)
if (mayInterceptIndexedAccesses())
return;
- setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AddIndexedAccessors));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AddIndexedAccessors), m_butterfly);
if (!vm.prototypeMap.isPrototype(this))
return;
@@ -681,7 +681,7 @@ ArrayStorage* JSObject::createInitialArrayStorage(VM& vm)
ContiguousJSValues JSObject::convertUndecidedToInt32(VM& vm)
{
ASSERT(hasUndecided(structure()->indexingType()));
- setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateInt32));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateInt32), m_butterfly);
return m_butterfly->contiguousInt32();
}
@@ -692,14 +692,14 @@ ContiguousDoubles JSObject::convertUndecidedToDouble(VM& vm)
for (unsigned i = m_butterfly->vectorLength(); i--;)
m_butterfly->contiguousDouble()[i] = QNaN;
- setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble), m_butterfly);
return m_butterfly->contiguousDouble();
}
ContiguousJSValues JSObject::convertUndecidedToContiguous(VM& vm)
{
ASSERT(hasUndecided(structure()->indexingType()));
- setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous), m_butterfly);
return m_butterfly->contiguous();
}
@@ -765,7 +765,7 @@ ContiguousDoubles JSObject::convertInt32ToDouble(VM& vm)
*currentAsDouble = v.asInt32();
}
- setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble), m_butterfly);
return m_butterfly->contiguousDouble();
}
@@ -773,7 +773,7 @@ ContiguousJSValues JSObject::convertInt32ToContiguous(VM& vm)
{
ASSERT(hasInt32(structure()->indexingType()));
- setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous), m_butterfly);
return m_butterfly->contiguous();
}
@@ -831,7 +831,7 @@ ContiguousJSValues JSObject::genericConvertDoubleToContiguous(VM& vm)
currentAsValue->setWithoutWriteBarrier(v);
}
- setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous), m_butterfly);
return m_butterfly->contiguous();
}
@@ -1129,7 +1129,7 @@ void JSObject::switchToSlowPutArrayStorage(VM& vm)
case NonArrayWithArrayStorage:
case ArrayWithArrayStorage: {
Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), SwitchToSlowPutArrayStorage);
- setStructure(vm, newStructure);
+ setStructure(vm, newStructure, m_butterfly);
break;
}
@@ -1153,7 +1153,7 @@ void JSObject::setPrototype(VM& vm, JSValue prototype)
vm.prototypeMap.addPrototype(asObject(prototype));
Structure* newStructure = Structure::changePrototypeTransition(vm, structure(), prototype);
- setStructure(vm, newStructure);
+ setStructure(vm, newStructure, m_butterfly);
if (!newStructure->anyObjectInChainMayInterceptIndexedAccesses())
return;
@@ -1213,7 +1213,7 @@ void JSObject::putDirectAccessor(ExecState* exec, PropertyName propertyName, JSV
// getters and setters, though, we also need to change our Structure
// if we override an existing non-getter or non-setter.
if (slot.type() != PutPropertySlot::NewProperty)
- setStructure(vm, Structure::attributeChangeTransition(vm, structure(), propertyName, attributes));
+ setStructure(vm, Structure::attributeChangeTransition(vm, structure(), propertyName, attributes), m_butterfly);
if (attributes & ReadOnly)
structure()->setContainsReadOnlyProperties();
@@ -1570,7 +1570,7 @@ void JSObject::seal(VM& vm)
if (isSealed(vm))
return;
preventExtensions(vm);
- setStructure(vm, Structure::sealTransition(vm, structure()));
+ setStructure(vm, Structure::sealTransition(vm, structure()), m_butterfly);
}
void JSObject::freeze(VM& vm)
@@ -1578,14 +1578,14 @@ void JSObject::freeze(VM& vm)
if (isFrozen(vm))
return;
preventExtensions(vm);
- setStructure(vm, Structure::freezeTransition(vm, structure()));
+ setStructure(vm, Structure::freezeTransition(vm, structure()), m_butterfly);
}
void JSObject::preventExtensions(VM& vm)
{
enterDictionaryIndexingMode(vm);
if (isExtensible())
- setStructure(vm, Structure::preventExtensionsTransition(vm, structure()));
+ setStructure(vm, Structure::preventExtensionsTransition(vm, structure()), m_butterfly);
}
// This presently will flatten to an uncachable dictionary; this is suitable
@@ -1603,7 +1603,7 @@ void JSObject::reifyStaticFunctionsForDelete(ExecState* exec)
}
if (!structure()->isUncacheableDictionary())
- setStructure(vm, Structure::toUncacheableDictionaryTransition(vm, structure()));
+ setStructure(vm, Structure::toUncacheableDictionaryTransition(vm, structure()), m_butterfly);
for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
const HashTable* hashTable = info->propHashTable(globalObject()->globalExec());
@@ -1633,7 +1633,7 @@ bool JSObject::removeDirect(VM& vm, PropertyName propertyName)
return true;
}
- setStructure(vm, Structure::removePropertyTransition(vm, structure(), propertyName, offset));
+ setStructure(vm, Structure::removePropertyTransition(vm, structure(), propertyName, offset), m_butterfly);
if (offset == invalidOffset)
return false;
putDirectUndefined(offset);