Changeset 144708 in webkit
- Timestamp:
- Mar 4, 2013 7:05:27 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r144113 r144708 281 281 runtime/PropertyNameArray.cpp 282 282 runtime/PropertySlot.cpp 283 runtime/PropertyTable.cpp 283 284 runtime/PrototypeMap.cpp 284 285 runtime/RegExp.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r144698 r144708 1 2013-03-04 Andreas Kling <akling@apple.com> 2 3 Unused Structure property tables waste 14MB on Membuster. 4 <http://webkit.org/b/110854> 5 <rdar://problem/13292104> 6 7 Reviewed by Geoffrey Garen. 8 9 Turn PropertyTable into a GC object and have Structure drop unpinned tables when marking. 10 14 MB progression on Membuster3. 11 12 * CMakeLists.txt: 13 * GNUmakefile.list.am: 14 * JavaScriptCore.gypi: 15 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 16 * JavaScriptCore.xcodeproj/project.pbxproj: 17 * Target.pri: 18 19 Added PropertyTable.cpp. 20 21 * runtime/PropertyTable.cpp: Added. 22 (JSC::PropertyTable::create): 23 (JSC::PropertyTable::clone): 24 (JSC::PropertyTable::PropertyTable): 25 (JSC::PropertyTable::destroy): 26 (JSC::PropertyTable::~PropertyTable): 27 (JSC::PropertyTable::visitChildren): 28 29 Moved marking of property table values here from Structure::visitChildren(). 30 31 * runtime/WriteBarrier.h: 32 (JSC::WriteBarrierBase::get): 33 34 Move m_cell to a local before using it multiple times. This avoids a multiple-access race when 35 Structure::checkOffsetConsistency() is used in assertions on the main thread while a marking thread 36 zaps the property table. 37 38 * runtime/Structure.h: 39 (JSC::Structure::materializePropertyMapIfNecessary): 40 (JSC::Structure::materializePropertyMapIfNecessaryForPinning): 41 * runtime/StructureInlines.h: 42 (JSC::Structure::propertyTable): 43 44 Added a getter for the Structure's PropertyTable that ASSERTs GC currently isn't active. 45 Because GC can zap an unpinned property table at any time, it's not entirely safe to access it. 46 Renamed the variable itself to m_propertyTableUnsafe to force call sites into explaining themselves. 47 48 (JSC::Structure::putWillGrowOutOfLineStorage): 49 (JSC::Structure::checkOffsetConsistency): 50 51 Moved these out of Structure.h to break header dependency cycle between Structure/PropertyTable. 52 53 * runtime/Structure.cpp: 54 (JSC::Structure::visitChildren): 55 56 Null out m_propertyTable if the table is unpinned. This'll cause the table to get GC'd. 57 58 * runtime/JSGlobalData.h: 59 * runtime/JSGlobalData.cpp: 60 (JSC::JSGlobalData::JSGlobalData): 61 62 Add a global propertyTableStructure. 63 64 * runtime/PropertyMapHashTable.h: 65 (PropertyTable): 66 (JSC::PropertyTable::createStructure): 67 (JSC::PropertyTable::copy): 68 69 Make PropertyTable a GC object. 70 71 * runtime/Structure.cpp: 72 (JSC::Structure::dumpStatistics): 73 (JSC::Structure::materializePropertyMap): 74 (JSC::Structure::despecifyDictionaryFunction): 75 (JSC::Structure::addPropertyTransition): 76 (JSC::Structure::changePrototypeTransition): 77 (JSC::Structure::despecifyFunctionTransition): 78 (JSC::Structure::attributeChangeTransition): 79 (JSC::Structure::toDictionaryTransition): 80 (JSC::Structure::sealTransition): 81 (JSC::Structure::freezeTransition): 82 (JSC::Structure::preventExtensionsTransition): 83 (JSC::Structure::nonPropertyTransition): 84 (JSC::Structure::isSealed): 85 (JSC::Structure::isFrozen): 86 (JSC::Structure::flattenDictionaryStructure): 87 (JSC::Structure::pin): 88 (JSC::Structure::copyPropertyTable): 89 (JSC::Structure::copyPropertyTableForPinning): 90 (JSC::Structure::get): 91 (JSC::Structure::despecifyFunction): 92 (JSC::Structure::despecifyAllFunctions): 93 (JSC::Structure::putSpecificValue): 94 (JSC::Structure::remove): 95 (JSC::Structure::createPropertyMap): 96 (JSC::Structure::getPropertyNamesFromStructure): 97 (JSC::Structure::checkConsistency): 98 1 99 2013-03-04 Chris Fleizach <cfleizach@apple.com> 2 100 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r144113 r144708 723 723 Source/JavaScriptCore/runtime/PropertySlot.cpp \ 724 724 Source/JavaScriptCore/runtime/PropertySlot.h \ 725 Source/JavaScriptCore/runtime/PropertyTable.cpp \ 725 726 Source/JavaScriptCore/runtime/PrototypeMap.cpp \ 726 727 Source/JavaScriptCore/runtime/PrototypeMap.h \ -
trunk/Source/JavaScriptCore/JavaScriptCore.gypi
r144489 r144708 759 759 'runtime/PropertySlot.cpp', 760 760 'runtime/PropertySlot.h', 761 'runtime/PropertyTable.cpp', 761 762 'runtime/PropertyStorage.h', 762 763 'runtime/Protect.h', -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r144113 r144708 306 306 <ClCompile Include="..\runtime\PropertyNameArray.cpp" /> 307 307 <ClCompile Include="..\runtime\PropertySlot.cpp" /> 308 <ClCompile Include="..\runtime\PropertyTable.cpp" /> 308 309 <ClCompile Include="..\runtime\PrototypeMap.cpp" /> 309 310 <ClCompile Include="..\runtime\RegExp.cpp" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r144521 r144708 704 704 A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; }; 705 705 A8A4748E151A8306004123FF /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A4748D151A8306004123FF /* libWTF.a */; }; 706 ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */; }; 706 707 BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9050E1839DB000F9297 /* ErrorConstructor.h */; }; 707 708 BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9070E1839DB000F9297 /* ErrorPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1619 1620 A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; }; 1620 1621 A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; }; 1622 AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyTable.cpp; sourceTree = "<group>"; }; 1621 1623 BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ToolExecutable.xcconfig; sourceTree = "<group>"; }; 1622 1624 BC02E9040E1839DB000F9297 /* ErrorConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorConstructor.cpp; sourceTree = "<group>"; }; … … 2507 2509 65621E6C089E859700760F35 /* PropertySlot.h */, 2508 2510 0FB7F39015ED8E3800F167B2 /* PropertyStorage.h */, 2511 AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */, 2509 2512 65C02FBB0637462A003E7EE6 /* Protect.h */, 2510 2513 14D844A216AA2C7000A65AF0 /* PrototypeMap.cpp */, … … 4024 4027 0FBE0F7616C1DB0F0082C5E8 /* DFGUnificationPhase.cpp in Sources */, 4025 4028 0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */, 4029 ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */, 4026 4030 ); 4027 4031 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/JavaScriptCore/Target.pri
r144113 r144708 299 299 runtime/PropertyNameArray.cpp \ 300 300 runtime/PropertySlot.cpp \ 301 runtime/PropertyTable.cpp \ 301 302 runtime/PrototypeMap.cpp \ 302 303 runtime/RegExpConstructor.cpp \ -
trunk/Source/JavaScriptCore/runtime/JSGlobalData.cpp
r144113 r144708 233 233 unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull())); 234 234 unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull())); 235 propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull())); 235 236 smallStrings.initializeCommonStrings(*this); 236 237 -
trunk/Source/JavaScriptCore/runtime/JSGlobalData.h
r144113 r144708 257 257 Strong<Structure> unlinkedEvalCodeBlockStructure; 258 258 Strong<Structure> unlinkedFunctionCodeBlockStructure; 259 Strong<Structure> propertyTableStructure; 259 260 260 261 IdentifierTable* identifierTable; -
trunk/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
r144113 r144708 23 23 24 24 #include "PropertyOffset.h" 25 #include "Structure.h" 25 26 #include "WriteBarrier.h" 26 27 #include <wtf/HashTable.h> … … 86 87 }; 87 88 88 class PropertyTable { 89 WTF_MAKE_FAST_ALLOCATED; 89 class PropertyTable : public JSCell { 90 90 91 91 // This is the implementation for 'iterator' and 'const_iterator', … … 130 130 131 131 public: 132 static const bool needsDestruction = true; 133 static const bool hasImmortalStructure = true; 134 static void destroy(JSCell*); 135 136 static JS_EXPORTDATA const ClassInfo s_info; 137 138 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 139 { 140 return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info); 141 } 142 143 static void visitChildren(JSCell*, SlotVisitor&); 144 132 145 typedef StringImpl* KeyType; 133 146 typedef PropertyMapEntry ValueType; … … 143 156 144 157 // Constructor is passed an initial capacity, a PropertyTable to copy, or both. 145 explicit PropertyTable(unsigned initialCapacity);146 PropertyTable(JSGlobalData&, JSCell*, const PropertyTable&);147 PropertyTable(JSGlobalData&, JSCell*, unsigned initialCapacity, const PropertyTable&);158 static PropertyTable* create(JSGlobalData&, unsigned initialCapacity); 159 static PropertyTable* clone(JSGlobalData&, JSCell* owner, const PropertyTable&); 160 static PropertyTable* clone(JSGlobalData&, JSCell* owner, unsigned initialCapacity, const PropertyTable&); 148 161 ~PropertyTable(); 149 162 … … 182 195 183 196 // Copy this PropertyTable, ensuring the copy has at least the capacity provided. 184 P assOwnPtr<PropertyTable>copy(JSGlobalData&, JSCell* owner, unsigned newCapacity);197 PropertyTable* copy(JSGlobalData&, JSCell* owner, unsigned newCapacity); 185 198 186 199 #ifndef NDEBUG … … 190 203 191 204 private: 205 PropertyTable(JSGlobalData&, unsigned initialCapacity); 206 PropertyTable(JSGlobalData&, JSCell*, const PropertyTable&); 207 PropertyTable(JSGlobalData&, JSCell*, unsigned initialCapacity, const PropertyTable&); 208 192 209 PropertyTable(const PropertyTable&); 193 210 // Used to insert a value known not to be in the table, and where we know capacity to be available. … … 240 257 }; 241 258 242 inline PropertyTable::PropertyTable(unsigned initialCapacity)243 : m_indexSize(sizeForCapacity(initialCapacity))244 , m_indexMask(m_indexSize - 1)245 , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))246 , m_keyCount(0)247 , m_deletedCount(0)248 {249 ASSERT(isPowerOf2(m_indexSize));250 }251 252 inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, const PropertyTable& other)253 : m_indexSize(other.m_indexSize)254 , m_indexMask(other.m_indexMask)255 , m_index(static_cast<unsigned*>(fastMalloc(dataSize())))256 , m_keyCount(other.m_keyCount)257 , m_deletedCount(other.m_deletedCount)258 {259 ASSERT(isPowerOf2(m_indexSize));260 261 memcpy(m_index, other.m_index, dataSize());262 263 iterator end = this->end();264 for (iterator iter = begin(); iter != end; ++iter) {265 iter->key->ref();266 Heap::writeBarrier(owner, iter->specificValue.get());267 }268 269 // Copy the m_deletedOffsets vector.270 Vector<PropertyOffset>* otherDeletedOffsets = other.m_deletedOffsets.get();271 if (otherDeletedOffsets)272 m_deletedOffsets = adoptPtr(new Vector<PropertyOffset>(*otherDeletedOffsets));273 }274 275 inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, unsigned initialCapacity, const PropertyTable& other)276 : m_indexSize(sizeForCapacity(initialCapacity))277 , m_indexMask(m_indexSize - 1)278 , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))279 , m_keyCount(0)280 , m_deletedCount(0)281 {282 ASSERT(isPowerOf2(m_indexSize));283 ASSERT(initialCapacity >= other.m_keyCount);284 285 const_iterator end = other.end();286 for (const_iterator iter = other.begin(); iter != end; ++iter) {287 ASSERT(canInsert());288 reinsert(*iter);289 iter->key->ref();290 Heap::writeBarrier(owner, iter->specificValue.get());291 }292 293 // Copy the m_deletedOffsets vector.294 Vector<PropertyOffset>* otherDeletedOffsets = other.m_deletedOffsets.get();295 if (otherDeletedOffsets)296 m_deletedOffsets = adoptPtr(new Vector<PropertyOffset>(*otherDeletedOffsets));297 }298 299 inline PropertyTable::~PropertyTable()300 {301 iterator end = this->end();302 for (iterator iter = begin(); iter != end; ++iter)303 iter->key->deref();304 305 fastFree(m_index);306 }307 308 259 inline PropertyTable::iterator PropertyTable::begin() 309 260 { … … 503 454 } 504 455 505 inline P assOwnPtr<PropertyTable>PropertyTable::copy(JSGlobalData& globalData, JSCell* owner, unsigned newCapacity)456 inline PropertyTable* PropertyTable::copy(JSGlobalData& globalData, JSCell* owner, unsigned newCapacity) 506 457 { 507 458 ASSERT(newCapacity >= m_keyCount); … … 510 461 // save rehashing all keys. 511 462 if (sizeForCapacity(newCapacity) == m_indexSize) 512 return adoptPtr(new PropertyTable(globalData, owner, *this));513 return adoptPtr(new PropertyTable(globalData, owner, newCapacity, *this));463 return PropertyTable::clone(globalData, owner, *this); 464 return PropertyTable::clone(globalData, owner, newCapacity, *this); 514 465 } 515 466 -
trunk/Source/JavaScriptCore/runtime/Structure.cpp
r144113 r144708 132 132 } 133 133 134 if (structure-> m_propertyTable) {134 if (structure->propertyTable()) { 135 135 ++numberWithPropertyMaps; 136 totalPropertyMapsSize += structure-> m_propertyTable->sizeInMemory();136 totalPropertyMapsSize += structure->propertyTable()->sizeInMemory(); 137 137 } 138 138 } … … 235 235 { 236 236 ASSERT(structure()->classInfo() == &s_info); 237 ASSERT(! m_propertyTable);237 ASSERT(!propertyTable()); 238 238 239 239 Vector<Structure*, 8> structures; … … 245 245 while ((structure = structure->previousID())) { 246 246 if (structure->m_isPinnedPropertyTable) { 247 ASSERT(structure-> m_propertyTable);247 ASSERT(structure->propertyTable()); 248 248 ASSERT(!structure->previousID()); 249 249 250 m_propertyTable = structure->m_propertyTable->copy(globalData, 0, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));250 propertyTable().set(globalData, this, structure->propertyTable()->copy(globalData, 0, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity))); 251 251 break; 252 252 } … … 255 255 } 256 256 257 if (! m_propertyTable)258 createPropertyMap( numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));257 if (!propertyTable()) 258 createPropertyMap(globalData, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity)); 259 259 260 260 for (ptrdiff_t i = structures.size() - 1; i >= 0; --i) { … … 263 263 continue; 264 264 PropertyMapEntry entry(globalData, this, structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get()); 265 m_propertyTable->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);265 propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange); 266 266 } 267 267 … … 288 288 289 289 ASSERT(isDictionary()); 290 ASSERT( m_propertyTable);291 292 PropertyMapEntry* entry = m_propertyTable->find(rep).first;290 ASSERT(propertyTable()); 291 292 PropertyMapEntry* entry = propertyTable()->find(rep).first; 293 293 ASSERT(entry); 294 294 entry->specificValue.clear(); … … 374 374 transition->m_specificValueInPrevious.setMayBeNull(globalData, transition, specificValue); 375 375 376 if (structure-> m_propertyTable) {376 if (structure->propertyTable()) { 377 377 structure->checkOffsetConsistency(); 378 378 if (structure->m_isPinnedPropertyTable) 379 transition->m_propertyTable = structure->m_propertyTable->copy(globalData, transition, structure->m_propertyTable->size() + 1); 380 else 381 transition->m_propertyTable = structure->m_propertyTable.release(); 379 transition->propertyTable().set(globalData, transition, structure->propertyTable()->copy(globalData, transition, structure->propertyTable()->size() + 1)); 380 else { 381 transition->propertyTable().set(globalData, transition, structure->propertyTable().get()); 382 structure->propertyTable().clear(); 383 } 382 384 } else { 383 385 if (structure->previousID()) 384 386 transition->materializePropertyMap(globalData); 385 387 else 386 transition->createPropertyMap( );388 transition->createPropertyMap(globalData); 387 389 } 388 390 transition->m_offset = structure->m_offset; … … 416 418 417 419 structure->materializePropertyMapIfNecessary(globalData); 418 transition-> m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);420 transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition)); 419 421 transition->m_offset = structure->m_offset; 420 422 transition->pin(); … … 432 434 433 435 structure->materializePropertyMapIfNecessary(globalData); 434 transition-> m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);436 transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition)); 435 437 transition->m_offset = structure->m_offset; 436 438 transition->pin(); … … 453 455 454 456 structure->materializePropertyMapIfNecessary(globalData); 455 transition-> m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);457 transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition)); 456 458 transition->m_offset = structure->m_offset; 457 459 transition->pin(); … … 460 462 } 461 463 462 ASSERT(structure-> m_propertyTable);463 PropertyMapEntry* entry = structure-> m_propertyTable->find(propertyName.uid()).first;464 ASSERT(structure->propertyTable()); 465 PropertyMapEntry* entry = structure->propertyTable()->find(propertyName.uid()).first; 464 466 ASSERT(entry); 465 467 entry->attributes = attributes; … … 476 478 477 479 structure->materializePropertyMapIfNecessary(globalData); 478 transition-> m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);480 transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition)); 479 481 transition->m_offset = structure->m_offset; 480 482 transition->m_dictionaryKind = kind; … … 500 502 Structure* transition = preventExtensionsTransition(globalData, structure); 501 503 502 if (transition-> m_propertyTable) {503 PropertyTable::iterator end = transition-> m_propertyTable->end();504 for (PropertyTable::iterator iter = transition-> m_propertyTable->begin(); iter != end; ++iter)504 if (transition->propertyTable()) { 505 PropertyTable::iterator end = transition->propertyTable()->end(); 506 for (PropertyTable::iterator iter = transition->propertyTable()->begin(); iter != end; ++iter) 505 507 iter->attributes |= DontDelete; 506 508 } … … 515 517 Structure* transition = preventExtensionsTransition(globalData, structure); 516 518 517 if (transition-> m_propertyTable) {518 PropertyTable::iterator iter = transition-> m_propertyTable->begin();519 PropertyTable::iterator end = transition-> m_propertyTable->end();519 if (transition->propertyTable()) { 520 PropertyTable::iterator iter = transition->propertyTable()->begin(); 521 PropertyTable::iterator end = transition->propertyTable()->end(); 520 522 if (iter != end) 521 523 transition->m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true; … … 536 538 537 539 structure->materializePropertyMapIfNecessary(globalData); 538 transition-> m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);540 transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition)); 539 541 transition->m_offset = structure->m_offset; 540 542 transition->m_preventExtensions = true; … … 573 575 checkOffset(transition->m_offset, transition->inlineCapacity()); 574 576 575 if (structure-> m_propertyTable) {577 if (structure->propertyTable()) { 576 578 structure->checkOffsetConsistency(); 577 579 if (structure->m_isPinnedPropertyTable) 578 transition->m_propertyTable = structure->m_propertyTable->copy(globalData, transition, structure->m_propertyTable->size() + 1); 579 else 580 transition->m_propertyTable = structure->m_propertyTable.release(); 580 transition->propertyTable().set(globalData, transition, structure->propertyTable()->copy(globalData, transition, structure->propertyTable()->size() + 1)); 581 else { 582 transition->propertyTable().set(globalData, transition, structure->propertyTable().get()); 583 structure->propertyTable().clear(); 584 } 581 585 } else { 582 586 if (structure->previousID()) 583 587 transition->materializePropertyMap(globalData); 584 588 else 585 transition->createPropertyMap( );589 transition->createPropertyMap(globalData); 586 590 } 587 591 … … 598 602 599 603 materializePropertyMapIfNecessary(globalData); 600 if (! m_propertyTable)604 if (!propertyTable()) 601 605 return true; 602 606 603 PropertyTable::iterator end = m_propertyTable->end();604 for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {607 PropertyTable::iterator end = propertyTable()->end(); 608 for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) { 605 609 if ((iter->attributes & DontDelete) != DontDelete) 606 610 return false; … … 616 620 617 621 materializePropertyMapIfNecessary(globalData); 618 if (! m_propertyTable)622 if (!propertyTable()) 619 623 return true; 620 624 621 PropertyTable::iterator end = m_propertyTable->end();622 for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {625 PropertyTable::iterator end = propertyTable()->end(); 626 for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) { 623 627 if (!(iter->attributes & DontDelete)) 624 628 return false; … … 634 638 ASSERT(isDictionary()); 635 639 if (isUncacheableDictionary()) { 636 ASSERT( m_propertyTable);637 638 size_t propertyCount = m_propertyTable->size();640 ASSERT(propertyTable()); 641 642 size_t propertyCount = propertyTable()->size(); 639 643 640 644 // Holds our values compacted by insertion order. … … 643 647 // Copies out our values from their hashed locations, compacting property table offsets as we go. 644 648 unsigned i = 0; 645 PropertyTable::iterator end = m_propertyTable->end();649 PropertyTable::iterator end = propertyTable()->end(); 646 650 m_offset = invalidOffset; 647 for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter, ++i) {651 for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter, ++i) { 648 652 values[i] = object->getDirect(iter->offset); 649 653 m_offset = iter->offset = offsetForPropertyNumber(i, m_inlineCapacity); … … 654 658 object->putDirect(globalData, offsetForPropertyNumber(i, m_inlineCapacity), values[i]); 655 659 656 m_propertyTable->clearDeletedOffsets();660 propertyTable()->clearDeletedOffsets(); 657 661 checkOffsetConsistency(); 658 662 } … … 689 693 void Structure::pin() 690 694 { 691 ASSERT( m_propertyTable);695 ASSERT(propertyTable()); 692 696 m_isPinnedPropertyTable = true; 693 697 clearPreviousID(); … … 738 742 #endif 739 743 740 PassOwnPtr<PropertyTable> Structure::copyPropertyTable(JSGlobalData& globalData, Structure* owner) 741 { 742 return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : 0); 743 } 744 745 PassOwnPtr<PropertyTable> Structure::copyPropertyTableForPinning(JSGlobalData& globalData, Structure* owner) 746 { 747 return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : new PropertyTable(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity))); 744 PropertyTable* Structure::copyPropertyTable(JSGlobalData& globalData, Structure* owner) 745 { 746 if (!propertyTable()) 747 return 0; 748 return PropertyTable::clone(globalData, owner, *propertyTable().get()); 749 } 750 751 PropertyTable* Structure::copyPropertyTableForPinning(JSGlobalData& globalData, Structure* owner) 752 { 753 if (propertyTable()) 754 return PropertyTable::clone(globalData, owner, *propertyTable().get()); 755 return PropertyTable::create(globalData, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity)); 748 756 } 749 757 … … 753 761 754 762 materializePropertyMapIfNecessary(globalData); 755 if (! m_propertyTable)763 if (!propertyTable()) 756 764 return invalidOffset; 757 765 758 PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;766 PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first; 759 767 if (!entry) 760 768 return invalidOffset; … … 768 776 { 769 777 materializePropertyMapIfNecessary(globalData); 770 if (! m_propertyTable)778 if (!propertyTable()) 771 779 return false; 772 780 773 PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;781 PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first; 774 782 if (!entry) 775 783 return false; … … 783 791 { 784 792 materializePropertyMapIfNecessary(globalData); 785 if (! m_propertyTable)793 if (!propertyTable()) 786 794 return; 787 795 788 PropertyTable::iterator end = m_propertyTable->end();789 for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter)796 PropertyTable::iterator end = propertyTable()->end(); 797 for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) 790 798 iter->specificValue.clear(); 791 799 } … … 801 809 StringImpl* rep = propertyName.uid(); 802 810 803 if (! m_propertyTable)804 createPropertyMap( );805 806 PropertyOffset newOffset = m_propertyTable->nextOffset(m_inlineCapacity);807 808 m_propertyTable->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue), m_offset, PropertyTable::PropertyOffsetMayChange);811 if (!propertyTable()) 812 createPropertyMap(globalData); 813 814 PropertyOffset newOffset = propertyTable()->nextOffset(m_inlineCapacity); 815 816 propertyTable()->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue), m_offset, PropertyTable::PropertyOffsetMayChange); 809 817 810 818 checkConsistency(); … … 818 826 StringImpl* rep = propertyName.uid(); 819 827 820 if (! m_propertyTable)828 if (!propertyTable()) 821 829 return invalidOffset; 822 830 823 PropertyTable::find_iterator position = m_propertyTable->find(rep);831 PropertyTable::find_iterator position = propertyTable()->find(rep); 824 832 if (!position.first) 825 833 return invalidOffset; … … 827 835 PropertyOffset offset = position.first->offset; 828 836 829 m_propertyTable->remove(position);830 m_propertyTable->addDeletedOffset(offset);837 propertyTable()->remove(position); 838 propertyTable()->addDeletedOffset(offset); 831 839 832 840 checkConsistency(); … … 834 842 } 835 843 836 void Structure::createPropertyMap( unsigned capacity)837 { 838 ASSERT(! m_propertyTable);844 void Structure::createPropertyMap(JSGlobalData& globalData, unsigned capacity) 845 { 846 ASSERT(!propertyTable()); 839 847 840 848 checkConsistency(); 841 m_propertyTable = adoptPtr(new PropertyTable(capacity));849 propertyTable().set(globalData, this, PropertyTable::create(globalData, capacity)); 842 850 } 843 851 … … 845 853 { 846 854 materializePropertyMapIfNecessary(globalData); 847 if (! m_propertyTable)855 if (!propertyTable()) 848 856 return; 849 857 850 858 bool knownUnique = !propertyNames.size(); 851 859 852 PropertyTable::iterator end = m_propertyTable->end();853 for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {860 PropertyTable::iterator end = propertyTable()->end(); 861 for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) { 854 862 ASSERT(m_hasNonEnumerableProperties || !(iter->attributes & DontEnum)); 855 863 if (iter->key->isIdentifier() && (!(iter->attributes & DontEnum) || mode == IncludeDontEnumProperties)) { … … 883 891 visitor.append(&thisObject->m_previousOrRareData); 884 892 visitor.append(&thisObject->m_specificValueInPrevious); 885 if (thisObject->m_propertyTable) { 886 PropertyTable::iterator end = thisObject->m_propertyTable->end(); 887 for (PropertyTable::iterator ptr = thisObject->m_propertyTable->begin(); ptr != end; ++ptr) 888 visitor.append(&ptr->specificValue); 889 } 893 894 if (thisObject->m_isPinnedPropertyTable) { 895 ASSERT(thisObject->m_propertyTableUnsafe); 896 visitor.append(&thisObject->m_propertyTableUnsafe); 897 } else if (thisObject->m_propertyTableUnsafe) 898 thisObject->m_propertyTableUnsafe.clear(); 890 899 } 891 900 … … 978 987 void Structure::checkConsistency() 979 988 { 980 if (! m_propertyTable)989 if (!propertyTable()) 981 990 return; 982 991 983 992 if (!m_hasNonEnumerableProperties) { 984 PropertyTable::iterator end = m_propertyTable->end();985 for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {993 PropertyTable::iterator end = propertyTable()->end(); 994 for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) { 986 995 ASSERT(!(iter->attributes & DontEnum)); 987 996 } 988 997 } 989 998 990 m_propertyTable->checkConsistency();999 propertyTable()->checkConsistency(); 991 1000 } 992 1001 -
trunk/Source/JavaScriptCore/runtime/Structure.h
r144113 r144708 32 32 #include "JSCell.h" 33 33 #include "JSType.h" 34 #include "PropertyMapHashTable.h"35 34 #include "PropertyName.h" 36 35 #include "PropertyNameArray.h" 36 #include "PropertyOffset.h" 37 37 #include "Protect.h" 38 38 #include "StructureRareData.h" … … 41 41 #include "Watchpoint.h" 42 42 #include "Weak.h" 43 #include <wtf/PassOwnPtr.h>44 43 #include <wtf/PassRefPtr.h> 45 44 #include <wtf/RefCounted.h> … … 52 51 class PropertyNameArray; 53 52 class PropertyNameArrayData; 53 class PropertyTable; 54 54 class StructureChain; 55 55 class SlotVisitor; … … 109 109 bool isExtensible() const { return !m_preventExtensions; } 110 110 bool didTransition() const { return m_didTransition; } 111 bool putWillGrowOutOfLineStorage() 112 { 113 checkOffsetConsistency(); 114 115 ASSERT(outOfLineCapacity() >= outOfLineSize()); 116 117 if (!m_propertyTable) { 118 unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset); 119 ASSERT(outOfLineCapacity() >= currentSize); 120 return currentSize == outOfLineCapacity(); 121 } 122 123 ASSERT(totalStorageCapacity() >= m_propertyTable->propertyStorageSize()); 124 if (m_propertyTable->hasDeletedOffset()) 125 return false; 126 127 ASSERT(totalStorageCapacity() >= m_propertyTable->size()); 128 return m_propertyTable->size() == totalStorageCapacity(); 129 } 111 bool putWillGrowOutOfLineStorage(); 130 112 JS_EXPORT_PRIVATE size_t suggestedNewOutOfLineStorageCapacity(); 131 113 … … 383 365 PropertyOffset remove(PropertyName); 384 366 385 void createPropertyMap( unsigned keyCount = 0);367 void createPropertyMap(JSGlobalData&, unsigned keyCount = 0); 386 368 void checkConsistency(); 387 369 … … 389 371 void despecifyAllFunctions(JSGlobalData&); 390 372 391 PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner); 392 PassOwnPtr<PropertyTable> copyPropertyTableForPinning(JSGlobalData&, Structure* owner); 373 WriteBarrier<PropertyTable>& propertyTable(); 374 375 PropertyTable* copyPropertyTable(JSGlobalData&, Structure* owner); 376 PropertyTable* copyPropertyTableForPinning(JSGlobalData&, Structure* owner); 393 377 JS_EXPORT_PRIVATE void materializePropertyMap(JSGlobalData&); 394 378 void materializePropertyMapIfNecessary(JSGlobalData& globalData) … … 396 380 ASSERT(structure()->classInfo() == &s_info); 397 381 ASSERT(checkOffsetConsistency()); 398 if (! m_propertyTable&& previousID())382 if (!propertyTable() && previousID()) 399 383 materializePropertyMap(globalData); 400 384 } … … 403 387 ASSERT(structure()->classInfo() == &s_info); 404 388 checkOffsetConsistency(); 405 if (! m_propertyTable)389 if (!propertyTable()) 406 390 materializePropertyMap(globalData); 407 391 } … … 446 430 } 447 431 448 ALWAYS_INLINE bool checkOffsetConsistency() const 449 { 450 if (!m_propertyTable) { 451 ASSERT(!m_isPinnedPropertyTable); 452 return true; 453 } 454 455 RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == m_propertyTable->propertyStorageSize()); 456 unsigned totalSize = m_propertyTable->propertyStorageSize(); 457 RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset)); 458 459 return true; 460 } 432 bool checkOffsetConsistency() const; 461 433 462 434 void allocateRareData(JSGlobalData&); … … 483 455 StructureTransitionTable m_transitionTable; 484 456 485 OwnPtr<PropertyTable> m_propertyTable; 457 // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread. 458 WriteBarrier<PropertyTable> m_propertyTableUnsafe; 486 459 487 460 mutable InlineWatchpointSet m_transitionWatchpointSet; -
trunk/Source/JavaScriptCore/runtime/StructureInlines.h
r144113 r144708 27 27 #define StructureInlines_h 28 28 29 #include "PropertyMapHashTable.h" 29 30 #include "Structure.h" 30 31 … … 62 63 ASSERT(structure()->classInfo() == &s_info); 63 64 materializePropertyMapIfNecessary(globalData); 64 if (! m_propertyTable)65 if (!propertyTable()) 65 66 return invalidOffset; 66 67 67 PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;68 PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first; 68 69 return entry ? entry->offset : invalidOffset; 69 70 } … … 73 74 ASSERT(structure()->classInfo() == &s_info); 74 75 materializePropertyMapIfNecessary(globalData); 75 if (! m_propertyTable)76 if (!propertyTable()) 76 77 return invalidOffset; 77 78 78 PropertyMapEntry* entry = m_propertyTable->findWithString(name.impl()).first;79 PropertyMapEntry* entry = propertyTable()->findWithString(name.impl()).first; 79 80 return entry ? entry->offset : invalidOffset; 80 81 } … … 180 181 } 181 182 183 inline bool Structure::putWillGrowOutOfLineStorage() 184 { 185 checkOffsetConsistency(); 186 187 ASSERT(outOfLineCapacity() >= outOfLineSize()); 188 189 if (!propertyTable()) { 190 unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset); 191 ASSERT(outOfLineCapacity() >= currentSize); 192 return currentSize == outOfLineCapacity(); 193 } 194 195 ASSERT(totalStorageCapacity() >= propertyTable()->propertyStorageSize()); 196 if (propertyTable()->hasDeletedOffset()) 197 return false; 198 199 ASSERT(totalStorageCapacity() >= propertyTable()->size()); 200 return propertyTable()->size() == totalStorageCapacity(); 201 } 202 203 ALWAYS_INLINE WriteBarrier<PropertyTable>& Structure::propertyTable() 204 { 205 ASSERT(!globalObject() || !globalObject()->globalData().heap.isBusy()); 206 return m_propertyTableUnsafe; 207 } 208 209 ALWAYS_INLINE bool Structure::checkOffsetConsistency() const 210 { 211 PropertyTable* propertyTable = m_propertyTableUnsafe.get(); 212 213 if (!propertyTable) { 214 ASSERT(!m_isPinnedPropertyTable); 215 return true; 216 } 217 218 RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == propertyTable->propertyStorageSize()); 219 unsigned totalSize = propertyTable->propertyStorageSize(); 220 RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset)); 221 222 return true; 223 } 224 182 225 } // namespace JSC 183 226 -
trunk/Source/JavaScriptCore/runtime/WriteBarrier.h
r128084 r144708 100 100 T* get() const 101 101 { 102 if (m_cell) 103 validateCell(m_cell); 104 return reinterpret_cast<T*>(static_cast<void*>(m_cell)); 102 // Copy m_cell to a local to avoid multiple-read issues. (See <http://webkit.org/b/110854>) 103 JSCell* cell = m_cell; 104 if (cell) 105 validateCell(cell); 106 return reinterpret_cast<T*>(static_cast<void*>(cell)); 105 107 } 106 108
Note: See TracChangeset
for help on using the changeset viewer.