Changeset 38407 in webkit for trunk/JavaScriptCore/runtime/StructureID.cpp
- Timestamp:
- Nov 14, 2008, 3:36:06 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/StructureID.cpp
r38138 r38407 60 60 static const unsigned tinyMapThreshold = 20; 61 61 62 static const unsigned newTableSize = 16; 63 62 64 #ifndef NDEBUG 63 65 static WTF::RefCountedLeakCounter structureIDCounter("StructureID"); … … 81 83 unsigned numberUsingSingleSlot = 0; 82 84 unsigned numberSingletons = 0; 85 unsigned numberWithPropertyMaps = 0; 83 86 unsigned totalPropertyMapsSize = 0; 84 87 … … 96 99 } 97 100 98 if (structureID->m_propertyTable) 101 if (structureID->m_propertyTable) { 102 ++numberWithPropertyMaps; 99 103 totalPropertyMapsSize += PropertyMapHashTable::allocationSize(structureID->m_propertyTable->size); 104 } 100 105 } 101 106 … … 104 109 printf("Number of StructureIDs that are leaf nodes: %d\n", numberLeaf); 105 110 printf("Number of StructureIDs that singletons: %d\n", numberSingletons); 111 printf("Number of StructureIDs with PropertyMaps: %d\n", numberWithPropertyMaps); 106 112 107 113 printf("Size of a single StructureIDs: %d\n", static_cast<unsigned>(sizeof(StructureID))); … … 122 128 , m_propertyTable(0) 123 129 , m_propertyStorageCapacity(JSObject::inlineStorageCapacity) 124 , m_ cachedTransistionOffset(WTF::notFound)130 , m_offset(WTF::notFound) 125 131 , m_isDictionary(false) 132 , m_isPinnedPropertyTable(false) 126 133 , m_hasGetterSetterProperties(false) 127 134 , m_usingSingleTransitionSlot(true) … … 202 209 shouldIgnoreLeaks = false; 203 210 #endif 211 } 212 213 static bool isPowerOf2(unsigned v) 214 { 215 // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html 216 217 return !(v & (v - 1)) && v; 218 } 219 220 static unsigned nextPowerOf2(unsigned v) 221 { 222 // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html 223 // Devised by Sean Anderson, Sepember 14, 2001 224 225 v--; 226 v |= v >> 1; 227 v |= v >> 2; 228 v |= v >> 4; 229 v |= v >> 8; 230 v |= v >> 16; 231 v++; 232 233 return v; 234 } 235 236 static unsigned sizeForKeyCount(size_t keyCount) 237 { 238 if (keyCount == WTF::notFound) 239 return newTableSize; 240 241 if (keyCount < 8) 242 return newTableSize; 243 244 if (isPowerOf2(keyCount)) 245 return keyCount * 4; 246 247 return nextPowerOf2(keyCount) * 2; 248 } 249 250 void StructureID::materializePropertyMap() 251 { 252 ASSERT(!m_propertyTable); 253 254 Vector<StructureID*, 8> structures; 255 structures.append(this); 256 257 StructureID* structure = this; 258 259 // Search for the last StructureID with a property table. 260 while ((structure = structure->previousID())) { 261 if (structure->m_isPinnedPropertyTable) { 262 ASSERT(structure->m_propertyTable); 263 ASSERT(!structure->m_previous); 264 265 m_propertyTable = structure->copyPropertyTable(); 266 break; 267 } 268 269 structures.append(structure); 270 } 271 272 if (!m_propertyTable) 273 createPropertyMapHashTable(sizeForKeyCount(m_offset + 1)); 274 else { 275 if (sizeForKeyCount(m_offset + 1) > m_propertyTable->size) 276 rehashPropertyMapHashTable(sizeForKeyCount(m_offset + 1)); // This could be made more efficient by combining with the copy above. 277 } 278 279 for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) { 280 structure = structures[i]; 281 structure->m_nameInPrevious->ref(); 282 PropertyMapEntry entry(structure->m_nameInPrevious, structure->m_offset, structure->m_attributesInPrevious, ++m_propertyTable->lastIndexUsed); 283 insertIntoPropertyMapHashTable(entry); 284 } 204 285 } 205 286 … … 267 348 } 268 349 269 PassRefPtr<StructureID> StructureID::addPropertyTransition (StructureID* structureID, const Identifier& propertyName, unsigned attributes, size_t& offset)350 PassRefPtr<StructureID> StructureID::addPropertyTransitionToExistingStructure(StructureID* structureID, const Identifier& propertyName, unsigned attributes, size_t& offset) 270 351 { 271 352 ASSERT(!structureID->m_isDictionary); … … 275 356 StructureID* existingTransition = structureID->m_transitions.singleTransition; 276 357 if (existingTransition && existingTransition->m_nameInPrevious == propertyName.ustring().rep() && existingTransition->m_attributesInPrevious == attributes) { 277 offset = structureID->m_transitions.singleTransition-> cachedTransistionOffset();358 offset = structureID->m_transitions.singleTransition->m_offset; 278 359 ASSERT(offset != WTF::notFound); 279 360 return existingTransition; … … 281 362 } else { 282 363 if (StructureID* existingTransition = structureID->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes))) { 283 offset = existingTransition-> cachedTransistionOffset();364 offset = existingTransition->m_offset; 284 365 ASSERT(offset != WTF::notFound); 285 366 return existingTransition; 286 } 287 } 367 } 368 } 369 370 return 0; 371 } 372 373 PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, unsigned attributes, size_t& offset) 374 { 375 ASSERT(!structureID->m_isDictionary); 376 ASSERT(structureID->typeInfo().type() == ObjectType); 377 ASSERT(structureID->m_deletedOffsets.isEmpty()); 378 ASSERT(!StructureID::addPropertyTransitionToExistingStructure(structureID, propertyName, attributes, offset)); 288 379 289 380 if (structureID->m_transitionCount > s_maxTransitionLength) { … … 301 392 transition->m_attributesInPrevious = attributes; 302 393 transition->m_transitionCount = structureID->m_transitionCount + 1; 303 transition->m_propertyTable = structureID->copyPropertyTable();304 transition->m_deletedOffsets = structureID->m_deletedOffsets;305 394 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; 306 395 transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties; 396 397 if (structureID->m_propertyTable) { 398 if (structureID->m_isPinnedPropertyTable) 399 transition->m_propertyTable = structureID->copyPropertyTable(); 400 else { 401 transition->m_propertyTable = structureID->m_propertyTable; 402 structureID->m_propertyTable = 0; 403 } 404 } else { 405 if (structureID->m_previous) 406 transition->materializePropertyMap(); 407 else 408 transition->createPropertyMapHashTable(); 409 } 307 410 308 411 offset = transition->put(propertyName, attributes); … … 310 413 transition->growPropertyStorageCapacity(); 311 414 312 transition-> setCachedTransistionOffset(offset);415 transition->m_offset = offset; 313 416 314 417 if (structureID->m_usingSingleTransitionSlot) { … … 332 435 ASSERT(!structureID->m_isDictionary); 333 436 334 RefPtr<StructureID> transition = create(structureID->m_prototype, structureID->typeInfo()); 335 transition->m_isDictionary = true; 336 transition->m_propertyTable = structureID->copyPropertyTable(); 437 RefPtr<StructureID> transition = toDictionaryTransition(structureID); 438 439 offset = transition->remove(propertyName); 440 441 return transition.release(); 442 } 443 444 PassRefPtr<StructureID> StructureID::changePrototypeTransition(StructureID* structureID, JSValue* prototype) 445 { 446 RefPtr<StructureID> transition = create(prototype, structureID->typeInfo()); 447 448 transition->m_transitionCount = structureID->m_transitionCount + 1; 337 449 transition->m_deletedOffsets = structureID->m_deletedOffsets; 338 450 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; 339 451 transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties; 340 452 341 offset = transition->remove(propertyName); 453 // Don't set m_offset, as one can not transition to this. 454 455 structureID->materializePropertyMapIfNecessary(); 456 transition->m_propertyTable = structureID->copyPropertyTable(); 457 transition->m_isPinnedPropertyTable = true; 458 459 return transition.release(); 460 } 461 462 PassRefPtr<StructureID> StructureID::getterSetterTransition(StructureID* structureID) 463 { 464 RefPtr<StructureID> transition = create(structureID->storedPrototype(), structureID->typeInfo()); 465 transition->m_transitionCount = structureID->m_transitionCount + 1; 466 transition->m_deletedOffsets = structureID->m_deletedOffsets; 467 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; 468 transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties; 469 470 // Don't set m_offset, as one can not transition to this. 471 472 structureID->materializePropertyMapIfNecessary(); 473 transition->m_propertyTable = structureID->copyPropertyTable(); 474 transition->m_isPinnedPropertyTable = true; 342 475 343 476 return transition.release(); … … 350 483 RefPtr<StructureID> transition = create(structureID->m_prototype, structureID->typeInfo()); 351 484 transition->m_isDictionary = true; 352 transition->m_propertyTable = structureID->copyPropertyTable();353 485 transition->m_deletedOffsets = structureID->m_deletedOffsets; 354 486 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; 355 487 transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties; 488 489 structureID->materializePropertyMapIfNecessary(); 490 transition->m_propertyTable = structureID->copyPropertyTable(); 491 transition->m_isPinnedPropertyTable = true; 492 356 493 return transition.release(); 357 494 } … … 364 501 // for them, we don't need to allocate a new StructureID when transitioning 365 502 // to non-dictionary status. 366 structureID->m_isDictionary = false; 503 504 // FIMXE: We can make this more efficient by canonicalizing the StructureID (draining the 505 // deleted offsets vector) before transitioning from dictionary. 506 if (structureID->m_deletedOffsets.isEmpty()) 507 structureID->m_isDictionary = false; 508 367 509 return structureID; 368 510 } 369 511 370 PassRefPtr<StructureID> StructureID::changePrototypeTransition(StructureID* structureID, JSValue* prototype)371 {372 RefPtr<StructureID> transition = create(prototype, structureID->typeInfo());373 transition->m_transitionCount = structureID->m_transitionCount + 1;374 transition->m_propertyTable = structureID->copyPropertyTable();375 transition->m_deletedOffsets = structureID->m_deletedOffsets;376 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;377 transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties;378 return transition.release();379 }380 381 PassRefPtr<StructureID> StructureID::getterSetterTransition(StructureID* structureID)382 {383 RefPtr<StructureID> transition = create(structureID->storedPrototype(), structureID->typeInfo());384 transition->m_transitionCount = structureID->m_transitionCount + 1;385 transition->m_propertyTable = structureID->copyPropertyTable();386 transition->m_deletedOffsets = structureID->m_deletedOffsets;387 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;388 transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;389 return transition.release();390 }391 392 512 size_t StructureID::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes) 393 513 { 514 ASSERT(!m_transitions.singleTransition); 515 516 materializePropertyMapIfNecessary(); 517 518 m_isPinnedPropertyTable = true; 394 519 size_t offset = put(propertyName, attributes); 395 520 if (propertyStorageSize() > propertyStorageCapacity()) … … 401 526 size_t StructureID::removePropertyWithoutTransition(const Identifier& propertyName) 402 527 { 528 ASSERT(!m_transitions.singleTransition); 529 ASSERT(m_isDictionary); 530 531 materializePropertyMapIfNecessary(); 532 533 m_isPinnedPropertyTable = true; 403 534 size_t offset = remove(propertyName); 404 535 clearEnumerationCache(); … … 450 581 inline void StructureID::checkConsistency() 451 582 { 452 } 583 } 453 584 454 585 #endif … … 472 603 } 473 604 474 size_t StructureID::get(const Identifier& propertyName, unsigned& attributes) const605 size_t StructureID::get(const Identifier& propertyName, unsigned& attributes) 475 606 { 476 607 ASSERT(!propertyName.isNull()); 477 608 609 materializePropertyMapIfNecessary(); 478 610 if (!m_propertyTable) 479 611 return WTF::notFound; … … 713 845 } 714 846 715 void StructureID::expandPropertyMapHashTable()716 {717 ASSERT(m_propertyTable);718 rehashPropertyMapHashTable(m_propertyTable->size * 2);719 }720 721 847 void StructureID::createPropertyMapHashTable() 722 848 { 723 const unsigned newTableSize = 16; 724 849 ASSERT(sizeForKeyCount(7) == newTableSize); 850 createPropertyMapHashTable(newTableSize); 851 } 852 853 void StructureID::createPropertyMapHashTable(unsigned newTableSize) 854 { 725 855 ASSERT(!m_propertyTable); 856 ASSERT(isPowerOf2(newTableSize)); 726 857 727 858 checkConsistency(); … … 734 865 } 735 866 867 void StructureID::expandPropertyMapHashTable() 868 { 869 ASSERT(m_propertyTable); 870 rehashPropertyMapHashTable(m_propertyTable->size * 2); 871 } 872 736 873 void StructureID::rehashPropertyMapHashTable() 737 874 { … … 744 881 { 745 882 ASSERT(m_propertyTable); 883 ASSERT(isPowerOf2(newTableSize)); 746 884 747 885 checkConsistency(); … … 779 917 } 780 918 781 void StructureID::getEnumerablePropertyNamesInternal(PropertyNameArray& propertyNames) const 782 { 919 void StructureID::getEnumerablePropertyNamesInternal(PropertyNameArray& propertyNames) 920 { 921 materializePropertyMapIfNecessary(); 783 922 if (!m_propertyTable) 784 923 return; … … 842 981 return; 843 982 844 ASSERT(m_propertyTable->size >= 16);983 ASSERT(m_propertyTable->size >= newTableSize); 845 984 ASSERT(m_propertyTable->sizeMask); 846 985 ASSERT(m_propertyTable->size == m_propertyTable->sizeMask + 1);
Note:
See TracChangeset
for help on using the changeset viewer.