Changeset 154366 in webkit
- Timestamp:
- Aug 20, 2013 3:17:29 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r154362 r154366 1 2013-08-20 Mark Hahnenberg <mhahnenberg@apple.com> 2 3 <https://webkit.org/b/120079> Flattening a dictionary can cause CopiedSpace corruption 4 5 Reviewed by Oliver Hunt. 6 7 When we flatten an object in dictionary mode, we compact its properties. If the object 8 had out-of-line storage in the form of a Butterfly prior to this compaction, and after 9 compaction its properties fit inline, the object's Structure "forgets" that the object 10 has a non-zero Butterfly pointer. During GC, we check the Butterfly and reportLiveBytes 11 with bytes = 0, which causes all sorts of badness in CopiedSpace. 12 13 Instead, after we flatten a dictionary, if properties fit inline we should clear the 14 Butterfly pointer so that the GC doesn't get confused later. 15 16 This patch does this clearing, and it also adds JSObject::checkStructure, which overrides 17 JSCell::checkStructure to add an ASSERT that makes sure that the Structure being assigned 18 agrees with the whether or not the object has a Butterfly. Also added an ASSERT to check 19 that the number of bytes reported to SlotVisitor::copyLater is non-zero. 20 21 * heap/SlotVisitorInlines.h: 22 (JSC::SlotVisitor::copyLater): 23 * runtime/JSObject.cpp: 24 (JSC::JSObject::notifyPresenceOfIndexedAccessors): 25 (JSC::JSObject::convertUndecidedToInt32): 26 (JSC::JSObject::convertUndecidedToDouble): 27 (JSC::JSObject::convertUndecidedToContiguous): 28 (JSC::JSObject::convertInt32ToDouble): 29 (JSC::JSObject::convertInt32ToContiguous): 30 (JSC::JSObject::genericConvertDoubleToContiguous): 31 (JSC::JSObject::switchToSlowPutArrayStorage): 32 (JSC::JSObject::setPrototype): 33 (JSC::JSObject::putDirectAccessor): 34 (JSC::JSObject::seal): 35 (JSC::JSObject::freeze): 36 (JSC::JSObject::preventExtensions): 37 (JSC::JSObject::reifyStaticFunctionsForDelete): 38 (JSC::JSObject::removeDirect): 39 * runtime/JSObject.h: 40 (JSC::JSObject::setButterfly): 41 (JSC::JSObject::putDirectInternal): 42 (JSC::JSObject::setStructure): 43 (JSC::JSObject::setStructureAndReallocateStorageIfNecessary): 44 * runtime/Structure.cpp: 45 (JSC::Structure::flattenDictionaryStructure): 46 1 47 2013-08-20 Alex Christensen <achristensen@apple.com> 2 48 -
trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h
r153720 r154366 211 211 inline void SlotVisitor::copyLater(JSCell* owner, CopyToken token, void* ptr, size_t bytes) 212 212 { 213 ASSERT(bytes); 213 214 CopiedBlock* block = CopiedSpace::blockFor(ptr); 214 215 if (block->isOversize()) { -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r154337 r154366 584 584 return; 585 585 586 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AddIndexedAccessors) );586 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AddIndexedAccessors), m_butterfly); 587 587 588 588 if (!vm.prototypeMap.isPrototype(this)) … … 670 670 { 671 671 ASSERT(hasUndecided(structure()->indexingType())); 672 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateInt32) );672 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateInt32), m_butterfly); 673 673 return m_butterfly->contiguousInt32(); 674 674 } … … 681 681 m_butterfly->contiguousDouble()[i] = QNaN; 682 682 683 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble) );683 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble), m_butterfly); 684 684 return m_butterfly->contiguousDouble(); 685 685 } … … 688 688 { 689 689 ASSERT(hasUndecided(structure()->indexingType())); 690 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous) );690 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous), m_butterfly); 691 691 return m_butterfly->contiguous(); 692 692 } … … 754 754 } 755 755 756 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble) );756 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble), m_butterfly); 757 757 return m_butterfly->contiguousDouble(); 758 758 } … … 762 762 ASSERT(hasInt32(structure()->indexingType())); 763 763 764 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous) );764 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous), m_butterfly); 765 765 return m_butterfly->contiguous(); 766 766 } … … 820 820 } 821 821 822 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous) );822 setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous), m_butterfly); 823 823 return m_butterfly->contiguous(); 824 824 } … … 1118 1118 case ArrayWithArrayStorage: { 1119 1119 Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), SwitchToSlowPutArrayStorage); 1120 setStructure(vm, newStructure );1120 setStructure(vm, newStructure, m_butterfly); 1121 1121 break; 1122 1122 } … … 1142 1142 1143 1143 Structure* newStructure = Structure::changePrototypeTransition(vm, structure(), prototype); 1144 setStructure(vm, newStructure );1144 setStructure(vm, newStructure, m_butterfly); 1145 1145 1146 1146 if (!newStructure->anyObjectInChainMayInterceptIndexedAccesses()) … … 1199 1199 // if we override an existing non-getter or non-setter. 1200 1200 if (slot.type() != PutPropertySlot::NewProperty) 1201 setStructure(vm, Structure::attributeChangeTransition(vm, structure(), propertyName, attributes) );1201 setStructure(vm, Structure::attributeChangeTransition(vm, structure(), propertyName, attributes), m_butterfly); 1202 1202 1203 1203 if (attributes & ReadOnly) … … 1556 1556 return; 1557 1557 preventExtensions(vm); 1558 setStructure(vm, Structure::sealTransition(vm, structure()) );1558 setStructure(vm, Structure::sealTransition(vm, structure()), m_butterfly); 1559 1559 } 1560 1560 … … 1564 1564 return; 1565 1565 preventExtensions(vm); 1566 setStructure(vm, Structure::freezeTransition(vm, structure()) );1566 setStructure(vm, Structure::freezeTransition(vm, structure()), m_butterfly); 1567 1567 } 1568 1568 … … 1571 1571 enterDictionaryIndexingMode(vm); 1572 1572 if (isExtensible()) 1573 setStructure(vm, Structure::preventExtensionsTransition(vm, structure()) );1573 setStructure(vm, Structure::preventExtensionsTransition(vm, structure()), m_butterfly); 1574 1574 } 1575 1575 … … 1589 1589 1590 1590 if (!structure()->isUncacheableDictionary()) 1591 setStructure(vm, Structure::toUncacheableDictionaryTransition(vm, structure()) );1591 setStructure(vm, Structure::toUncacheableDictionaryTransition(vm, structure()), m_butterfly); 1592 1592 1593 1593 for (const ClassInfo* info = classInfo(); info; info = info->parentClass) { … … 1619 1619 } 1620 1620 1621 setStructure(vm, Structure::removePropertyTransition(vm, structure(), propertyName, offset) );1621 setStructure(vm, Structure::removePropertyTransition(vm, structure(), propertyName, offset), m_butterfly); 1622 1622 if (offset == invalidOffset) 1623 1623 return false; -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r154337 r154366 611 611 void setButterflyWithoutChangingStructure(Butterfly*); // You probably don't want to call this. 612 612 613 void setStructure(VM&, Structure*, Butterfly* = 0); 613 614 void setStructureAndReallocateStorageIfNecessary(VM&, unsigned oldCapacity, Structure*); 614 615 void setStructureAndReallocateStorageIfNecessary(VM&, Structure*); … … 1125 1126 ASSERT(structure); 1126 1127 ASSERT(!butterfly == (!structure->outOfLineCapacity() && !structure->hasIndexingHeader(this))); 1127 setStructure(vm, structure );1128 setStructure(vm, structure, butterfly); 1128 1129 m_butterfly = butterfly; 1129 1130 } … … 1342 1343 } 1343 1344 // case (2) Despecify, fall through to (3). 1344 setStructure(vm, Structure::despecifyFunctionTransition(vm, structure(), propertyName) );1345 setStructure(vm, Structure::despecifyFunctionTransition(vm, structure(), propertyName), m_butterfly); 1345 1346 } 1346 1347 … … 1370 1371 } 1371 1372 1373 inline void JSObject::setStructure(VM& vm, Structure* structure, Butterfly* butterfly) 1374 { 1375 JSCell::setStructure(vm, structure); 1376 ASSERT_UNUSED(butterfly, !butterfly == !(structure->outOfLineCapacity() || structure->hasIndexingHeader(this))); 1377 } 1378 1372 1379 inline void JSObject::setStructureAndReallocateStorageIfNecessary(VM& vm, unsigned oldCapacity, Structure* newStructure) 1373 1380 { … … 1375 1382 1376 1383 if (oldCapacity == newStructure->outOfLineCapacity()) { 1377 setStructure(vm, newStructure );1384 setStructure(vm, newStructure, m_butterfly); 1378 1385 return; 1379 1386 } -
trunk/Source/JavaScriptCore/runtime/Structure.cpp
r154199 r154366 703 703 704 704 m_dictionaryKind = NoneDictionaryKind; 705 706 // If the object had a Butterfly but after flattening/compacting we no longer have need of it, 707 // we need to zero it out because the collector depends on the Structure to know the size for copying. 708 if (object->butterfly() && !this->outOfLineCapacity() && !this->hasIndexingHeader(object)) 709 object->setButterfly(vm, 0, this); 710 705 711 return this; 706 712 }
Note: See TracChangeset
for help on using the changeset viewer.