Changeset 54265 in webkit
- Timestamp:
- Feb 2, 2010 5:13:47 PM (14 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r54263 r54265 1 2010-02-02 Oliver Hunt <oliver@apple.com> 2 3 Reviewed by Geoffrey Garen. 4 5 Crash in CollectorBitmap::get at nbcolympics.com 6 https://bugs.webkit.org/show_bug.cgi?id=34504 7 8 This was caused by the use of m_offset to determine the offset of 9 a new property into the property storage. This patch corrects 10 the effected cases by incorporating the anonymous slot count. It 11 also removes the duplicate copy of anonymous slot count from the 12 property table as keeping this up to date merely increased the 13 chance of a mismatch. Finally I've added a large number of 14 assertions in an attempt to prevent such a bug from happening 15 again. 16 17 With the new assertions in place the existing anonymous slot tests 18 all fail without the m_offset fixes. 19 20 * runtime/PropertyMapHashTable.h: 21 * runtime/Structure.cpp: 22 (JSC::Structure::materializePropertyMap): 23 (JSC::Structure::addPropertyTransitionToExistingStructure): 24 (JSC::Structure::addPropertyTransition): 25 (JSC::Structure::removePropertyTransition): 26 (JSC::Structure::flattenDictionaryStructure): 27 (JSC::Structure::addPropertyWithoutTransition): 28 (JSC::Structure::removePropertyWithoutTransition): 29 (JSC::Structure::copyPropertyTable): 30 (JSC::Structure::get): 31 (JSC::Structure::put): 32 (JSC::Structure::remove): 33 (JSC::Structure::insertIntoPropertyMapHashTable): 34 (JSC::Structure::createPropertyMapHashTable): 35 (JSC::Structure::rehashPropertyMapHashTable): 36 (JSC::Structure::checkConsistency): 37 1 38 2010-02-02 Steve Falkenburg <sfalken@apple.com> 2 39 -
trunk/JavaScriptCore/runtime/PropertyMapHashTable.h
r48403 r54265 62 62 unsigned keyCount; 63 63 unsigned deletedSentinelCount; 64 unsigned anonymousSlotCount;65 64 unsigned lastIndexUsed; 66 65 Vector<unsigned>* deletedOffsets; -
trunk/JavaScriptCore/runtime/Structure.cpp
r54129 r54265 273 273 rehashPropertyMapHashTable(sizeForKeyCount(m_offset + 1)); // This could be made more efficient by combining with the copy above. 274 274 } 275 276 m_propertyTable->anonymousSlotCount = m_anonymousSlotCount; 275 277 276 for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) { 278 277 structure = structures[i]; 279 278 structure->m_nameInPrevious->ref(); 280 PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);279 PropertyMapEntry entry(structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed); 281 280 insertIntoPropertyMapHashTable(entry); 282 281 } … … 344 343 if (Structure* existingTransition = structure->table.get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) { 345 344 ASSERT(existingTransition->m_offset != noOffset); 346 offset = existingTransition->m_offset; 345 offset = existingTransition->m_offset + existingTransition->m_anonymousSlotCount; 346 ASSERT(offset >= structure->m_anonymousSlotCount); 347 ASSERT(structure->m_anonymousSlotCount == existingTransition->m_anonymousSlotCount); 347 348 return existingTransition; 348 349 } … … 364 365 ASSERT(structure != transition); 365 366 offset = transition->put(propertyName, attributes, specificValue); 367 ASSERT(offset >= structure->m_anonymousSlotCount); 368 ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount); 366 369 if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) 367 370 transition->growPropertyStorageCapacity(); … … 382 385 383 386 if (structure->m_propertyTable) { 384 ASSERT(structure->m_propertyTable->anonymousSlotCount == structure->m_anonymousSlotCount);385 387 if (structure->m_isPinnedPropertyTable) 386 388 transition->m_propertyTable = structure->copyPropertyTable(); … … 397 399 398 400 offset = transition->put(propertyName, attributes, specificValue); 401 ASSERT(offset >= structure->m_anonymousSlotCount); 402 ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount); 399 403 if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) 400 404 transition->growPropertyStorageCapacity(); 401 405 402 transition->m_offset = offset ;406 transition->m_offset = offset - structure->m_anonymousSlotCount; 403 407 ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount()); 404 408 structure->table.add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue); … … 413 417 414 418 offset = transition->remove(propertyName); 419 ASSERT(offset >= structure->m_anonymousSlotCount); 420 ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount); 415 421 416 422 return transition.release(); … … 530 536 // reorder the storage, so we have to copy the current values out 531 537 Vector<JSValue> values(propertyCount); 532 ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount); 533 unsigned anonymousSlotCount = m_propertyTable->anonymousSlotCount; 538 unsigned anonymousSlotCount = m_anonymousSlotCount; 534 539 for (unsigned i = 0; i < propertyCount; i++) { 535 540 PropertyMapEntry* entry = sortedPropertyEntries[i]; … … 566 571 567 572 size_t offset = put(propertyName, attributes, specificValue); 573 ASSERT(offset >= m_anonymousSlotCount); 568 574 if (propertyStorageSize() > propertyStorageCapacity()) 569 575 growPropertyStorageCapacity(); … … 580 586 m_isPinnedPropertyTable = true; 581 587 size_t offset = remove(propertyName); 588 ASSERT(offset >= m_anonymousSlotCount); 582 589 return offset; 583 590 } … … 621 628 if (!m_propertyTable) 622 629 return 0; 623 624 ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount); 630 625 631 size_t tableSize = PropertyMapHashTable::allocationSize(m_propertyTable->size); 626 632 PropertyMapHashTable* newTable = static_cast<PropertyMapHashTable*>(fastMalloc(tableSize)); … … 637 643 newTable->deletedOffsets = new Vector<unsigned>(*m_propertyTable->deletedOffsets); 638 644 639 newTable->anonymousSlotCount = m_propertyTable->anonymousSlotCount;640 645 return newTable; 641 646 } … … 660 665 attributes = m_propertyTable->entries()[entryIndex - 1].attributes; 661 666 specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue; 667 ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount); 662 668 return m_propertyTable->entries()[entryIndex - 1].offset; 663 669 } … … 683 689 attributes = m_propertyTable->entries()[entryIndex - 1].attributes; 684 690 specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue; 691 ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount); 685 692 return m_propertyTable->entries()[entryIndex - 1].offset; 686 693 } … … 764 771 if (!m_propertyTable) 765 772 createPropertyMapHashTable(); 766 ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount);767 773 768 774 // FIXME: Consider a fast case for tables with no deleted sentinels. … … 832 838 m_propertyTable->deletedOffsets->removeLast(); 833 839 } else 834 newOffset = m_propertyTable->keyCount + m_ propertyTable->anonymousSlotCount;840 newOffset = m_propertyTable->keyCount + m_anonymousSlotCount; 835 841 m_propertyTable->entries()[entryIndex - 1].offset = newOffset; 836 842 843 ASSERT(newOffset >= m_anonymousSlotCount); 837 844 ++m_propertyTable->keyCount; 838 845 … … 859 866 if (!m_propertyTable) 860 867 return notFound; 861 862 ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount); 868 863 869 #if DUMP_PROPERTYMAP_STATS 864 870 ++numProbes; … … 899 905 900 906 size_t offset = m_propertyTable->entries()[entryIndex - 1].offset; 907 ASSERT(offset >= m_anonymousSlotCount); 901 908 902 909 key->deref(); … … 924 931 { 925 932 ASSERT(m_propertyTable); 926 927 ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount); 933 ASSERT(entry.offset >= m_anonymousSlotCount); 928 934 unsigned i = entry.key->existingHash(); 929 935 unsigned k = 0; … … 975 981 m_propertyTable->size = newTableSize; 976 982 m_propertyTable->sizeMask = newTableSize - 1; 977 m_propertyTable->anonymousSlotCount = m_anonymousSlotCount;978 983 979 984 checkConsistency(); … … 1005 1010 m_propertyTable->size = newTableSize; 1006 1011 m_propertyTable->sizeMask = newTableSize - 1; 1007 m_propertyTable->anonymousSlotCount = oldTable->anonymousSlotCount;1008 1012 1009 1013 unsigned lastIndexUsed = 0; … … 1135 1139 ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[c].attributes & DontEnum)); 1136 1140 UString::Rep* rep = m_propertyTable->entries()[c].key; 1141 ASSERT(m_propertyTable->entries()[c].offset >= m_anonymousSlotCount); 1137 1142 if (!rep) 1138 1143 continue; -
trunk/JavaScriptCore/runtime/Structure.h
r54141 r54265 205 205 206 206 uint32_t m_propertyStorageCapacity; 207 208 // m_offset does not account for anonymous slots 207 209 signed char m_offset; 208 210
Note: See TracChangeset
for help on using the changeset viewer.