Changeset 36285 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Sep 8, 2008, 11:55:39 PM (17 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/JSObject.cpp
r36263 r36285 70 70 JSCell::mark(); 71 71 m_structureID->mark(); 72 m_propertyMap.mark(); 72 73 unsigned storageSize = m_structureID->propertyMap().makingCount(); 74 if (storageSize) { 75 for (unsigned i = 1; i <= storageSize; ++i) { 76 JSValue* v = m_propertyStorage[i]; 77 if (!v->marked()) 78 v->mark(); 79 } 80 } 73 81 74 82 JSOBJECT_MARK_END(); … … 120 128 // Check if there are any setters or getters in the prototype chain 121 129 JSValue* prototype; 122 for (JSObject* obj = this; !obj-> m_propertyMap.hasGetterSetterProperties(); obj = static_cast<JSObject*>(prototype)) {130 for (JSObject* obj = this; !obj->structureID()->propertyMap().hasGetterSetterProperties(); obj = static_cast<JSObject*>(prototype)) { 123 131 prototype = obj->prototype(); 124 132 if (prototype->isNull()) { … … 129 137 130 138 unsigned attributes; 131 if (m_ propertyMap.get(propertyName, attributes) && attributes & ReadOnly)139 if (m_structureID->propertyMap().get(propertyName, attributes, m_propertyStorage) && attributes & ReadOnly) 132 140 return; 133 141 134 142 for (JSObject* obj = this; ; obj = static_cast<JSObject*>(prototype)) { 135 if (JSValue* gs = obj-> m_propertyMap.get(propertyName)) {143 if (JSValue* gs = obj->structureID()->propertyMap().get(propertyName, obj->propertyStorage())) { 136 144 if (gs->isGetterSetter()) { 137 145 JSObject* setterFunc = static_cast<GetterSetter*>(gs)->setter(); … … 195 203 { 196 204 unsigned attributes; 197 JSValue* v = m_ propertyMap.get(propertyName, attributes);205 JSValue* v = m_structureID->propertyMap().get(propertyName, attributes, m_propertyStorage); 198 206 if (v) { 199 207 if ((attributes & DontDelete)) … … 286 294 void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction) 287 295 { 288 GetterSetter* getterSetter; 296 JSValue* object = getDirect(propertyName); 297 if (object && object->isGetterSetter()) { 298 ASSERT(m_structureID->propertyMap().hasGetterSetterProperties()); 299 GetterSetter* getterSetter = static_cast<GetterSetter*>(object); 300 getterSetter->setGetter(getterFunction); 301 return; 302 } 303 289 304 PutPropertySlot slot; 290 291 JSValue* object = getDirect(propertyName); 292 if (object && object->isGetterSetter()) 293 getterSetter = static_cast<GetterSetter*>(object); 294 else { 295 getterSetter = new (exec) GetterSetter; 296 putDirect(propertyName, getterSetter, None, true, slot); 297 } 305 GetterSetter* getterSetter = new (exec) GetterSetter; 306 putDirect(propertyName, getterSetter, None, true, slot); 298 307 299 308 // putDirect will change our StructureID if we add a new property. For … … 307 316 } 308 317 309 m_ propertyMap.setHasGetterSetterProperties(true);318 m_structureID->propertyMap().setHasGetterSetterProperties(true); 310 319 getterSetter->setGetter(getterFunction); 311 320 } … … 313 322 void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction) 314 323 { 315 GetterSetter* getterSetter; 324 JSValue* object = getDirect(propertyName); 325 if (object && object->isGetterSetter()) { 326 ASSERT(m_structureID->propertyMap().hasGetterSetterProperties()); 327 GetterSetter* getterSetter = static_cast<GetterSetter*>(object); 328 getterSetter->setSetter(setterFunction); 329 return; 330 } 331 316 332 PutPropertySlot slot; 317 318 JSValue* object = getDirect(propertyName); 319 if (object && object->isGetterSetter()) 320 getterSetter = static_cast<GetterSetter*>(object); 321 else { 322 getterSetter = new (exec) GetterSetter; 323 putDirect(propertyName, getterSetter, None, true, slot); 324 } 333 GetterSetter* getterSetter = new (exec) GetterSetter; 334 putDirect(propertyName, getterSetter, None, true, slot); 325 335 326 336 // putDirect will change our StructureID if we add a new property. For … … 334 344 } 335 345 336 m_ propertyMap.setHasGetterSetterProperties(true);346 m_structureID->propertyMap().setHasGetterSetterProperties(true); 337 347 getterSetter->setSetter(setterFunction); 338 348 } … … 412 422 bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const 413 423 { 414 if (m_ propertyMap.get(propertyName, attributes))424 if (m_structureID->propertyMap().get(propertyName, attributes, m_propertyStorage)) 415 425 return true; 416 426 … … 427 437 void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) 428 438 { 429 m_ propertyMap.getEnumerablePropertyNames(propertyNames);439 m_structureID->propertyMap().getEnumerablePropertyNames(propertyNames); 430 440 431 441 // Add properties from the static hashtables of properties … … 486 496 void JSObject::removeDirect(const Identifier& propertyName) 487 497 { 488 m_propertyMap.remove(propertyName); 489 if (!m_structureID->isDictionary()) { 490 RefPtr<StructureID> structureID = StructureID::toDictionaryTransition(m_structureID); 491 setStructureID(structureID.release()); 492 } 498 if (m_structureID->isDictionary()) { 499 m_structureID->propertyMap().remove(propertyName, m_propertyStorage); 500 return; 501 } 502 503 RefPtr<StructureID> structureID = StructureID::toDictionaryTransition(m_structureID); 504 structureID->propertyMap().remove(propertyName, m_propertyStorage); 505 setStructureID(structureID.release()); 493 506 } 494 507 -
trunk/JavaScriptCore/kjs/JSObject.h
r36263 r36285 75 75 StructureID* inheritorID(); 76 76 77 PropertyStorage& propertyStorage() { return m_propertyStorage; } 78 77 79 virtual UString className() const; 78 80 … … 121 123 122 124 // This get function only looks at the property map. 123 JSValue* getDirect(const Identifier& propertyName) const { return m_propertyMap.get(propertyName); } 124 JSValue** getDirectLocation(const Identifier& propertyName) { return m_propertyMap.getLocation(propertyName); } 125 JSValue** getDirectLocation(const Identifier& propertyName, bool& isWriteable) { return m_propertyMap.getLocation(propertyName, isWriteable); } 126 size_t offsetForLocation(JSValue** location) { return m_propertyMap.offsetForLocation(location); } 125 JSValue* getDirect(const Identifier& propertyName) const 126 { 127 return m_structureID->propertyMap().get(propertyName, m_propertyStorage); 128 } 129 130 JSValue** getDirectLocation(const Identifier& propertyName) 131 { 132 return m_structureID->propertyMap().getLocation(propertyName, m_propertyStorage); 133 } 134 135 JSValue** getDirectLocation(const Identifier& propertyName, bool& isWriteable) 136 { 137 return m_structureID->propertyMap().getLocation(propertyName, isWriteable, m_propertyStorage); 138 } 139 140 size_t offsetForLocation(JSValue** location) 141 { 142 return location - m_propertyStorage.get(); 143 } 144 127 145 void removeDirect(const Identifier& propertyName); 128 bool hasCustomProperties() { return !m_ propertyMap.isEmpty(); }129 bool hasGetterSetterProperties() { return m_ propertyMap.hasGetterSetterProperties(); }146 bool hasCustomProperties() { return !m_structureID->propertyMap().isEmpty(); } 147 bool hasGetterSetterProperties() { return m_structureID->propertyMap().hasGetterSetterProperties(); } 130 148 131 149 void putDirect(const Identifier& propertyName, JSValue* value, unsigned attr = 0); … … 134 152 135 153 // Fast access to known property offsets. 136 JSValue* getDirectOffset(size_t offset) { return m_property Map.getOffset(offset); }137 void putDirectOffset(size_t offset, JSValue* v ) { m_propertyMap.putOffset(offset, v); }154 JSValue* getDirectOffset(size_t offset) { return m_propertyStorage[offset]; } 155 void putDirectOffset(size_t offset, JSValue* value) { m_propertyStorage[offset] = value; } 138 156 139 157 void fillGetterPropertySlot(PropertySlot&, JSValue** location); … … 159 177 StructureID* createInheritorID(); 160 178 161 Property Map m_propertyMap;179 PropertyStorage m_propertyStorage; 162 180 RefPtr<StructureID> m_inheritorID; 163 181 }; … … 285 303 { 286 304 if (JSValue** location = getDirectLocation(propertyName, slotIsWriteable)) { 287 if (m_ propertyMap.hasGetterSetterProperties() && location[0]->isGetterSetter()) {305 if (m_structureID->propertyMap().hasGetterSetterProperties() && location[0]->isGetterSetter()) { 288 306 slotIsWriteable = false; 289 307 fillGetterPropertySlot(slot, location); … … 309 327 { 310 328 if (JSValue** location = getDirectLocation(propertyName)) { 311 if (m_ propertyMap.hasGetterSetterProperties() && location[0]->isGetterSetter())329 if (m_structureID->propertyMap().hasGetterSetterProperties() && location[0]->isGetterSetter()) 312 330 fillGetterPropertySlot(slot, location); 313 331 else … … 331 349 } 332 350 333 inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value, unsigned attr , bool checkReadOnly, PutPropertySlot& slot)351 inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) 334 352 { 335 353 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); 336 m_propertyMap.put(propertyName, value, attr, checkReadOnly, this, slot); 337 if (slot.type() == PutPropertySlot::NewProperty) { 338 if (!m_structureID->isDictionary()) { 339 RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName); 340 setStructureID(structureID.release()); 341 } 342 } 354 355 if (m_structureID->isDictionary()) { 356 m_structureID->propertyMap().put(propertyName, value, attributes, checkReadOnly, this, slot, m_propertyStorage); 357 return; 358 } 359 360 bool isWriteable; 361 size_t offset = m_structureID->propertyMap().getOffset(propertyName, isWriteable); 362 if (offset != WTF::notFound) { 363 if (checkReadOnly && !isWriteable) 364 return; 365 m_propertyStorage[offset] = value; 366 slot.setExistingProperty(this, offset); 367 return; 368 } 369 370 RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName, value, attributes, checkReadOnly, this, slot, m_propertyStorage); 371 setStructureID(structureID.release()); 343 372 } 344 373 -
trunk/JavaScriptCore/kjs/PropertyMap.cpp
r36263 r36285 42 42 #endif 43 43 44 #define USE_SINGLE_ENTRY 145 46 44 namespace JSC { 47 45 … … 83 81 #if !DO_PROPERTYMAP_CONSTENCY_CHECK 84 82 85 inline void PropertyMap::checkConsistency() 86 { 87 } 88 89 #endif 83 inline void PropertyMap::checkConsistency(PropertyStorage&) 84 { 85 } 86 87 #endif 88 89 PropertyMap& PropertyMap::operator=(const PropertyMap& other) 90 { 91 if (other.m_table) { 92 size_t tableSize = Table::allocationSize(other.m_table->size); 93 m_table = static_cast<Table*>(fastMalloc(tableSize)); 94 memcpy(m_table, other.m_table, tableSize); 95 96 unsigned entryCount = m_table->keyCount + m_table->deletedSentinelCount; 97 for (unsigned i = 1; i <= entryCount; ++i) { 98 if (UString::Rep* key = m_table->entries()[i].key) 99 key->ref(); 100 } 101 } 102 103 m_getterSetterFlag = other.m_getterSetterFlag; 104 return *this; 105 } 90 106 91 107 PropertyMap::~PropertyMap() 92 108 { 93 if (!m_usingTable) { 94 #if USE_SINGLE_ENTRY 95 if (m_singleEntryKey) 96 m_singleEntryKey->deref(); 97 #endif 109 if (!m_table) 98 110 return; 99 } 100 101 unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount; 111 112 unsigned entryCount = m_table->keyCount + m_table->deletedSentinelCount; 102 113 for (unsigned i = 1; i <= entryCount; i++) { 103 if (UString::Rep* key = m_ u.table->entries()[i].key)114 if (UString::Rep* key = m_table->entries()[i].key) 104 115 key->deref(); 105 116 } 106 fastFree(m_ u.table);107 } 108 109 JSValue* PropertyMap::get(const Identifier& propertyName, unsigned& attributes ) const117 fastFree(m_table); 118 } 119 120 JSValue* PropertyMap::get(const Identifier& propertyName, unsigned& attributes, const PropertyStorage& propertyStorage) const 110 121 { 111 122 ASSERT(!propertyName.isNull()); … … 113 124 UString::Rep* rep = propertyName._ustring.rep(); 114 125 115 if (!m_usingTable) { 116 #if USE_SINGLE_ENTRY 117 if (rep == m_singleEntryKey) { 118 attributes = m_singleEntryAttributes; 119 return m_u.singleEntryValue; 120 } 121 #endif 126 if (!m_table) 122 127 return 0; 123 }124 128 125 129 unsigned i = rep->computedHash(); … … 129 133 #endif 130 134 131 unsigned entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];135 unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 132 136 if (entryIndex == emptyEntryIndex) 133 137 return 0; 134 138 135 if (rep == m_ u.table->entries()[entryIndex - 1].key) {136 attributes = m_ u.table->entries()[entryIndex - 1].attributes;137 return m_u.table->entries()[entryIndex - 1].value;139 if (rep == m_table->entries()[entryIndex - 1].key) { 140 attributes = m_table->entries()[entryIndex - 1].attributes; 141 return propertyStorage[entryIndex - 1]; 138 142 } 139 143 … … 151 155 #endif 152 156 153 entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];157 entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 154 158 if (entryIndex == emptyEntryIndex) 155 159 return 0; 156 160 157 if (rep == m_ u.table->entries()[entryIndex - 1].key) {158 attributes = m_ u.table->entries()[entryIndex - 1].attributes;159 return m_u.table->entries()[entryIndex - 1].value;160 } 161 } 162 } 163 164 JSValue* PropertyMap::get(const Identifier& propertyName ) const161 if (rep == m_table->entries()[entryIndex - 1].key) { 162 attributes = m_table->entries()[entryIndex - 1].attributes; 163 return propertyStorage[entryIndex - 1]; 164 } 165 } 166 } 167 168 JSValue* PropertyMap::get(const Identifier& propertyName, const PropertyStorage& propertyStorage) const 165 169 { 166 170 ASSERT(!propertyName.isNull()); … … 168 172 UString::Rep* rep = propertyName._ustring.rep(); 169 173 170 if (!m_usingTable) { 171 #if USE_SINGLE_ENTRY 172 if (rep == m_singleEntryKey) 173 return m_u.singleEntryValue; 174 #endif 174 if (!m_table) 175 175 return 0; 176 }177 176 178 177 unsigned i = rep->computedHash(); … … 182 181 #endif 183 182 184 unsigned entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];183 unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 185 184 if (entryIndex == emptyEntryIndex) 186 185 return 0; 187 186 188 if (rep == m_ u.table->entries()[entryIndex - 1].key)189 return m_u.table->entries()[entryIndex - 1].value;187 if (rep == m_table->entries()[entryIndex - 1].key) 188 return propertyStorage[entryIndex - 1]; 190 189 191 190 #if DUMP_PROPERTYMAP_STATS … … 202 201 #endif 203 202 204 entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];203 entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 205 204 if (entryIndex == emptyEntryIndex) 206 205 return 0; 207 206 208 if (rep == m_ u.table->entries()[entryIndex - 1].key)209 return m_u.table->entries()[entryIndex - 1].value;210 } 211 } 212 213 JSValue** PropertyMap::getLocation(const Identifier& propertyName )207 if (rep == m_table->entries()[entryIndex - 1].key) 208 return propertyStorage[entryIndex - 1]; 209 } 210 } 211 212 JSValue** PropertyMap::getLocation(const Identifier& propertyName, const PropertyStorage& propertyStorage) 214 213 { 215 214 ASSERT(!propertyName.isNull()); … … 217 216 UString::Rep* rep = propertyName._ustring.rep(); 218 217 219 if (!m_usingTable) { 220 #if USE_SINGLE_ENTRY 221 if (rep == m_singleEntryKey) 222 return &m_u.singleEntryValue; 223 #endif 218 if (!m_table) 224 219 return 0; 225 }226 220 227 221 unsigned i = rep->computedHash(); … … 231 225 #endif 232 226 233 unsigned entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];227 unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 234 228 if (entryIndex == emptyEntryIndex) 235 229 return 0; 236 230 237 if (rep == m_ u.table->entries()[entryIndex - 1].key)238 return & m_u.table->entries()[entryIndex - 1].value;231 if (rep == m_table->entries()[entryIndex - 1].key) 232 return &propertyStorage[entryIndex - 1]; 239 233 240 234 #if DUMP_PROPERTYMAP_STATS … … 251 245 #endif 252 246 253 entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];247 entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 254 248 if (entryIndex == emptyEntryIndex) 255 249 return 0; 256 250 257 if (rep == m_ u.table->entries()[entryIndex - 1].key)258 return & m_u.table->entries()[entryIndex - 1].value;259 } 260 } 261 262 JSValue** PropertyMap::getLocation(const Identifier& propertyName, bool& isWriteable )251 if (rep == m_table->entries()[entryIndex - 1].key) 252 return &propertyStorage[entryIndex - 1]; 253 } 254 } 255 256 JSValue** PropertyMap::getLocation(const Identifier& propertyName, bool& isWriteable, const PropertyStorage& propertyStorage) 263 257 { 264 258 ASSERT(!propertyName.isNull()); … … 266 260 UString::Rep* rep = propertyName._ustring.rep(); 267 261 268 if (!m_usingTable) { 269 #if USE_SINGLE_ENTRY 270 if (rep == m_singleEntryKey) { 271 isWriteable = !(m_singleEntryAttributes & ReadOnly); 272 return &m_u.singleEntryValue; 273 } 274 #endif 262 if (!m_table) 275 263 return 0; 276 }277 264 278 265 unsigned i = rep->computedHash(); … … 282 269 #endif 283 270 284 unsigned entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];271 unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 285 272 if (entryIndex == emptyEntryIndex) 286 273 return 0; 287 274 288 if (rep == m_ u.table->entries()[entryIndex - 1].key) {289 isWriteable = !(m_ u.table->entries()[entryIndex - 1].attributes & ReadOnly);290 return & m_u.table->entries()[entryIndex - 1].value;275 if (rep == m_table->entries()[entryIndex - 1].key) { 276 isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly); 277 return &propertyStorage[entryIndex - 1]; 291 278 } 292 279 … … 304 291 #endif 305 292 306 entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];293 entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 307 294 if (entryIndex == emptyEntryIndex) 308 295 return 0; 309 296 310 if (rep == m_ u.table->entries()[entryIndex - 1].key) {311 isWriteable = !(m_ u.table->entries()[entryIndex - 1].attributes & ReadOnly);312 return & m_u.table->entries()[entryIndex - 1].value;313 } 314 } 315 } 316 317 void PropertyMap::put(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot& slot )297 if (rep == m_table->entries()[entryIndex - 1].key) { 298 isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly); 299 return &propertyStorage[entryIndex - 1]; 300 } 301 } 302 } 303 304 void PropertyMap::put(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage) 318 305 { 319 306 ASSERT(!propertyName.isNull()); 320 307 ASSERT(value); 321 308 322 checkConsistency( );309 checkConsistency(propertyStorage); 323 310 324 311 UString::Rep* rep = propertyName._ustring.rep(); 325 312 326 #if USE_SINGLE_ENTRY 327 if (!m_usingTable) { 328 if (!m_singleEntryKey) { 329 rep->ref(); 330 m_singleEntryKey = rep; 331 m_u.singleEntryValue = value; 332 m_singleEntryAttributes = static_cast<short>(attributes); 333 checkConsistency(); 334 slot.setNewProperty(slotBase, WTF::notFound); 335 return; 336 } 337 if (rep == m_singleEntryKey && !(checkReadOnly && (m_singleEntryAttributes & ReadOnly))) { 338 m_u.singleEntryValue = value; 339 return; 340 } 341 } 342 #endif 343 344 if (!m_usingTable) 345 expand(); 313 if (!m_table) 314 expand(propertyStorage); 346 315 347 316 // FIXME: Consider a fast case for tables with no deleted sentinels. … … 357 326 358 327 while (1) { 359 unsigned entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];328 unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 360 329 if (entryIndex == emptyEntryIndex) 361 330 break; 362 331 363 if (m_ u.table->entries()[entryIndex - 1].key == rep) {364 if (checkReadOnly && (m_ u.table->entries()[entryIndex - 1].attributes & ReadOnly))332 if (m_table->entries()[entryIndex - 1].key == rep) { 333 if (checkReadOnly && (m_table->entries()[entryIndex - 1].attributes & ReadOnly)) 365 334 return; 366 335 // Put a new value in an existing hash table entry. 367 m_u.table->entries()[entryIndex - 1].value= value;336 propertyStorage[entryIndex - 1] = value; 368 337 // Attributes are intentionally not updated. 369 slot.setExistingProperty(slotBase, offsetForTableLocation(&m_u.table->entries()[entryIndex - 1].value));338 slot.setExistingProperty(slotBase, entryIndex - 1); 370 339 return; 371 340 } else if (entryIndex == deletedSentinelIndex) { … … 392 361 393 362 // Figure out which entry to use. 394 unsigned entryIndex = m_ u.table->keyCount + m_u.table->deletedSentinelCount + 2;363 unsigned entryIndex = m_table->keyCount + m_table->deletedSentinelCount + 2; 395 364 if (foundDeletedElement) { 396 365 i = deletedElementIndex; 397 --m_ u.table->deletedSentinelCount;366 --m_table->deletedSentinelCount; 398 367 399 368 // Since we're not making the table bigger, we can't use the entry one past … … 401 370 // slot that we can use. We know it will be there because we did at least one 402 371 // deletion in the past that left an entry empty. 403 while (m_ u.table->entries()[--entryIndex - 1].key) { }372 while (m_table->entries()[--entryIndex - 1].key) { } 404 373 } 405 374 406 375 // Create a new hash table entry. 407 m_ u.table->entryIndices[i & m_u.table->sizeMask] = entryIndex;376 m_table->entryIndices[i & m_table->sizeMask] = entryIndex; 408 377 409 378 // Create a new hash table entry. 410 379 rep->ref(); 411 m_u.table->entries()[entryIndex - 1].key = rep; 412 m_u.table->entries()[entryIndex - 1].value = value; 413 m_u.table->entries()[entryIndex - 1].attributes = attributes; 414 m_u.table->entries()[entryIndex - 1].index = ++m_u.table->lastIndexUsed; 415 ++m_u.table->keyCount; 416 417 if ((m_u.table->keyCount + m_u.table->deletedSentinelCount) * 2 >= m_u.table->size) 418 expand(); 419 420 checkConsistency(); 421 slot.setNewProperty(slotBase, offsetForTableLocation(&m_u.table->entries()[entryIndex - 1].value)); 422 } 423 424 void PropertyMap::insert(const Entry& entry) 425 { 426 ASSERT(m_u.table); 380 m_table->entries()[entryIndex - 1].key = rep; 381 m_table->entries()[entryIndex - 1].attributes = attributes; 382 m_table->entries()[entryIndex - 1].index = ++m_table->lastIndexUsed; 383 ++m_table->keyCount; 384 385 propertyStorage[entryIndex - 1] = value; 386 387 if ((m_table->keyCount + m_table->deletedSentinelCount) * 2 >= m_table->size) 388 expand(propertyStorage); 389 390 checkConsistency(propertyStorage); 391 slot.setNewProperty(slotBase, entryIndex - 1); 392 } 393 394 size_t PropertyMap::getOffset(const Identifier& propertyName) 395 { 396 ASSERT(!propertyName.isNull()); 397 398 if (!m_table) 399 return WTF::notFound; 400 401 UString::Rep* rep = propertyName._ustring.rep(); 402 403 unsigned i = rep->computedHash(); 404 405 #if DUMP_PROPERTYMAP_STATS 406 ++numProbes; 407 #endif 408 409 unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 410 if (entryIndex == emptyEntryIndex) 411 return WTF::notFound; 412 413 if (rep == m_table->entries()[entryIndex - 1].key) 414 return entryIndex - 1; 415 416 #if DUMP_PROPERTYMAP_STATS 417 ++numCollisions; 418 #endif 419 420 unsigned k = 1 | doubleHash(rep->computedHash()); 421 422 while (1) { 423 i += k; 424 425 #if DUMP_PROPERTYMAP_STATS 426 ++numRehashes; 427 #endif 428 429 entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 430 if (entryIndex == emptyEntryIndex) 431 return WTF::notFound; 432 433 if (rep == m_table->entries()[entryIndex - 1].key) 434 return entryIndex - 1; 435 } 436 } 437 438 size_t PropertyMap::getOffset(const Identifier& propertyName, bool& isWriteable) 439 { 440 ASSERT(!propertyName.isNull()); 441 442 if (!m_table) 443 return WTF::notFound; 444 445 UString::Rep* rep = propertyName._ustring.rep(); 446 447 unsigned i = rep->computedHash(); 448 449 #if DUMP_PROPERTYMAP_STATS 450 ++numProbes; 451 #endif 452 453 unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 454 if (entryIndex == emptyEntryIndex) 455 return WTF::notFound; 456 457 if (rep == m_table->entries()[entryIndex - 1].key) { 458 isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly); 459 return entryIndex - 1; 460 } 461 462 #if DUMP_PROPERTYMAP_STATS 463 ++numCollisions; 464 #endif 465 466 unsigned k = 1 | doubleHash(rep->computedHash()); 467 468 while (1) { 469 i += k; 470 471 #if DUMP_PROPERTYMAP_STATS 472 ++numRehashes; 473 #endif 474 475 entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 476 if (entryIndex == emptyEntryIndex) 477 return WTF::notFound; 478 479 if (rep == m_table->entries()[entryIndex - 1].key) { 480 isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly); 481 return entryIndex - 1; 482 } 483 } 484 } 485 486 void PropertyMap::insert(const Entry& entry, JSValue* value, PropertyStorage& propertyStorage) 487 { 488 ASSERT(m_table); 427 489 428 490 unsigned i = entry.key->computedHash(); … … 434 496 435 497 while (1) { 436 unsigned entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];498 unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 437 499 if (entryIndex == emptyEntryIndex) 438 500 break; … … 452 514 } 453 515 454 unsigned entryIndex = m_u.table->keyCount + 2; 455 m_u.table->entryIndices[i & m_u.table->sizeMask] = entryIndex; 456 m_u.table->entries()[entryIndex - 1] = entry; 457 ++m_u.table->keyCount; 458 } 459 460 void PropertyMap::expand() 461 { 462 if (!m_usingTable) 463 createTable(); 516 unsigned entryIndex = m_table->keyCount + 2; 517 m_table->entryIndices[i & m_table->sizeMask] = entryIndex; 518 m_table->entries()[entryIndex - 1] = entry; 519 520 propertyStorage[entryIndex - 1] = value; 521 522 ++m_table->keyCount; 523 } 524 525 void PropertyMap::expand(PropertyStorage& propertyStorage) 526 { 527 if (!m_table) 528 createTable(propertyStorage); 464 529 else 465 rehash(m_u.table->size * 2); 466 } 467 468 void PropertyMap::rehash() 469 { 470 ASSERT(m_usingTable); 471 ASSERT(m_u.table); 472 ASSERT(m_u.table->size); 473 rehash(m_u.table->size); 474 } 475 476 void PropertyMap::createTable() 530 rehash(m_table->size * 2, propertyStorage); 531 } 532 533 void PropertyMap::rehash(PropertyStorage& propertyStorage) 534 { 535 ASSERT(m_table); 536 ASSERT(m_table->size); 537 rehash(m_table->size, propertyStorage); 538 } 539 540 void PropertyMap::createTable(PropertyStorage& propertyStorage) 477 541 { 478 542 const unsigned newTableSize = 16; 479 543 480 ASSERT(!m_usingTable); 481 482 checkConsistency(); 483 484 #if USE_SINGLE_ENTRY 485 JSValue* oldSingleEntryValue = m_u.singleEntryValue; 486 #endif 487 488 m_u.table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize))); 489 m_u.table->size = newTableSize; 490 m_u.table->sizeMask = newTableSize - 1; 491 m_usingTable = true; 492 493 #if USE_SINGLE_ENTRY 494 if (m_singleEntryKey) { 495 insert(Entry(m_singleEntryKey, oldSingleEntryValue, m_singleEntryAttributes)); 496 m_singleEntryKey = 0; 497 } 498 #endif 499 500 checkConsistency(); 501 } 502 503 void PropertyMap::rehash(unsigned newTableSize) 504 { 505 ASSERT(!m_singleEntryKey); 506 ASSERT(m_u.table); 507 ASSERT(m_usingTable); 508 509 checkConsistency(); 510 511 Table* oldTable = m_u.table; 512 513 m_u.table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize))); 514 m_u.table->size = newTableSize; 515 m_u.table->sizeMask = newTableSize - 1; 544 ASSERT(!m_table); 545 546 checkConsistency(propertyStorage); 547 548 m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize))); 549 m_table->size = newTableSize; 550 m_table->sizeMask = newTableSize - 1; 551 552 propertyStorage.set(new JSValue*[m_table->size]); 553 554 checkConsistency(propertyStorage); 555 } 556 557 void PropertyMap::rehash(unsigned newTableSize, PropertyStorage& propertyStorage) 558 { 559 ASSERT(m_table); 560 561 checkConsistency(propertyStorage); 562 563 Table* oldTable = m_table; 564 JSValue** oldPropertStorage = propertyStorage.release(); 565 566 m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize))); 567 m_table->size = newTableSize; 568 m_table->sizeMask = newTableSize - 1; 569 570 propertyStorage.set(new JSValue*[m_table->size]); 516 571 517 572 unsigned lastIndexUsed = 0; … … 520 575 if (oldTable->entries()[i].key) { 521 576 lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed); 522 insert(oldTable->entries()[i] );523 } 524 } 525 m_ u.table->lastIndexUsed = lastIndexUsed;577 insert(oldTable->entries()[i], oldPropertStorage[i], propertyStorage); 578 } 579 } 580 m_table->lastIndexUsed = lastIndexUsed; 526 581 527 582 fastFree(oldTable); 528 529 checkConsistency(); 530 } 531 532 void PropertyMap::remove(const Identifier& propertyName) 583 delete [] oldPropertStorage; 584 585 checkConsistency(propertyStorage); 586 } 587 588 void PropertyMap::resizePropertyStorage(PropertyStorage& propertyStorage, unsigned oldSize) 589 { 590 ASSERT(m_table); 591 592 if (propertyStorage) { 593 JSValue** oldPropertStorage = propertyStorage.release(); 594 propertyStorage.set(new JSValue*[m_table->size]); 595 596 // FIXME: this can probalby use memcpy 597 for (unsigned i = 1; i <= oldSize; ++i) 598 propertyStorage[i] = oldPropertStorage[i]; 599 600 delete [] oldPropertStorage; 601 } else 602 propertyStorage.set(new JSValue*[m_table->size]); 603 604 checkConsistency(propertyStorage); 605 } 606 607 void PropertyMap::remove(const Identifier& propertyName, PropertyStorage& propertyStorage) 533 608 { 534 609 ASSERT(!propertyName.isNull()); 535 610 536 checkConsistency( );611 checkConsistency(propertyStorage); 537 612 538 613 UString::Rep* rep = propertyName._ustring.rep(); 539 614 540 if (!m_usingTable) { 541 #if USE_SINGLE_ENTRY 542 if (rep == m_singleEntryKey) { 543 m_singleEntryKey->deref(); 544 m_singleEntryKey = 0; 545 checkConsistency(); 546 } 547 #endif 615 if (!m_table) 548 616 return; 549 }550 617 551 618 #if DUMP_PROPERTYMAP_STATS … … 560 627 UString::Rep* key = 0; 561 628 while (1) { 562 entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];629 entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 563 630 if (entryIndex == emptyEntryIndex) 564 631 return; 565 632 566 key = m_ u.table->entries()[entryIndex - 1].key;633 key = m_table->entries()[entryIndex - 1].key; 567 634 if (rep == key) 568 635 break; … … 584 651 // Replace this one element with the deleted sentinel. Also clear out 585 652 // the entry so we can iterate all the entries as needed. 586 m_ u.table->entryIndices[i & m_u.table->sizeMask] = deletedSentinelIndex;653 m_table->entryIndices[i & m_table->sizeMask] = deletedSentinelIndex; 587 654 key->deref(); 588 m_u.table->entries()[entryIndex - 1].key = 0; 589 m_u.table->entries()[entryIndex - 1].value = jsUndefined(); 590 m_u.table->entries()[entryIndex - 1].attributes = 0; 591 ASSERT(m_u.table->keyCount >= 1); 592 --m_u.table->keyCount; 593 ++m_u.table->deletedSentinelCount; 594 595 if (m_u.table->deletedSentinelCount * 4 >= m_u.table->size) 596 rehash(); 597 598 checkConsistency(); 599 } 600 601 void PropertyMap::mark() const 602 { 603 if (!m_usingTable) { 604 #if USE_SINGLE_ENTRY 605 if (m_singleEntryKey) { 606 JSValue* v = m_u.singleEntryValue; 607 if (!v->marked()) 608 v->mark(); 609 } 610 #endif 611 return; 612 } 613 614 unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount; 615 for (unsigned i = 1; i <= entryCount; i++) { 616 JSValue* v = m_u.table->entries()[i].value; 617 if (!v->marked()) 618 v->mark(); 619 } 655 m_table->entries()[entryIndex - 1].key = 0; 656 m_table->entries()[entryIndex - 1].attributes = 0; 657 658 propertyStorage[entryIndex - 1] = jsUndefined(); 659 660 ASSERT(m_table->keyCount >= 1); 661 --m_table->keyCount; 662 ++m_table->deletedSentinelCount; 663 664 if (m_table->deletedSentinelCount * 4 >= m_table->size) 665 rehash(propertyStorage); 666 667 checkConsistency(propertyStorage); 620 668 } 621 669 … … 633 681 void PropertyMap::getEnumerablePropertyNames(PropertyNameArray& propertyNames) const 634 682 { 635 if (!m_usingTable) { 636 #if USE_SINGLE_ENTRY 637 UString::Rep* key = m_singleEntryKey; 638 if (key && !(m_singleEntryAttributes & DontEnum)) 639 propertyNames.add(key); 640 #endif 683 if (!m_table) 641 684 return; 642 } 643 644 if (m_u.table->keyCount < tinyMapThreshold) { 685 686 if (m_table->keyCount < tinyMapThreshold) { 645 687 Entry* a[tinyMapThreshold]; 646 688 int i = 0; 647 unsigned entryCount = m_ u.table->keyCount + m_u.table->deletedSentinelCount;689 unsigned entryCount = m_table->keyCount + m_table->deletedSentinelCount; 648 690 for (unsigned k = 1; k <= entryCount; k++) { 649 if (m_ u.table->entries()[k].key && !(m_u.table->entries()[k].attributes & DontEnum)) {650 Entry* value = &m_ u.table->entries()[k];691 if (m_table->entries()[k].key && !(m_table->entries()[k].attributes & DontEnum)) { 692 Entry* value = &m_table->entries()[k]; 651 693 int j; 652 694 for (j = i - 1; j >= 0 && a[j]->index > value->index; --j) … … 667 709 668 710 // Allocate a buffer to use to sort the keys. 669 Vector<Entry*, smallMapThreshold> sortedEnumerables(m_ u.table->keyCount);711 Vector<Entry*, smallMapThreshold> sortedEnumerables(m_table->keyCount); 670 712 671 713 // Get pointers to the enumerable entries in the buffer. 672 714 Entry** p = sortedEnumerables.data(); 673 unsigned entryCount = m_ u.table->keyCount + m_u.table->deletedSentinelCount;715 unsigned entryCount = m_table->keyCount + m_table->deletedSentinelCount; 674 716 for (unsigned i = 1; i <= entryCount; i++) { 675 if (m_ u.table->entries()[i].key && !(m_u.table->entries()[i].attributes & DontEnum))676 *p++ = &m_ u.table->entries()[i];717 if (m_table->entries()[i].key && !(m_table->entries()[i].attributes & DontEnum)) 718 *p++ = &m_table->entries()[i]; 677 719 } 678 720 … … 687 729 #if DO_PROPERTYMAP_CONSTENCY_CHECK 688 730 689 void PropertyMap::checkConsistency( )690 { 691 if (!m_ usingTable)731 void PropertyMap::checkConsistency(PropertyStorage& propertyStorage) 732 { 733 if (!m_table) 692 734 return; 693 735 694 ASSERT(m_ u.table->size >= 16);695 ASSERT(m_ u.table->sizeMask);696 ASSERT(m_ u.table->size == m_u.table->sizeMask + 1);697 ASSERT(!(m_ u.table->size & m_u.table->sizeMask));698 699 ASSERT(m_ u.table->keyCount <= m_u.table->size / 2);700 ASSERT(m_ u.table->deletedSentinelCount <= m_u.table->size / 4);701 702 ASSERT(m_ u.table->keyCount + m_u.table->deletedSentinelCount <= m_u.table->size / 2);736 ASSERT(m_table->size >= 16); 737 ASSERT(m_table->sizeMask); 738 ASSERT(m_table->size == m_table->sizeMask + 1); 739 ASSERT(!(m_table->size & m_table->sizeMask)); 740 741 ASSERT(m_table->keyCount <= m_table->size / 2); 742 ASSERT(m_table->deletedSentinelCount <= m_table->size / 4); 743 744 ASSERT(m_table->keyCount + m_table->deletedSentinelCount <= m_table->size / 2); 703 745 704 746 unsigned indexCount = 0; 705 747 unsigned deletedIndexCount = 0; 706 for (unsigned a = 0; a != m_ u.table->size; ++a) {707 unsigned entryIndex = m_ u.table->entryIndices[a];748 for (unsigned a = 0; a != m_table->size; ++a) { 749 unsigned entryIndex = m_table->entryIndices[a]; 708 750 if (entryIndex == emptyEntryIndex) 709 751 continue; … … 713 755 } 714 756 ASSERT(entryIndex > deletedSentinelIndex); 715 ASSERT(entryIndex - 1 <= m_ u.table->keyCount + m_u.table->deletedSentinelCount);757 ASSERT(entryIndex - 1 <= m_table->keyCount + m_table->deletedSentinelCount); 716 758 ++indexCount; 717 759 718 for (unsigned b = a + 1; b != m_ u.table->size; ++b)719 ASSERT(m_ u.table->entryIndices[b] != entryIndex);720 } 721 ASSERT(indexCount == m_ u.table->keyCount);722 ASSERT(deletedIndexCount == m_ u.table->deletedSentinelCount);723 724 ASSERT(m_ u.table->entries()[0].key == 0);760 for (unsigned b = a + 1; b != m_table->size; ++b) 761 ASSERT(m_table->entryIndices[b] != entryIndex); 762 } 763 ASSERT(indexCount == m_table->keyCount); 764 ASSERT(deletedIndexCount == m_table->deletedSentinelCount); 765 766 ASSERT(m_table->entries()[0].key == 0); 725 767 726 768 unsigned nonEmptyEntryCount = 0; 727 for (unsigned c = 1; c <= m_ u.table->keyCount + m_u.table->deletedSentinelCount; ++c) {728 UString::Rep* rep = m_ u.table->entries()[c].key;769 for (unsigned c = 1; c <= m_table->keyCount + m_table->deletedSentinelCount; ++c) { 770 UString::Rep* rep = m_table->entries()[c].key; 729 771 if (!rep) { 730 ASSERT( m_u.table->entries()[c].value->isUndefined());772 ASSERT(propertyStorage[c]->isUndefined()); 731 773 continue; 732 774 } … … 736 778 unsigned entryIndex; 737 779 while (1) { 738 entryIndex = m_ u.table->entryIndices[i & m_u.table->sizeMask];780 entryIndex = m_table->entryIndices[i & m_table->sizeMask]; 739 781 ASSERT(entryIndex != emptyEntryIndex); 740 if (rep == m_ u.table->entries()[entryIndex - 1].key)782 if (rep == m_table->entries()[entryIndex - 1].key) 741 783 break; 742 784 if (k == 0) … … 747 789 } 748 790 749 ASSERT(nonEmptyEntryCount == m_ u.table->keyCount);791 ASSERT(nonEmptyEntryCount == m_table->keyCount); 750 792 } 751 793 -
trunk/JavaScriptCore/kjs/PropertyMap.h
r36263 r36285 24 24 #include "PropertySlot.h" 25 25 #include "identifier.h" 26 #include <wtf/OwnArrayPtr.h> 26 27 #include <wtf/NotFound.h> 27 28 … … 31 32 class JSValue; 32 33 class PropertyNameArray; 33 struct PropertyMapEntry; 34 struct PropertyMapHashTable;34 35 typedef OwnArrayPtr<JSValue*> PropertyStorage; 35 36 36 37 struct PropertyMapEntry { 37 38 UString::Rep* key; 38 JSValue* value;39 39 unsigned attributes; 40 40 unsigned index; 41 41 42 PropertyMapEntry(UString::Rep* k, JSValue* v,int a)42 PropertyMapEntry(UString::Rep* k, int a) 43 43 : key(k) 44 , value(v)45 44 , attributes(a) 46 45 , index(0) … … 81 80 }; 82 81 83 class PropertyMap : Noncopyable{82 class PropertyMap { 84 83 friend class CTI; 85 86 84 public: 87 85 PropertyMap(); 88 86 ~PropertyMap(); 89 87 90 bool isEmpty() { return !m_usingTable & !m_singleEntryKey; }88 PropertyMap& operator=(const PropertyMap&); 91 89 92 void put(const Identifier& propertyName, JSValue*, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot&); 93 void remove(const Identifier& propertyName); 94 JSValue* get(const Identifier& propertyName) const; 95 JSValue* get(const Identifier& propertyName, unsigned& attributes) const; 96 JSValue** getLocation(const Identifier& propertyName); 97 JSValue** getLocation(const Identifier& propertyName, bool& isWriteable); 98 99 JSValue* getOffset(size_t offset) 100 { 101 ASSERT(m_usingTable); 102 return reinterpret_cast<JSValue**>(m_u.table->entryIndices)[offset]; 103 } 104 void putOffset(size_t offset, JSValue* v) 105 { 106 ASSERT(m_usingTable); 107 reinterpret_cast<JSValue**>(m_u.table->entryIndices)[offset] = v; 108 } 90 bool isEmpty() { return !m_table; } 109 91 110 size_t offsetForLocation(JSValue** location) { return m_usingTable ? offsetForTableLocation(location) : WTF::notFound; } 92 void put(const Identifier& propertyName, JSValue*, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot&, PropertyStorage&); 93 void remove(const Identifier& propertyName, PropertyStorage&); 94 JSValue* get(const Identifier& propertyName, const PropertyStorage&) const; 95 JSValue* get(const Identifier& propertyName, unsigned& attributes, const PropertyStorage&) const; 96 JSValue** getLocation(const Identifier& propertyName, const PropertyStorage&); 97 JSValue** getLocation(const Identifier& propertyName, bool& isWriteable, const PropertyStorage&); 111 98 112 void mark() const; 99 size_t getOffset(const Identifier& propertyName); 100 size_t getOffset(const Identifier& propertyName, bool& isWriteable); 101 113 102 void getEnumerablePropertyNames(PropertyNameArray&) const; 114 103 115 104 bool hasGetterSetterProperties() const { return m_getterSetterFlag; } 116 105 void setHasGetterSetterProperties(bool f) { m_getterSetterFlag = f; } 106 107 unsigned size() const { return m_table ? m_table->size : 0; } 108 unsigned makingCount() const { return m_table ? m_table->keyCount + m_table->deletedSentinelCount : 0; } 109 110 void resizePropertyStorage(PropertyStorage&, unsigned oldSize); 117 111 118 112 private: … … 121 115 122 116 static bool keysMatch(const UString::Rep*, const UString::Rep*); 123 void expand(); 124 void rehash(); 125 void rehash(unsigned newTableSize); 126 void createTable(); 127 128 void insert(const Entry&); 129 130 size_t offsetForTableLocation(JSValue** location) 131 { 132 ASSERT(m_usingTable); 133 return location - reinterpret_cast<JSValue**>(m_u.table->entryIndices); 134 } 117 void expand(PropertyStorage&); 118 void rehash(PropertyStorage&); 119 void rehash(unsigned newTableSize, PropertyStorage&); 120 void createTable(PropertyStorage&); 135 121 136 void checkConsistency(); 137 138 UString::Rep* m_singleEntryKey; 139 union { 140 JSValue* singleEntryValue; 141 Table* table; 142 } m_u; 122 void insert(const Entry&, JSValue*, PropertyStorage&); 143 123 144 short m_singleEntryAttributes; 124 void checkConsistency(PropertyStorage&); 125 126 Table* m_table; 145 127 bool m_getterSetterFlag : 1; 146 bool m_usingTable : 1;147 128 }; 148 129 149 130 inline PropertyMap::PropertyMap() 150 : m_ singleEntryKey(0)131 : m_table(0) 151 132 , m_getterSetterFlag(false) 152 , m_usingTable(false)153 154 133 { 155 134 } -
trunk/JavaScriptCore/kjs/StructureID.cpp
r36263 r36285 1 // -*- mode: c++; c-basic-offset: 4 -*-2 1 /* 3 2 * Copyright (C) 2008 Apple Inc. All rights reserved. … … 32 31 #include <wtf/RefPtr.h> 33 32 33 using namespace std; 34 34 35 namespace JSC { 35 36 … … 46 47 } 47 48 48 PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& name)49 PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage) 49 50 { 50 51 ASSERT(!structureID->m_isDictionary); 51 52 52 if (StructureID* existingTransition = structureID->m_transitionTable.get(name.ustring().rep())) 53 if (StructureID* existingTransition = structureID->m_transitionTable.get(make_pair(propertyName.ustring().rep(), attributes))) { 54 if (structureID->m_propertyMap.size() != existingTransition->m_propertyMap.size()) 55 existingTransition->m_propertyMap.resizePropertyStorage(propertyStorage, structureID->m_propertyMap.size()); 56 57 size_t offset = existingTransition->propertyMap().getOffset(propertyName); 58 ASSERT(offset != WTF::notFound); 59 propertyStorage[offset] = value; 60 slot.setExistingProperty(slotBase, offset); 61 53 62 return existingTransition; 63 } 54 64 55 if (structureID->m_transitionCount > s_maxTransitionLength) 56 return toDictionaryTransition(structureID); 65 if (structureID->m_transitionCount > s_maxTransitionLength) { 66 RefPtr<StructureID> transition = toDictionaryTransition(structureID); 67 transition->m_propertyMap.put(propertyName, value, attributes, checkReadOnly, slotBase, slot, propertyStorage); 68 return transition.release(); 69 } 57 70 58 71 RefPtr<StructureID> transition = create(structureID->m_prototype); 59 72 transition->m_cachedPrototypeChain = structureID->m_cachedPrototypeChain; 60 73 transition->m_previous = structureID; 61 transition->m_nameInPrevious = name.ustring().rep(); 74 transition->m_nameInPrevious = propertyName.ustring().rep(); 75 transition->m_attributesInPrevious = attributes; 62 76 transition->m_transitionCount = structureID->m_transitionCount + 1; 77 transition->m_propertyMap = structureID->m_propertyMap; 63 78 64 structureID->m_transitionTable.add(name.ustring().rep(), transition.get()); 79 transition->m_propertyMap.put(propertyName, value, attributes, checkReadOnly, slotBase, slot, propertyStorage); 80 81 structureID->m_transitionTable.add(make_pair(propertyName.ustring().rep(), attributes), transition.get()); 65 82 return transition.release(); 66 83 } … … 72 89 RefPtr<StructureID> transition = create(structureID->m_prototype); 73 90 transition->m_isDictionary = true; 91 transition->m_propertyMap = structureID->m_propertyMap; 74 92 return transition.release(); 75 93 } … … 90 108 RefPtr<StructureID> transition = create(prototype); 91 109 transition->m_transitionCount = structureID->m_transitionCount + 1; 110 transition->m_propertyMap = structureID->m_propertyMap; 92 111 return transition.release(); 93 112 } … … 97 116 RefPtr<StructureID> transition = create(structureID->prototype()); 98 117 transition->m_transitionCount = structureID->m_transitionCount + 1; 118 transition->m_propertyMap = structureID->m_propertyMap; 99 119 return transition.release(); 100 120 } … … 103 123 { 104 124 if (m_previous) { 105 ASSERT(m_previous->m_transitionTable.contains(m _nameInPrevious));106 m_previous->m_transitionTable.remove(m _nameInPrevious);125 ASSERT(m_previous->m_transitionTable.contains(make_pair(m_nameInPrevious, m_attributesInPrevious))); 126 m_previous->m_transitionTable.remove(make_pair(m_nameInPrevious, m_attributesInPrevious)); 107 127 } 108 128 } -
trunk/JavaScriptCore/kjs/StructureID.h
r36263 r36285 1 // -*- mode: c++; c-basic-offset: 4 -*-2 1 /* 3 2 * Copyright (C) 2008 Apple Inc. All rights reserved. … … 28 27 #define StructureID_h 29 28 29 #include "JSValue.h" 30 #include "PropertyMap.h" 31 #include "ustring.h" 32 #include <wtf/HashFunctions.h> 33 #include <wtf/HashTraits.h> 30 34 #include <wtf/OwnArrayPtr.h> 31 35 #include <wtf/PassRefPtr.h> 32 36 #include <wtf/RefCounted.h> 33 #include "JSValue.h"34 #include "ustring.h"35 37 36 38 namespace JSC { … … 38 40 class JSValue; 39 41 class StructureIDChain; 42 43 struct TransitionTableHash { 44 typedef std::pair<RefPtr<UString::Rep>, unsigned> TransitionTableKey; 45 static unsigned hash(const TransitionTableKey& p) 46 { 47 return p.first->computedHash(); 48 } 49 50 static bool equal(const TransitionTableKey& a, const TransitionTableKey& b) 51 { 52 return a == b; 53 } 54 55 static const bool safeToCompareToEmptyOrDeleted = true; 56 }; 57 58 struct TransitionTableHashTraits { 59 typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits; 60 typedef WTF::GenericHashTraits<unsigned> SecondTraits; 61 typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType; 62 63 static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; 64 static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } 65 66 static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; 67 68 static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } 69 static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } 70 }; 40 71 41 72 class StructureID : public RefCounted<StructureID> { … … 45 76 return adoptRef(new StructureID(prototype)); 46 77 } 47 78 48 79 static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype); 49 static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& name);80 static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, JSValue*, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot&, PropertyStorage&); 50 81 static PassRefPtr<StructureID> getterSetterTransition(StructureID*); 51 82 static PassRefPtr<StructureID> toDictionaryTransition(StructureID*); … … 63 94 64 95 JSValue* prototype() const { return m_prototype; } 65 96 66 97 void setCachedPrototypeChain(PassRefPtr<StructureIDChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } 67 98 StructureIDChain* cachedPrototypeChain() const { return m_cachedPrototypeChain.get(); } 68 99 100 const PropertyMap& propertyMap() const { return m_propertyMap; } 101 PropertyMap& propertyMap() { return m_propertyMap; } 102 69 103 private: 70 typedef HashMap<RefPtr<UString::Rep>, StructureID*, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> > > TransitionTable; 71 104 typedef std::pair<RefPtr<UString::Rep>, unsigned> TransitionTableKey; 105 typedef HashMap<TransitionTableKey, StructureID*, TransitionTableHash, TransitionTableHashTraits> TransitionTable; 106 72 107 StructureID(JSValue* prototype); 73 108 … … 81 116 RefPtr<StructureID> m_previous; 82 117 UString::Rep* m_nameInPrevious; 118 unsigned m_attributesInPrevious; 83 119 84 120 size_t m_transitionCount; 85 121 TransitionTable m_transitionTable; 122 123 PropertyMap m_propertyMap; 86 124 }; 87 125
Note:
See TracChangeset
for help on using the changeset viewer.