Changeset 37370 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Oct 6, 2008, 10:43:06 PM (17 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
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.