Changeset 167501 in webkit
- Timestamp:
- Apr 18, 2014 1:07:50 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r167500 r167501 1 2014-04-17 Mark Hahnenberg <mhahnenberg@apple.com> 2 3 Deleting properties poisons objects 4 https://bugs.webkit.org/show_bug.cgi?id=131551 5 6 Reviewed by Geoffrey Garen. 7 8 New JS regress test. We're ~3.5x faster on this microbenchmark now. 9 10 * js/regress/delete-a-few-properties-then-get-by-id-expected.txt: Added. 11 * js/regress/delete-a-few-properties-then-get-by-id.html: Added. 12 * js/regress/script-tests/delete-a-few-properties-then-get-by-id.js: Added. 13 (MyObject): 14 (foo): 15 1 16 2014-04-18 Alexey Proskuryakov <ap@apple.com> 2 17 -
trunk/Source/JavaScriptCore/ChangeLog
r167467 r167501 1 2014-04-17 Mark Hahnenberg <mhahnenberg@apple.com> 2 3 Deleting properties poisons objects 4 https://bugs.webkit.org/show_bug.cgi?id=131551 5 6 Reviewed by Geoffrey Garen. 7 8 This is ~3% progression on Dromaeo with a ~6% progression on the jslib portion of Dromaeo in particular. 9 10 * runtime/Structure.cpp: 11 (JSC::Structure::Structure): 12 (JSC::Structure::materializePropertyMap): We now re-use deleted properties when materializing the property map. 13 (JSC::Structure::removePropertyTransition): We allow up to 5 deletes for a particular path through the tree of 14 Structure transitions. After that, we convert to an uncacheable dictionary like we used to. We don't cache 15 delete transitions, but we allow transitioning from them. 16 (JSC::Structure::changePrototypeTransition): 17 (JSC::Structure::despecifyFunctionTransition): 18 (JSC::Structure::attributeChangeTransition): 19 (JSC::Structure::toDictionaryTransition): 20 (JSC::Structure::preventExtensionsTransition): 21 (JSC::Structure::addPropertyWithoutTransition): 22 (JSC::Structure::removePropertyWithoutTransition): 23 (JSC::Structure::pin): Now does only what it says it does--marks the property table as pinned. 24 (JSC::Structure::pinAndPreventTransitions): More descriptive version of what the old pin() was doing. 25 * runtime/Structure.h: 26 * runtime/StructureInlines.h: 27 (JSC::Structure::checkOffsetConsistency): Rearranged variables to be more sensible. 28 1 29 2014-04-17 Filip Pizlo <fpizlo@apple.com> 2 30 -
trunk/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
r166792 r167501 64 64 jsPropertyNameIterator->finishCreation(vm, propertyNames.data(), o); 65 65 66 if (o->structure()->isDictionary()) 66 // JSPropertyNameIterator doesn't know how to skip deleted buckets, so just give up. 67 if (o->structure()->isDictionary() || o->structure()->hasDeletedOffsets()) 67 68 return jsPropertyNameIterator; 68 69 -
trunk/Source/JavaScriptCore/runtime/Structure.cpp
r165946 r167501 166 166 , m_offset(invalidOffset) 167 167 , m_inlineCapacity(inlineCapacity) 168 , m_forgivenDeletes(0) 168 169 , m_dictionaryKind(NoneDictionaryKind) 169 170 , m_isPinnedPropertyTable(false) … … 193 194 , m_offset(invalidOffset) 194 195 , m_inlineCapacity(0) 196 , m_forgivenDeletes(0) 195 197 , m_dictionaryKind(NoneDictionaryKind) 196 198 , m_isPinnedPropertyTable(false) … … 219 221 , m_offset(invalidOffset) 220 222 , m_inlineCapacity(previous->m_inlineCapacity) 223 , m_forgivenDeletes(previous->m_forgivenDeletes) 221 224 , m_dictionaryKind(previous->m_dictionaryKind) 222 225 , m_isPinnedPropertyTable(false) … … 311 314 if (!structure->m_nameInPrevious) 312 315 continue; 313 PropertyMapEntry entry(vm, this, structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get()); 316 317 PropertyMapEntry entry(vm, this, 318 structure->m_nameInPrevious.get(), 319 propertyTable()->nextOffset(m_inlineCapacity), 320 structure->m_attributesInPrevious, 321 structure->m_specificValueInPrevious.get()); 314 322 propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange); 315 323 } … … 459 467 ASSERT(!structure->isUncacheableDictionary()); 460 468 469 if (structure->m_forgivenDeletes < s_maxForgivenDeletes) { 470 Structure* transition = create(vm, structure); 471 472 DeferGC deferGC(vm.heap); 473 structure->materializePropertyMapIfNecessary(vm, deferGC); 474 transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition)); 475 transition->m_offset = structure->m_offset; 476 transition->pinAndPreventTransitions(); 477 478 offset = transition->remove(propertyName); 479 ASSERT(offset != invalidOffset); 480 transition->m_forgivenDeletes = structure->m_forgivenDeletes + 1; 481 482 transition->checkOffsetConsistency(); 483 return transition; 484 } 485 461 486 Structure* transition = toUncacheableDictionaryTransition(vm, structure); 462 463 487 offset = transition->remove(propertyName); 464 465 488 transition->checkOffsetConsistency(); 466 489 return transition; … … 477 500 transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition)); 478 501 transition->m_offset = structure->m_offset; 479 transition->pin ();502 transition->pinAndPreventTransitions(); 480 503 481 504 transition->checkOffsetConsistency(); … … 494 517 transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition)); 495 518 transition->m_offset = structure->m_offset; 496 transition->pin ();519 transition->pinAndPreventTransitions(); 497 520 498 521 if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount) … … 516 539 transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition)); 517 540 transition->m_offset = structure->m_offset; 518 transition->pin ();541 transition->pinAndPreventTransitions(); 519 542 520 543 structure = transition; … … 541 564 transition->m_offset = structure->m_offset; 542 565 transition->m_dictionaryKind = kind; 543 transition->pin ();566 transition->pinAndPreventTransitions(); 544 567 545 568 transition->checkOffsetConsistency(); … … 604 627 transition->m_offset = structure->m_offset; 605 628 transition->m_preventExtensions = true; 606 transition->pin ();629 transition->pinAndPreventTransitions(); 607 630 608 631 transition->checkOffsetConsistency(); … … 753 776 materializePropertyMapIfNecessaryForPinning(vm, deferGC); 754 777 755 pin ();778 pinAndPreventTransitions(); 756 779 757 780 return putSpecificValue(vm, propertyName, attributes, specificValue); … … 766 789 materializePropertyMapIfNecessaryForPinning(vm, deferGC); 767 790 768 pin ();791 pinAndPreventTransitions(); 769 792 return remove(propertyName); 770 793 } … … 774 797 ASSERT(propertyTable()); 775 798 m_isPinnedPropertyTable = true; 799 } 800 801 void Structure::pinAndPreventTransitions() 802 { 803 pin(); 776 804 clearPreviousID(); 777 805 m_nameInPrevious.clear(); -
trunk/Source/JavaScriptCore/runtime/Structure.h
r167452 r167501 138 138 void setPrototypeWithoutTransition(VM& vm, JSValue prototype) { m_prototype.set(vm, this, prototype); } 139 139 140 bool hasDeletedOffsets() const; 141 140 142 bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; } 141 143 bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; } … … 412 414 413 415 WriteBarrier<PropertyTable>& propertyTable(); 416 const WriteBarrier<PropertyTable>& propertyTable() const; 414 417 PropertyTable* takePropertyTableOrCloneIfPinned(VM&, Structure* owner); 415 418 PropertyTable* copyPropertyTable(VM&, Structure* owner); … … 458 461 459 462 void pin(); 463 void pinAndPreventTransitions(); 460 464 461 465 Structure* previous() const … … 513 517 ConcurrentJITLock m_lock; 514 518 519 static const unsigned s_maxForgivenDeletes = 5; 520 unsigned m_forgivenDeletes; 521 515 522 unsigned m_dictionaryKind : 2; 516 523 bool m_isPinnedPropertyTable : 1; -
trunk/Source/JavaScriptCore/runtime/StructureInlines.h
r165676 r167501 218 218 } 219 219 220 ALWAYS_INLINE WriteBarrier<PropertyTable>& Structure::propertyTable() 220 inline bool Structure::hasDeletedOffsets() const 221 { 222 // If we had deleted anything then we would have pinned our property table. 223 if (!propertyTable()) 224 return false; 225 return propertyTable()->hasDeletedOffset(); 226 } 227 228 inline WriteBarrier<PropertyTable>& Structure::propertyTable() 229 { 230 return const_cast<WriteBarrier<PropertyTable>&>(static_cast<const Structure*>(this)->propertyTable()); 231 } 232 233 inline const WriteBarrier<PropertyTable>& Structure::propertyTable() const 221 234 { 222 235 ASSERT(!globalObject() || !globalObject()->vm().heap.isCollecting()); … … 240 253 return true; 241 254 242 RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == propertyTable->propertyStorageSize());243 255 unsigned totalSize = propertyTable->propertyStorageSize(); 256 RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == totalSize); 244 257 RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset)); 245 258
Note: See TracChangeset
for help on using the changeset viewer.