Changeset 37370 in webkit for trunk/JavaScriptCore
- Timestamp:
- Oct 6, 2008, 10:43:06 PM (17 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r37366 r37370 1 2008-10-06 Sam Weinig <[email protected]> 2 3 Reviewed by Cameron Zwarich. 4 5 Fix for https://bugs.webkit.org/show_bug.cgi?id=21415 6 Improve the division between PropertyStorageArray and PropertyMap 7 8 - Rework ProperyMap to store offsets in the value so that they don't 9 change when rehashing. This allows us not to have to keep the 10 PropertyStorageArray in sync and thus not have to pass it in. 11 - Rename PropertyMap::getOffset -> PropertyMap::get since put/remove 12 now also return offsets. 13 - A Vector of deleted offsets is now needed since the storage is out of 14 band. 15 16 1% win on SunSpider. Wash on V8 suite. 17 18 * JavaScriptCore.exp: 19 * VM/CTI.cpp: 20 (JSC::transitionWillNeedStorageRealloc): 21 * VM/Machine.cpp: 22 (JSC::Machine::privateExecute): 23 Transition logic can be greatly simplified by the fact that 24 the storage capacity is always known, and is correct for the 25 inline case. 26 * kjs/JSObject.cpp: 27 (JSC::JSObject::put): Rename getOffset -> get. 28 (JSC::JSObject::deleteProperty): Ditto. 29 (JSC::JSObject::getPropertyAttributes): Ditto. 30 (JSC::JSObject::removeDirect): Use returned offset to 31 clear the value in the PropertyNameArray. 32 (JSC::JSObject::allocatePropertyStorage): Add assert. 33 * kjs/JSObject.h: 34 (JSC::JSObject::getDirect): Rename getOffset -> get 35 (JSC::JSObject::getDirectLocation): Rename getOffset -> get 36 (JSC::JSObject::putDirect): Use propertyStorageCapacity to determine whether 37 or not to resize. Also, since put now returns an offset (and thus 38 addPropertyTransition does also) setting of the PropertyStorageArray is 39 now done here. 40 (JSC::JSObject::transitionTo): 41 * kjs/PropertyMap.cpp: 42 (JSC::PropertyMap::checkConsistency): PropertyStorageArray is no longer 43 passed in. 44 (JSC::PropertyMap::operator=): Copy the delete offsets vector. 45 (JSC::PropertyMap::put): Instead of setting the PropertyNameArray 46 explicitly, return the offset where the value should go. 47 (JSC::PropertyMap::remove): Instead of removing from the PropertyNameArray 48 explicitly, return the offset where the value should be removed. 49 (JSC::PropertyMap::get): Switch to using the stored offset, instead 50 of the implicit one. 51 (JSC::PropertyMap::insert): 52 (JSC::PropertyMap::expand): This is never called when m_table is null, 53 so remove that branch and add it as an assertion. 54 (JSC::PropertyMap::createTable): Consistency checks no longer take 55 a PropertyNameArray. 56 (JSC::PropertyMap::rehash): No need to rehash the PropertyNameArray 57 now that it is completely out of band. 58 * kjs/PropertyMap.h: 59 (JSC::PropertyMapEntry::PropertyMapEntry): Store offset into PropertyNameArray. 60 (JSC::PropertyMap::get): Switch to using the stored offset, instead 61 of the implicit one. 62 * kjs/StructureID.cpp: 63 (JSC::StructureID::StructureID): Initialize the propertyStorageCapacity to 64 JSObject::inlineStorageCapacity. 65 (JSC::StructureID::growPropertyStorageCapacity): Grow the storage capacity as 66 described below. 67 (JSC::StructureID::addPropertyTransition): Copy the storage capacity. 68 (JSC::StructureID::toDictionaryTransition): Ditto. 69 (JSC::StructureID::changePrototypeTransition): Ditto. 70 (JSC::StructureID::getterSetterTransition): Ditto. 71 * kjs/StructureID.h: 72 (JSC::StructureID::propertyStorageCapacity): Add propertyStorageCapacity 73 which is the current capacity for the JSObjects PropertyStorageArray. 74 It starts at the JSObject::inlineStorageCapacity (currently 2), then 75 when it first needs to be resized moves to the JSObject::nonInlineBaseStorageCapacity 76 (currently 16), and after that doubles each time. 77 1 78 2008-10-06 Cameron Zwarich <[email protected]> 2 79 -
trunk/JavaScriptCore/JavaScriptCore.exp
r37349 r37370 109 109 __ZN3JSC11ProfileNode4sortEPFbRKN3WTF6RefPtrIS0_EES5_E 110 110 __ZN3JSC11ProgramNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm16EEERKNS_10SourceCodeEji 111 __ZN3JSC11PropertyMap3 putERKNS_10IdentifierEPNS_7JSValueEjbPNS_8JSObjectERNS_15PutPropertySlotERPS5_112 __ZN3JSC11PropertyMap 9getOffsetERKNS_10IdentifierERj111 __ZN3JSC11PropertyMap3getERKNS_10IdentifierERj 112 __ZN3JSC11PropertyMap3putERKNS_10IdentifierEj 113 113 __ZN3JSC11PropertyMapD1Ev 114 __ZN3JSC11StructureID21addPropertyTransitionEPS0_RKNS_10IdentifierE PNS_7JSValueEjPNS_8JSObjectERNS_15PutPropertySlotERPS6_114 __ZN3JSC11StructureID21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm 115 115 __ZN3JSC11StructureID21clearEnumerationCacheEv 116 116 __ZN3JSC11StructureID24fromDictionaryTransitionEPS0_ 117 117 __ZN3JSC11StructureID25changePrototypeTransitionEPS0_PNS_7JSValueE 118 __ZN3JSC11StructureID27growPropertyStorageCapacityEv 118 119 __ZN3JSC11StructureIDC1EPNS_7JSValueERKNS_8TypeInfoE 119 120 __ZN3JSC11StructureIDD1Ev -
trunk/JavaScriptCore/VM/CTI.cpp
r37366 r37370 2744 2744 static JSValue* SFX_CALL transitionObject(StructureID* newStructureID, size_t cachedOffset, JSObject* baseObject, JSValue* value) 2745 2745 { 2746 StructureID* oldStructureID = newStructureID->previousID();2747 2748 2746 baseObject->transitionTo(newStructureID); 2749 2750 if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)2751 baseObject->allocatePropertyStorage(oldStructureID->propertyMap().storageSize(), oldStructureID->propertyMap().size());2752 2753 2747 baseObject->putDirectOffset(cachedOffset, value); 2754 2748 return baseObject; … … 2759 2753 static inline bool transitionWillNeedStorageRealloc(StructureID* oldStructureID, StructureID* newStructureID) 2760 2754 { 2761 if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity) 2762 return true; 2763 2764 if (oldStructureID->propertyMap().storageSize() < JSObject::inlineStorageCapacity) 2765 return false; 2766 2767 if (oldStructureID->propertyMap().size() != newStructureID->propertyMap().size()) 2768 return true; 2769 2770 return false; 2755 return oldStructureID->propertyStorageCapacity() != newStructureID->propertyStorageCapacity(); 2771 2756 } 2772 2757 -
trunk/JavaScriptCore/VM/Machine.cpp
r37366 r37370 2722 2722 2723 2723 baseObject->transitionTo(newStructureID); 2724 if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)2725 baseObject->allocatePropertyStorage(oldStructureID->propertyMap().storageSize(), oldStructureID->propertyMap().size());2726 2724 2727 2725 int value = vPC[3].u.operand; -
trunk/JavaScriptCore/kjs/JSObject.cpp
r37337 r37370 135 135 136 136 unsigned attributes; 137 if ((m_structureID->propertyMap().get Offset(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)137 if ((m_structureID->propertyMap().get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly) 138 138 return; 139 139 … … 201 201 { 202 202 unsigned attributes; 203 if (m_structureID->propertyMap().get Offset(propertyName, attributes) != WTF::notFound) {203 if (m_structureID->propertyMap().get(propertyName, attributes) != WTF::notFound) { 204 204 if ((attributes & DontDelete)) 205 205 return false; … … 413 413 bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const 414 414 { 415 if (m_structureID->propertyMap().get Offset(propertyName, attributes) != WTF::notFound)415 if (m_structureID->propertyMap().get(propertyName, attributes) != WTF::notFound) 416 416 return true; 417 417 … … 469 469 void JSObject::removeDirect(const Identifier& propertyName) 470 470 { 471 size_t offset; 471 472 if (m_structureID->isDictionary()) { 472 m_structureID->propertyMap().remove(propertyName, m_propertyStorage); 473 m_structureID->clearEnumerationCache(); 473 offset = m_structureID->propertyMap().remove(propertyName); 474 if (offset != WTF::notFound) { 475 m_propertyStorage[offset] = jsUndefined(); 476 m_structureID->clearEnumerationCache(); 477 } 474 478 return; 475 479 } 476 480 477 481 RefPtr<StructureID> structureID = StructureID::toDictionaryTransition(m_structureID); 478 structureID->propertyMap().remove(propertyName, m_propertyStorage); 482 offset = structureID->propertyMap().remove(propertyName); 483 if (offset != WTF::notFound) 484 m_propertyStorage[offset] = jsUndefined(); 479 485 setStructureID(structureID.release()); 480 486 } … … 501 507 void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize) 502 508 { 509 ASSERT(newSize > oldSize); 510 503 511 JSValue** oldPropertStorage = m_propertyStorage; 504 512 m_propertyStorage = new JSValue*[newSize]; -
trunk/JavaScriptCore/kjs/JSObject.h
r37337 r37370 123 123 JSValue* getDirect(const Identifier& propertyName) const 124 124 { 125 size_t offset = m_structureID->propertyMap().get Offset(propertyName);125 size_t offset = m_structureID->propertyMap().get(propertyName); 126 126 return offset != WTF::notFound ? m_propertyStorage[offset] : 0; 127 127 } … … 129 129 JSValue** getDirectLocation(const Identifier& propertyName) 130 130 { 131 size_t offset = m_structureID->propertyMap().get Offset(propertyName);131 size_t offset = m_structureID->propertyMap().get(propertyName); 132 132 return offset != WTF::notFound ? locationForOffset(offset) : 0; 133 133 } … … 135 135 JSValue** getDirectLocation(const Identifier& propertyName, unsigned& attributes) 136 136 { 137 size_t offset = m_structureID->propertyMap().get Offset(propertyName, attributes);137 size_t offset = m_structureID->propertyMap().get(propertyName, attributes); 138 138 return offset != WTF::notFound ? locationForOffset(offset) : 0; 139 139 } … … 179 179 180 180 static const size_t inlineStorageCapacity = 2; 181 static const size_t nonInlineBaseStorageCapacity = 16; 181 182 182 183 static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(ObjectType)); } … … 365 366 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); 366 367 367 if (m_structureID->isDictionary()) { 368 unsigned currentAttributes; 369 size_t offset = m_structureID->propertyMap().getOffset(propertyName, currentAttributes); 370 if (offset != WTF::notFound) { 371 if (checkReadOnly && currentAttributes & ReadOnly) 372 return; 373 m_propertyStorage[offset] = value; 374 slot.setExistingProperty(this, offset); 375 return; 376 } 377 378 if (m_structureID->propertyMap().storageSize() == inlineStorageCapacity) 379 allocatePropertyStorage(m_structureID->propertyMap().storageSize(), m_structureID->propertyMap().size()); 380 m_structureID->propertyMap().put(propertyName, value, attributes, checkReadOnly, this, slot, m_propertyStorage); 381 m_structureID->clearEnumerationCache(); 382 return; 383 } 368 if (m_structureID->isDictionary()) { 369 unsigned currentAttributes; 370 size_t offset = m_structureID->propertyMap().get(propertyName, currentAttributes); 371 if (offset != WTF::notFound) { 372 if (checkReadOnly && currentAttributes & ReadOnly) 373 return; 374 m_propertyStorage[offset] = value; 375 slot.setExistingProperty(this, offset); 376 return; 377 } 378 379 size_t currentCapacity = m_structureID->propertyStorageCapacity(); 380 offset = m_structureID->propertyMap().put(propertyName, attributes); 381 if (m_structureID->propertyMap().storageSize() > m_structureID->propertyStorageCapacity()) { 382 m_structureID->growPropertyStorageCapacity(); 383 allocatePropertyStorage(currentCapacity, m_structureID->propertyStorageCapacity()); 384 } 385 386 m_propertyStorage[offset] = value; 387 slot.setNewProperty(this, offset); 388 m_structureID->clearEnumerationCache(); 389 return; 390 } 384 391 385 392 unsigned currentAttributes; 386 size_t offset = m_structureID->propertyMap().get Offset(propertyName, currentAttributes);393 size_t offset = m_structureID->propertyMap().get(propertyName, currentAttributes); 387 394 if (offset != WTF::notFound) { 388 395 if (checkReadOnly && currentAttributes & ReadOnly) … … 393 400 } 394 401 395 if (m_structureID->propertyMap().storageSize() == inlineStorageCapacity) 396 allocatePropertyStorage(m_structureID->propertyMap().storageSize(), m_structureID->propertyMap().size()); 397 398 RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName, value, attributes, this, slot, m_propertyStorage); 399 slot.setWasTransition(true); 400 setStructureID(structureID.release()); 402 size_t currentCapacity = m_structureID->propertyStorageCapacity(); 403 RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName, attributes, offset); 404 if (currentCapacity != structureID->propertyStorageCapacity()) 405 allocatePropertyStorage(currentCapacity, structureID->propertyStorageCapacity()); 406 407 ASSERT(offset < structureID->propertyStorageCapacity()); 408 m_propertyStorage[offset] = value; 409 slot.setNewProperty(this, offset); 410 slot.setWasTransition(true); 411 setStructureID(structureID.release()); 401 412 } 402 413 403 414 inline void JSObject::transitionTo(StructureID* newStructureID) 404 415 { 405 StructureID::transitionTo(m_structureID, newStructureID, this); 416 if (m_structureID->propertyStorageCapacity() != newStructureID->propertyStorageCapacity()) 417 allocatePropertyStorage(m_structureID->propertyStorageCapacity(), newStructureID->propertyStorageCapacity()); 406 418 setStructureID(newStructureID); 407 419 } -
trunk/JavaScriptCore/kjs/PropertyMap.cpp
r37321 r37370 78 78 #if !DO_PROPERTYMAP_CONSTENCY_CHECK 79 79 80 inline void PropertyMap::checkConsistency( PropertyStorage&)80 inline void PropertyMap::checkConsistency() 81 81 { 82 82 } … … 98 98 } 99 99 100 m_deletedOffsets = other.m_deletedOffsets; 100 101 m_getterSetterFlag = other.m_getterSetterFlag; 101 102 return *this; … … 115 116 } 116 117 117 size_t PropertyMap::put(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage)118 size_t PropertyMap::put(const Identifier& propertyName, unsigned attributes) 118 119 { 119 120 ASSERT(!propertyName.isNull()); 120 ASSERT( value);121 122 checkConsistency( propertyStorage);121 ASSERT(get(propertyName) == WTF::notFound); 122 123 checkConsistency(); 123 124 124 125 UString::Rep* rep = propertyName._ustring.rep(); 125 126 126 127 if (!m_table) 127 expand(propertyStorage);128 createTable(); 128 129 129 130 // FIXME: Consider a fast case for tables with no deleted sentinels. … … 143 144 break; 144 145 145 if (m_table->entries()[entryIndex - 1].key == rep) { 146 if (checkReadOnly && (m_table->entries()[entryIndex - 1].attributes & ReadOnly)) 147 return WTF::notFound; 148 // Put a new value in an existing hash table entry. 149 propertyStorage[entryIndex - 2] = value; 150 // Attributes are intentionally not updated. 151 slot.setExistingProperty(slotBase, entryIndex - 2); 152 return entryIndex - 2; 153 } else if (entryIndex == deletedSentinelIndex) { 146 if (entryIndex == deletedSentinelIndex) { 154 147 // If we find a deleted-element sentinel, remember it for use later. 155 148 if (!foundDeletedElement) { … … 194 187 m_table->entries()[entryIndex - 1].attributes = attributes; 195 188 m_table->entries()[entryIndex - 1].index = ++m_table->lastIndexUsed; 189 190 unsigned newOffset; 191 if (!m_deletedOffsets.isEmpty()) { 192 newOffset = m_deletedOffsets.last(); 193 m_deletedOffsets.removeLast(); 194 } else 195 newOffset = m_table->keyCount + m_table->deletedSentinelCount; 196 m_table->entries()[entryIndex - 1].offset = newOffset; 197 196 198 ++m_table->keyCount; 197 199 198 propertyStorage[entryIndex - 2] = value;199 200 200 if ((m_table->keyCount + m_table->deletedSentinelCount) * 2 >= m_table->size) 201 expand(propertyStorage); 202 203 checkConsistency(propertyStorage); 204 slot.setNewProperty(slotBase, entryIndex - 2); 205 return entryIndex - 2; 206 } 207 208 void PropertyMap::remove(const Identifier& propertyName, PropertyStorage& propertyStorage) 201 expand(); 202 203 checkConsistency(); 204 return newOffset; 205 } 206 207 size_t PropertyMap::remove(const Identifier& propertyName) 209 208 { 210 209 ASSERT(!propertyName.isNull()); 211 210 212 checkConsistency( propertyStorage);211 checkConsistency(); 213 212 214 213 UString::Rep* rep = propertyName._ustring.rep(); 215 214 216 215 if (!m_table) 217 return; 216 return WTF::notFound; 217 218 218 219 219 #if DUMP_PROPERTYMAP_STATS … … 230 230 entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 231 231 if (entryIndex == emptyEntryIndex) 232 return ;232 return WTF::notFound; 233 233 234 234 key = m_table->entries()[entryIndex - 1].key; … … 253 253 // the entry so we can iterate all the entries as needed. 254 254 m_table->entryIndices[i & m_table->sizeMask] = deletedSentinelIndex; 255 256 size_t offset = m_table->entries()[entryIndex - 1].offset; 257 255 258 key->deref(); 256 259 m_table->entries()[entryIndex - 1].key = 0; 257 260 m_table->entries()[entryIndex - 1].attributes = 0; 258 259 propertyStorage[entryIndex - 2] = jsUndefined();261 m_table->entries()[entryIndex - 1].offset = 0; 262 m_deletedOffsets.append(offset); 260 263 261 264 ASSERT(m_table->keyCount >= 1); … … 264 267 265 268 if (m_table->deletedSentinelCount * 4 >= m_table->size) 266 rehash(propertyStorage); 267 268 checkConsistency(propertyStorage); 269 } 270 271 size_t PropertyMap::getOffset(const Identifier& propertyName, unsigned& attributes) 269 rehash(); 270 271 checkConsistency(); 272 return offset; 273 } 274 275 size_t PropertyMap::get(const Identifier& propertyName, unsigned& attributes) 272 276 { 273 277 ASSERT(!propertyName.isNull()); … … 290 294 if (rep == m_table->entries()[entryIndex - 1].key) { 291 295 attributes = m_table->entries()[entryIndex - 1].attributes; 292 return entryIndex - 2;296 return m_table->entries()[entryIndex - 1].offset; 293 297 } 294 298 … … 312 316 if (rep == m_table->entries()[entryIndex - 1].key) { 313 317 attributes = m_table->entries()[entryIndex - 1].attributes; 314 return entryIndex - 2;315 } 316 } 317 } 318 319 void PropertyMap::insert(const Entry& entry , JSValue* value, PropertyStorage& propertyStorage)318 return m_table->entries()[entryIndex - 1].offset; 319 } 320 } 321 } 322 323 void PropertyMap::insert(const Entry& entry) 320 324 { 321 325 ASSERT(m_table); … … 351 355 m_table->entries()[entryIndex - 1] = entry; 352 356 353 propertyStorage[entryIndex - 2] = value;354 355 357 ++m_table->keyCount; 356 358 } 357 359 358 void PropertyMap::expand(PropertyStorage& propertyStorage) 359 { 360 if (!m_table) 361 createTable(propertyStorage); 362 else 363 rehash(m_table->size * 2, propertyStorage); 364 } 365 366 void PropertyMap::rehash(PropertyStorage& propertyStorage) 360 void PropertyMap::expand() 367 361 { 368 362 ASSERT(m_table); 369 ASSERT(m_table->size); 370 rehash(m_table->size, propertyStorage); 371 } 372 373 void PropertyMap::createTable(PropertyStorage& propertyStorage) 363 rehash(m_table->size * 2); 364 } 365 366 void PropertyMap::createTable() 374 367 { 375 368 const unsigned newTableSize = 16; … … 377 370 ASSERT(!m_table); 378 371 379 checkConsistency( propertyStorage);372 checkConsistency(); 380 373 381 374 m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize))); … … 383 376 m_table->sizeMask = newTableSize - 1; 384 377 385 checkConsistency( propertyStorage);386 } 387 388 void PropertyMap::rehash( unsigned newTableSize, PropertyStorage& propertyStorage)378 checkConsistency(); 379 } 380 381 void PropertyMap::rehash() 389 382 { 390 383 ASSERT(m_table); 391 392 checkConsistency(propertyStorage); 384 ASSERT(m_table->size); 385 rehash(m_table->size); 386 } 387 388 void PropertyMap::rehash(unsigned newTableSize) 389 { 390 ASSERT(m_table); 391 392 checkConsistency(); 393 393 394 394 Table* oldTable = m_table; 395 JSValue** oldPropertStorage = propertyStorage;396 395 397 396 m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize))); 398 397 m_table->size = newTableSize; 399 398 m_table->sizeMask = newTableSize - 1; 400 401 propertyStorage = new JSValue*[m_table->size];402 399 403 400 unsigned lastIndexUsed = 0; … … 406 403 if (oldTable->entries()[i].key) { 407 404 lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed); 408 insert(oldTable->entries()[i] , oldPropertStorage[i - 1], propertyStorage);405 insert(oldTable->entries()[i]); 409 406 } 410 407 } … … 412 409 413 410 fastFree(oldTable); 414 delete [] oldPropertStorage; 415 416 checkConsistency(propertyStorage); 411 412 checkConsistency(); 417 413 } 418 414 … … 486 482 #if DO_PROPERTYMAP_CONSTENCY_CHECK 487 483 488 void PropertyMap::checkConsistency( PropertyStorage& propertyStorage)484 void PropertyMap::checkConsistency() 489 485 { 490 486 if (!m_table) … … 526 522 for (unsigned c = 1; c <= m_table->keyCount + m_table->deletedSentinelCount; ++c) { 527 523 UString::Rep* rep = m_table->entries()[c].key; 528 if (!rep) { 529 ASSERT(propertyStorage[c - 1]->isUndefined()); 524 if (!rep) 530 525 continue; 531 }532 526 ++nonEmptyEntryCount; 533 527 unsigned i = rep->computedHash(); -
trunk/JavaScriptCore/kjs/PropertyMap.h
r37321 r37370 43 43 struct PropertyMapEntry { 44 44 UString::Rep* key; 45 unsigned offset; 45 46 unsigned attributes; 46 47 unsigned index; … … 48 49 PropertyMapEntry(UString::Rep* k, int a) 49 50 : key(k) 51 , offset(0) 50 52 , attributes(a) 51 53 , index(0) … … 95 97 bool isEmpty() { return !m_table; } 96 98 97 size_t put(const Identifier& propertyName, JSValue*, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot&, PropertyStorage&); 98 void remove(const Identifier& propertyName, PropertyStorage&); 99 100 size_t getOffset(const Identifier& propertyName); 101 size_t getOffset(const Identifier& propertyName, unsigned& attributes); 99 size_t get(const Identifier& propertyName); 100 size_t get(const Identifier& propertyName, unsigned& attributes); 101 size_t put(const Identifier& propertyName, unsigned attributes); 102 size_t remove(const Identifier& propertyName); 102 103 103 104 void getEnumerablePropertyNames(PropertyNameArray&) const; … … 115 116 typedef PropertyMapHashTable Table; 116 117 117 void expand( PropertyStorage&);118 void rehash( PropertyStorage&);119 void rehash(unsigned newTableSize , PropertyStorage&);120 void createTable( PropertyStorage&);118 void expand(); 119 void rehash(); 120 void rehash(unsigned newTableSize); 121 void createTable(); 121 122 122 void insert(const Entry& , JSValue*, PropertyStorage&);123 void insert(const Entry&); 123 124 124 void checkConsistency( PropertyStorage&);125 void checkConsistency(); 125 126 126 127 Table* m_table; 128 Vector<unsigned> m_deletedOffsets; 127 129 bool m_getterSetterFlag : 1; 128 130 }; … … 134 136 } 135 137 136 inline size_t PropertyMap::get Offset(const Identifier& propertyName)138 inline size_t PropertyMap::get(const Identifier& propertyName) 137 139 { 138 140 ASSERT(!propertyName.isNull()); … … 154 156 155 157 if (rep == m_table->entries()[entryIndex - 1].key) 156 return entryIndex - 2;158 return m_table->entries()[entryIndex - 1].offset; 157 159 158 160 #if DUMP_PROPERTYMAP_STATS … … 174 176 175 177 if (rep == m_table->entries()[entryIndex - 1].key) 176 return entryIndex - 2;178 return m_table->entries()[entryIndex - 1].offset; 177 179 } 178 180 } -
trunk/JavaScriptCore/kjs/StructureID.cpp
r37321 r37370 45 45 , m_nameInPrevious(0) 46 46 , m_transitionCount(0) 47 , m_propertyStorageCapacity(JSObject::inlineStorageCapacity) 47 48 , m_cachedTransistionOffset(WTF::notFound) 48 49 { … … 103 104 } 104 105 105 void StructureID::transitionTo(StructureID* oldStructureID, StructureID* newStructureID, JSObject* slotBase) 106 { 107 if (!slotBase->usingInlineStorage() && oldStructureID->m_propertyMap.size() != newStructureID->m_propertyMap.size()) 108 slotBase->allocatePropertyStorage(oldStructureID->m_propertyMap.size(), newStructureID->m_propertyMap.size()); 109 } 110 111 PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, JSValue* value, unsigned attributes, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage) 106 void StructureID::growPropertyStorageCapacity() 107 { 108 if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity) 109 m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity; 110 else 111 m_propertyStorageCapacity *= 2; 112 } 113 114 PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, unsigned attributes, size_t& offset) 112 115 { 113 116 ASSERT(!structureID->m_isDictionary); … … 115 118 116 119 if (StructureID* existingTransition = structureID->m_transitionTable.get(make_pair(propertyName.ustring().rep(), attributes))) { 117 if (!slotBase->usingInlineStorage() && structureID->m_propertyMap.size() != existingTransition->m_propertyMap.size()) 118 slotBase->allocatePropertyStorage(structureID->m_propertyMap.size(), existingTransition->m_propertyMap.size()); 119 120 size_t offset = existingTransition->cachedTransistionOffset(); 120 offset = existingTransition->cachedTransistionOffset(); 121 121 ASSERT(offset != WTF::notFound); 122 propertyStorage[offset] = value;123 slot.setNewProperty(slotBase, offset);124 125 122 return existingTransition; 126 123 } … … 128 125 if (structureID->m_transitionCount > s_maxTransitionLength) { 129 126 RefPtr<StructureID> transition = toDictionaryTransition(structureID); 130 transition->m_propertyMap.put(propertyName, value, attributes, false, slotBase, slot, propertyStorage); 127 offset = transition->m_propertyMap.put(propertyName, attributes); 128 if (transition->m_propertyMap.storageSize() > transition->propertyStorageCapacity()) 129 transition->growPropertyStorageCapacity(); 131 130 return transition.release(); 132 131 } … … 139 138 transition->m_transitionCount = structureID->m_transitionCount + 1; 140 139 transition->m_propertyMap = structureID->m_propertyMap; 141 142 size_t offset = transition->m_propertyMap.put(propertyName, value, attributes, false, slotBase, slot, propertyStorage); 140 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; 141 142 offset = transition->m_propertyMap.put(propertyName, attributes); 143 if (transition->m_propertyMap.storageSize() > transition->propertyStorageCapacity()) 144 transition->growPropertyStorageCapacity(); 145 143 146 transition->setCachedTransistionOffset(offset); 144 147 … … 154 157 transition->m_isDictionary = true; 155 158 transition->m_propertyMap = structureID->m_propertyMap; 159 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; 156 160 return transition.release(); 157 161 } … … 173 177 transition->m_transitionCount = structureID->m_transitionCount + 1; 174 178 transition->m_propertyMap = structureID->m_propertyMap; 179 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; 175 180 return transition.release(); 176 181 } … … 181 186 transition->m_transitionCount = structureID->m_transitionCount + 1; 182 187 transition->m_propertyMap = structureID->m_propertyMap; 188 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; 183 189 return transition.release(); 184 190 } -
trunk/JavaScriptCore/kjs/StructureID.h
r37321 r37370 84 84 85 85 static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype); 86 static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, JSValue*, unsigned attributes, JSObject* slotBase, PutPropertySlot&, PropertyStorage&);86 static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, unsigned attributes, size_t& offset); 87 87 static PassRefPtr<StructureID> getterSetterTransition(StructureID*); 88 88 static PassRefPtr<StructureID> toDictionaryTransition(StructureID*); … … 119 119 size_t cachedTransistionOffset() const { return m_cachedTransistionOffset; } 120 120 121 void growPropertyStorageCapacity(); 122 size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; } 123 121 124 void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*); 122 125 void clearEnumerationCache(); 123 124 static void transitionTo(StructureID* oldStructureID, StructureID* newStructureID, JSObject* slotBase);125 126 126 127 private: … … 149 150 150 151 PropertyMap m_propertyMap; 152 size_t m_propertyStorageCapacity; 151 153 152 154 size_t m_cachedTransistionOffset;
Note:
See TracChangeset
for help on using the changeset viewer.