Changeset 37381 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Oct 7, 2008, 11:17:37 AM (17 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/JSObject.cpp
r37370 r37381 135 135 136 136 unsigned attributes; 137 if ((m_structureID->propertyMap().get (propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)137 if ((m_structureID->propertyMap().getOffset(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly) 138 138 return; 139 139 … … 201 201 { 202 202 unsigned attributes; 203 if (m_structureID->propertyMap().get (propertyName, attributes) != WTF::notFound) {203 if (m_structureID->propertyMap().getOffset(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 (propertyName, attributes) != WTF::notFound)415 if (m_structureID->propertyMap().getOffset(propertyName, attributes) != WTF::notFound) 416 416 return true; 417 417 … … 469 469 void JSObject::removeDirect(const Identifier& propertyName) 470 470 { 471 size_t offset;472 471 if (m_structureID->isDictionary()) { 473 offset = m_structureID->propertyMap().remove(propertyName); 474 if (offset != WTF::notFound) { 475 m_propertyStorage[offset] = jsUndefined(); 476 m_structureID->clearEnumerationCache(); 477 } 472 m_structureID->propertyMap().remove(propertyName, m_propertyStorage); 473 m_structureID->clearEnumerationCache(); 478 474 return; 479 475 } 480 476 481 477 RefPtr<StructureID> structureID = StructureID::toDictionaryTransition(m_structureID); 482 offset = structureID->propertyMap().remove(propertyName); 483 if (offset != WTF::notFound) 484 m_propertyStorage[offset] = jsUndefined(); 478 structureID->propertyMap().remove(propertyName, m_propertyStorage); 485 479 setStructureID(structureID.release()); 486 480 } … … 507 501 void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize) 508 502 { 509 ASSERT(newSize > oldSize);510 511 503 JSValue** oldPropertStorage = m_propertyStorage; 512 504 m_propertyStorage = new JSValue*[newSize]; -
trunk/JavaScriptCore/kjs/JSObject.h
r37370 r37381 123 123 JSValue* getDirect(const Identifier& propertyName) const 124 124 { 125 size_t offset = m_structureID->propertyMap().get (propertyName);125 size_t offset = m_structureID->propertyMap().getOffset(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 (propertyName);131 size_t offset = m_structureID->propertyMap().getOffset(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 (propertyName, attributes);137 size_t offset = m_structureID->propertyMap().getOffset(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;182 181 183 182 static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(ObjectType)); } … … 366 365 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); 367 366 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 } 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 } 391 384 392 385 unsigned currentAttributes; 393 size_t offset = m_structureID->propertyMap().get (propertyName, currentAttributes);386 size_t offset = m_structureID->propertyMap().getOffset(propertyName, currentAttributes); 394 387 if (offset != WTF::notFound) { 395 388 if (checkReadOnly && currentAttributes & ReadOnly) … … 400 393 } 401 394 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()); 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()); 412 401 } 413 402 414 403 inline void JSObject::transitionTo(StructureID* newStructureID) 415 404 { 416 if (m_structureID->propertyStorageCapacity() != newStructureID->propertyStorageCapacity()) 417 allocatePropertyStorage(m_structureID->propertyStorageCapacity(), newStructureID->propertyStorageCapacity()); 405 StructureID::transitionTo(m_structureID, newStructureID, this); 418 406 setStructureID(newStructureID); 419 407 } -
trunk/JavaScriptCore/kjs/PropertyMap.cpp
r37370 r37381 78 78 #if !DO_PROPERTYMAP_CONSTENCY_CHECK 79 79 80 inline void PropertyMap::checkConsistency( )80 inline void PropertyMap::checkConsistency(PropertyStorage&) 81 81 { 82 82 } … … 98 98 } 99 99 100 m_deletedOffsets = other.m_deletedOffsets;101 100 m_getterSetterFlag = other.m_getterSetterFlag; 102 101 return *this; … … 116 115 } 117 116 118 size_t PropertyMap::put(const Identifier& propertyName, unsigned attributes)117 size_t PropertyMap::put(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage) 119 118 { 120 119 ASSERT(!propertyName.isNull()); 121 ASSERT( get(propertyName) == WTF::notFound);122 123 checkConsistency( );120 ASSERT(value); 121 122 checkConsistency(propertyStorage); 124 123 125 124 UString::Rep* rep = propertyName._ustring.rep(); 126 125 127 126 if (!m_table) 128 createTable();127 expand(propertyStorage); 129 128 130 129 // FIXME: Consider a fast case for tables with no deleted sentinels. … … 144 143 break; 145 144 146 if (entryIndex == deletedSentinelIndex) { 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) { 147 154 // If we find a deleted-element sentinel, remember it for use later. 148 155 if (!foundDeletedElement) { … … 187 194 m_table->entries()[entryIndex - 1].attributes = attributes; 188 195 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 } else195 newOffset = m_table->keyCount + m_table->deletedSentinelCount;196 m_table->entries()[entryIndex - 1].offset = newOffset;197 198 196 ++m_table->keyCount; 199 197 198 propertyStorage[entryIndex - 2] = value; 199 200 200 if ((m_table->keyCount + m_table->deletedSentinelCount) * 2 >= m_table->size) 201 expand(); 202 203 checkConsistency(); 204 return newOffset; 205 } 206 207 size_t PropertyMap::remove(const Identifier& propertyName) 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) 208 209 { 209 210 ASSERT(!propertyName.isNull()); 210 211 211 checkConsistency( );212 checkConsistency(propertyStorage); 212 213 213 214 UString::Rep* rep = propertyName._ustring.rep(); 214 215 215 216 if (!m_table) 216 return WTF::notFound; 217 217 return; 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 WTF::notFound;232 return; 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 258 255 key->deref(); 259 256 m_table->entries()[entryIndex - 1].key = 0; 260 257 m_table->entries()[entryIndex - 1].attributes = 0; 261 m_table->entries()[entryIndex - 1].offset = 0; 262 m_deletedOffsets.append(offset);258 259 propertyStorage[entryIndex - 2] = jsUndefined(); 263 260 264 261 ASSERT(m_table->keyCount >= 1); … … 267 264 268 265 if (m_table->deletedSentinelCount * 4 >= m_table->size) 269 rehash(); 270 271 checkConsistency(); 272 return offset; 273 } 274 275 size_t PropertyMap::get(const Identifier& propertyName, unsigned& attributes) 266 rehash(propertyStorage); 267 268 checkConsistency(propertyStorage); 269 } 270 271 size_t PropertyMap::getOffset(const Identifier& propertyName, unsigned& attributes) 276 272 { 277 273 ASSERT(!propertyName.isNull()); … … 294 290 if (rep == m_table->entries()[entryIndex - 1].key) { 295 291 attributes = m_table->entries()[entryIndex - 1].attributes; 296 return m_table->entries()[entryIndex - 1].offset;292 return entryIndex - 2; 297 293 } 298 294 … … 316 312 if (rep == m_table->entries()[entryIndex - 1].key) { 317 313 attributes = m_table->entries()[entryIndex - 1].attributes; 318 return m_table->entries()[entryIndex - 1].offset;319 } 320 } 321 } 322 323 void PropertyMap::insert(const Entry& entry )314 return entryIndex - 2; 315 } 316 } 317 } 318 319 void PropertyMap::insert(const Entry& entry, JSValue* value, PropertyStorage& propertyStorage) 324 320 { 325 321 ASSERT(m_table); … … 355 351 m_table->entries()[entryIndex - 1] = entry; 356 352 353 propertyStorage[entryIndex - 2] = value; 354 357 355 ++m_table->keyCount; 358 356 } 359 357 360 void PropertyMap::expand() 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) 361 367 { 362 368 ASSERT(m_table); 363 rehash(m_table->size * 2); 364 } 365 366 void PropertyMap::createTable() 369 ASSERT(m_table->size); 370 rehash(m_table->size, propertyStorage); 371 } 372 373 void PropertyMap::createTable(PropertyStorage& propertyStorage) 367 374 { 368 375 const unsigned newTableSize = 16; … … 370 377 ASSERT(!m_table); 371 378 372 checkConsistency( );379 checkConsistency(propertyStorage); 373 380 374 381 m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize))); … … 376 383 m_table->sizeMask = newTableSize - 1; 377 384 378 checkConsistency( );379 } 380 381 void PropertyMap::rehash( )385 checkConsistency(propertyStorage); 386 } 387 388 void PropertyMap::rehash(unsigned newTableSize, PropertyStorage& propertyStorage) 382 389 { 383 390 ASSERT(m_table); 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(); 391 392 checkConsistency(propertyStorage); 393 393 394 394 Table* oldTable = m_table; 395 JSValue** oldPropertStorage = propertyStorage; 395 396 396 397 m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize))); 397 398 m_table->size = newTableSize; 398 399 m_table->sizeMask = newTableSize - 1; 400 401 propertyStorage = new JSValue*[m_table->size]; 399 402 400 403 unsigned lastIndexUsed = 0; … … 403 406 if (oldTable->entries()[i].key) { 404 407 lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed); 405 insert(oldTable->entries()[i] );408 insert(oldTable->entries()[i], oldPropertStorage[i - 1], propertyStorage); 406 409 } 407 410 } … … 409 412 410 413 fastFree(oldTable); 411 412 checkConsistency(); 414 delete [] oldPropertStorage; 415 416 checkConsistency(propertyStorage); 413 417 } 414 418 … … 482 486 #if DO_PROPERTYMAP_CONSTENCY_CHECK 483 487 484 void PropertyMap::checkConsistency( )488 void PropertyMap::checkConsistency(PropertyStorage& propertyStorage) 485 489 { 486 490 if (!m_table) … … 522 526 for (unsigned c = 1; c <= m_table->keyCount + m_table->deletedSentinelCount; ++c) { 523 527 UString::Rep* rep = m_table->entries()[c].key; 524 if (!rep) 528 if (!rep) { 529 ASSERT(propertyStorage[c - 1]->isUndefined()); 525 530 continue; 531 } 526 532 ++nonEmptyEntryCount; 527 533 unsigned i = rep->computedHash(); -
trunk/JavaScriptCore/kjs/PropertyMap.h
r37370 r37381 43 43 struct PropertyMapEntry { 44 44 UString::Rep* key; 45 unsigned offset;46 45 unsigned attributes; 47 46 unsigned index; … … 49 48 PropertyMapEntry(UString::Rep* k, int a) 50 49 : key(k) 51 , offset(0)52 50 , attributes(a) 53 51 , index(0) … … 97 95 bool isEmpty() { return !m_table; } 98 96 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); 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); 103 102 104 103 void getEnumerablePropertyNames(PropertyNameArray&) const; … … 116 115 typedef PropertyMapHashTable Table; 117 116 118 void expand( );119 void rehash( );120 void rehash(unsigned newTableSize );121 void createTable( );117 void expand(PropertyStorage&); 118 void rehash(PropertyStorage&); 119 void rehash(unsigned newTableSize, PropertyStorage&); 120 void createTable(PropertyStorage&); 122 121 123 void insert(const Entry& );122 void insert(const Entry&, JSValue*, PropertyStorage&); 124 123 125 void checkConsistency( );124 void checkConsistency(PropertyStorage&); 126 125 127 126 Table* m_table; 128 Vector<unsigned> m_deletedOffsets;129 127 bool m_getterSetterFlag : 1; 130 128 }; … … 136 134 } 137 135 138 inline size_t PropertyMap::get (const Identifier& propertyName)136 inline size_t PropertyMap::getOffset(const Identifier& propertyName) 139 137 { 140 138 ASSERT(!propertyName.isNull()); … … 156 154 157 155 if (rep == m_table->entries()[entryIndex - 1].key) 158 return m_table->entries()[entryIndex - 1].offset;156 return entryIndex - 2; 159 157 160 158 #if DUMP_PROPERTYMAP_STATS … … 176 174 177 175 if (rep == m_table->entries()[entryIndex - 1].key) 178 return m_table->entries()[entryIndex - 1].offset;176 return entryIndex - 2; 179 177 } 180 178 } -
trunk/JavaScriptCore/kjs/StructureID.cpp
r37370 r37381 45 45 , m_nameInPrevious(0) 46 46 , m_transitionCount(0) 47 , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)48 47 , m_cachedTransistionOffset(WTF::notFound) 49 48 { … … 104 103 } 105 104 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) 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) 115 112 { 116 113 ASSERT(!structureID->m_isDictionary); … … 118 115 119 116 if (StructureID* existingTransition = structureID->m_transitionTable.get(make_pair(propertyName.ustring().rep(), attributes))) { 120 offset = existingTransition->cachedTransistionOffset(); 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(); 121 121 ASSERT(offset != WTF::notFound); 122 propertyStorage[offset] = value; 123 slot.setNewProperty(slotBase, offset); 124 122 125 return existingTransition; 123 126 } … … 125 128 if (structureID->m_transitionCount > s_maxTransitionLength) { 126 129 RefPtr<StructureID> transition = toDictionaryTransition(structureID); 127 offset = transition->m_propertyMap.put(propertyName, attributes); 128 if (transition->m_propertyMap.storageSize() > transition->propertyStorageCapacity()) 129 transition->growPropertyStorageCapacity(); 130 transition->m_propertyMap.put(propertyName, value, attributes, false, slotBase, slot, propertyStorage); 130 131 return transition.release(); 131 132 } … … 138 139 transition->m_transitionCount = structureID->m_transitionCount + 1; 139 140 transition->m_propertyMap = structureID->m_propertyMap; 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 141 142 size_t offset = transition->m_propertyMap.put(propertyName, value, attributes, false, slotBase, slot, propertyStorage); 146 143 transition->setCachedTransistionOffset(offset); 147 144 … … 157 154 transition->m_isDictionary = true; 158 155 transition->m_propertyMap = structureID->m_propertyMap; 159 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;160 156 return transition.release(); 161 157 } … … 177 173 transition->m_transitionCount = structureID->m_transitionCount + 1; 178 174 transition->m_propertyMap = structureID->m_propertyMap; 179 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;180 175 return transition.release(); 181 176 } … … 186 181 transition->m_transitionCount = structureID->m_transitionCount + 1; 187 182 transition->m_propertyMap = structureID->m_propertyMap; 188 transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;189 183 return transition.release(); 190 184 } -
trunk/JavaScriptCore/kjs/StructureID.h
r37370 r37381 84 84 85 85 static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype); 86 static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, unsigned attributes, size_t& offset);86 static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, JSValue*, unsigned attributes, JSObject* slotBase, PutPropertySlot&, PropertyStorage&); 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 124 121 void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*); 125 122 void clearEnumerationCache(); 123 124 static void transitionTo(StructureID* oldStructureID, StructureID* newStructureID, JSObject* slotBase); 126 125 127 126 private: … … 150 149 151 150 PropertyMap m_propertyMap; 152 size_t m_propertyStorageCapacity;153 151 154 152 size_t m_cachedTransistionOffset;
Note:
See TracChangeset
for help on using the changeset viewer.