Changeset 43432 in webkit for trunk/JavaScriptCore
- Timestamp:
- May 9, 2009, 1:35:57 AM (16 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r43431 r43432 1 2009-05-09 Maciej Stachowiak <[email protected]> 2 3 Reviewed by Gavin Barraclough. 4 5 Original patch by John McCall. Updated by Cameron Zwarich. Further refined by me. 6 7 - Assorted speedups to property access 8 9 ~.3%-1% speedup on SunSpider 10 11 1) When we know from the structure ID that an object is using inline storage, plant direct 12 loads and stores against it; no need to indirect through storage pointer. 13 14 2) Also because of the above, union the property storage pointer with the first inline property 15 slot and add an extra inline property slot. 16 17 * assembler/AbstractMacroAssembler.h: 18 (JSC::AbstractMacroAssembler::CodeLocationInstruction::CodeLocationInstruction): 19 (JSC::AbstractMacroAssembler::CodeLocationInstruction::patchLoadToLEA): 20 (JSC::::CodeLocationCommon::instructionAtOffset): 21 * assembler/MacroAssembler.h: 22 (JSC::MacroAssembler::storePtr): 23 * assembler/MacroAssemblerX86.h: 24 (JSC::MacroAssemblerX86::store32): 25 * assembler/MacroAssemblerX86_64.h: 26 (JSC::MacroAssemblerX86_64::storePtr): 27 * assembler/X86Assembler.h: 28 (JSC::X86Assembler::movq_EAXm): 29 (JSC::X86Assembler::movl_rm): 30 (JSC::X86Assembler::patchLoadToLEA): 31 * jit/JIT.cpp: 32 (JSC::JIT::privateCompileMainPass): 33 * jit/JIT.h: 34 * jit/JITPropertyAccess.cpp: 35 (JSC::JIT::compileGetByIdHotPath): 36 (JSC::JIT::compilePutByIdHotPath): 37 (JSC::JIT::compilePutDirectOffset): 38 (JSC::JIT::compileGetDirectOffset): 39 (JSC::JIT::privateCompilePutByIdTransition): 40 (JSC::JIT::patchGetByIdSelf): 41 (JSC::JIT::patchPutByIdReplace): 42 (JSC::JIT::privateCompileGetByIdSelf): 43 (JSC::JIT::privateCompileGetByIdProto): 44 (JSC::JIT::privateCompileGetByIdSelfList): 45 (JSC::JIT::privateCompileGetByIdProtoList): 46 (JSC::JIT::privateCompileGetByIdChainList): 47 (JSC::JIT::privateCompileGetByIdChain): 48 (JSC::JIT::privateCompilePutByIdReplace): 49 * runtime/JSObject.cpp: 50 (JSC::JSObject::mark): 51 (JSC::JSObject::removeDirect): 52 * runtime/JSObject.h: 53 (JSC::JSObject::propertyStorage): 54 (JSC::JSObject::getDirect): 55 (JSC::JSObject::getOffset): 56 (JSC::JSObject::offsetForLocation): 57 (JSC::JSObject::locationForOffset): 58 (JSC::JSObject::getDirectOffset): 59 (JSC::JSObject::putDirectOffset): 60 (JSC::JSObject::isUsingInlineStorage): 61 (JSC::JSObject::): 62 (JSC::JSObject::JSObject): 63 (JSC::JSObject::~JSObject): 64 (JSC::Structure::isUsingInlineStorage): 65 (JSC::JSObject::putDirect): 66 (JSC::JSObject::putDirectWithoutTransition): 67 (JSC::JSObject::allocatePropertyStorageInline): 68 * runtime/Structure.h: 69 1 70 2009-05-09 Geoffrey Garen <[email protected]> 2 71 -
trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h
r41544 r43432 38 38 class Jump; 39 39 class PatchBuffer; 40 class CodeLocationInstruction; 40 41 class CodeLocationLabel; 41 42 class CodeLocationJump; … … 407 408 // methods may be used to recover a handle that has nopw been 408 409 // retained, based on a known fixed relative offset from one that has. 410 CodeLocationInstruction instructionAtOffset(int offset); 409 411 CodeLocationLabel labelAtOffset(int offset); 410 412 CodeLocationJump jumpAtOffset(int offset); … … 423 425 424 426 void* m_location; 427 }; 428 429 // CodeLocationInstruction: 430 // 431 // An arbitrary instruction in the JIT code. 432 class CodeLocationInstruction : public CodeLocationCommon { 433 friend class CodeLocationCommon; 434 public: 435 CodeLocationInstruction() 436 { 437 } 438 439 void patchLoadToLEA() { 440 AssemblerType::patchLoadToLEA(reinterpret_cast<intptr_t>(this->m_location)); 441 } 442 443 private: 444 explicit CodeLocationInstruction(void* location) 445 : CodeLocationCommon(location) 446 { 447 } 425 448 }; 426 449 … … 805 828 806 829 template <class AssemblerType> 830 typename AbstractMacroAssembler<AssemblerType>::CodeLocationInstruction AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::instructionAtOffset(int offset) 831 { 832 return typename AbstractMacroAssembler::CodeLocationInstruction(reinterpret_cast<char*>(m_location) + offset); 833 } 834 835 template <class AssemblerType> 807 836 typename AbstractMacroAssembler<AssemblerType>::CodeLocationLabel AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::labelAtOffset(int offset) 808 837 { -
trunk/JavaScriptCore/assembler/MacroAssembler.h
r41103 r43432 243 243 } 244 244 245 void storePtr(RegisterID src, void* address) 246 { 247 store32(src, address); 248 } 249 245 250 void storePtr(ImmPtr imm, ImplicitAddress address) 246 251 { -
trunk/JavaScriptCore/assembler/MacroAssemblerX86.h
r41089 r43432 71 71 } 72 72 73 void store32(RegisterID src, void* address) 74 { 75 m_assembler.movl_rm(src, address); 76 } 77 73 78 Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right) 74 79 { -
trunk/JavaScriptCore/assembler/MacroAssemblerX86_64.h
r43220 r43432 242 242 m_assembler.movq_rm(src, address.offset, address.base, address.index, address.scale); 243 243 } 244 245 void storePtr(RegisterID src, void* address) 246 { 247 if (src == X86::eax) 248 m_assembler.movq_EAXm(address); 249 else { 250 swap(X86::eax, src); 251 m_assembler.movq_EAXm(address); 252 swap(X86::eax, src); 253 } 254 } 244 255 245 256 void storePtr(ImmPtr imm, ImplicitAddress address) -
trunk/JavaScriptCore/assembler/X86Assembler.h
r43220 r43432 938 938 } 939 939 940 void movq_EAXm(void* addr) 941 { 942 m_formatter.oneByteOp64(OP_MOV_OvEAX); 943 m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); 944 } 945 940 946 void movq_mr(int offset, RegisterID base, RegisterID dst) 941 947 { … … 972 978 973 979 #else 980 void movl_rm(RegisterID src, void* addr) 981 { 982 if (src == X86::eax) 983 movl_EAXm(addr); 984 else 985 m_formatter.oneByteOp(OP_MOV_EvGv, src, addr); 986 } 987 974 988 void movl_mr(void* addr, RegisterID dst) 975 989 { … … 1287 1301 ASSERT(linkOffset == static_cast<int>(linkOffset)); 1288 1302 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + from.m_offset)[-1] = linkOffset; 1303 } 1304 1305 static void patchLoadToLEA(intptr_t where) 1306 { 1307 char* ptr = reinterpret_cast<char*>(where); 1308 ptr[0] = OP_LEA; 1289 1309 } 1290 1310 -
trunk/JavaScriptCore/jit/JIT.cpp
r43431 r43432 595 595 596 596 // Load cached property 597 loadPtr(Address(regT0, FIELD_OFFSET(JSGlobalObject, m_propertyStorage)), regT0); 597 // Assume that the global object always uses external storage. 598 loadPtr(Address(regT0, FIELD_OFFSET(JSGlobalObject, m_externalStorage)), regT0); 598 599 load32(offsetAddr, regT1); 599 600 loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0); -
trunk/JavaScriptCore/jit/JIT.h
r43409 r43432 227 227 // These architecture specific value are used to enable patching - see comment on op_put_by_id. 228 228 static const int patchOffsetPutByIdStructure = 10; 229 static const int patchOffsetPutByIdExternalLoad = 20; 230 static const int patchLengthPutByIdExternalLoad = 4; 229 231 static const int patchOffsetPutByIdPropertyMapOffset = 31; 230 232 // These architecture specific value are used to enable patching - see comment on op_get_by_id. 231 233 static const int patchOffsetGetByIdStructure = 10; 232 234 static const int patchOffsetGetByIdBranchToSlowCase = 20; 235 static const int patchOffsetGetByIdExternalLoad = 20; 236 static const int patchLengthGetByIdExternalLoad = 4; 233 237 static const int patchOffsetGetByIdPropertyMapOffset = 31; 234 238 static const int patchOffsetGetByIdPutResult = 31; … … 242 246 // These architecture specific value are used to enable patching - see comment on op_put_by_id. 243 247 static const int patchOffsetPutByIdStructure = 7; 248 static const int patchOffsetPutByIdExternalLoad = 13; 249 static const int patchLengthPutByIdExternalLoad = 3; 244 250 static const int patchOffsetPutByIdPropertyMapOffset = 22; 245 251 // These architecture specific value are used to enable patching - see comment on op_get_by_id. 246 252 static const int patchOffsetGetByIdStructure = 7; 247 253 static const int patchOffsetGetByIdBranchToSlowCase = 13; 254 static const int patchOffsetGetByIdExternalLoad = 13; 255 static const int patchLengthGetByIdExternalLoad = 3; 248 256 static const int patchOffsetGetByIdPropertyMapOffset = 22; 249 257 static const int patchOffsetGetByIdPutResult = 22; … … 380 388 enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq }; 381 389 void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type); 390 391 void compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset); 392 void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset); 393 void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset); 382 394 383 395 void compileFastArith_op_add(Instruction*); -
trunk/JavaScriptCore/jit/JITPropertyAccess.cpp
r43409 r43432 109 109 ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase); 110 110 111 loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0); 111 Label externalLoad(this); 112 loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_externalStorage)), regT0); 113 Label externalLoadComplete(this); 114 ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetGetByIdExternalLoad); 115 ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthGetByIdExternalLoad); 116 112 117 DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0); 113 118 ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetGetByIdPropertyMapOffset); … … 164 169 165 170 // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used. 166 loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0); 171 Label externalLoad(this); 172 loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_externalStorage)), regT0); 173 Label externalLoadComplete(this); 174 ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetPutByIdExternalLoad); 175 ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthPutByIdExternalLoad); 176 167 177 DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset)); 168 178 ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset); … … 182 192 // Track the location of the call; this will be used to recover patch information. 183 193 m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call; 194 } 195 196 // Compile a store into an object's property storage. May overwrite the 197 // value in objectReg. 198 void JIT::compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset) 199 { 200 int offset = cachedOffset * sizeof(JSValue); 201 if (structure->isUsingInlineStorage()) 202 offset += FIELD_OFFSET(JSObject, m_inlineStorage); 203 else 204 loadPtr(Address(base, FIELD_OFFSET(JSObject, m_externalStorage)), base); 205 storePtr(value, Address(base, offset)); 206 } 207 208 // Compile a load from an object's property storage. May overwrite base. 209 void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset) 210 { 211 int offset = cachedOffset * sizeof(JSValue); 212 if (structure->isUsingInlineStorage()) 213 offset += FIELD_OFFSET(JSObject, m_inlineStorage); 214 else 215 loadPtr(Address(base, FIELD_OFFSET(JSObject, m_externalStorage)), base); 216 loadPtr(Address(base, offset), result); 217 } 218 219 void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset) 220 { 221 if (base->isUsingInlineStorage()) 222 loadPtr(static_cast<void*>(&base->m_inlineStorage[cachedOffset]), result); 223 else { 224 PropertyStorage* protoPropertyStorage = &base->m_externalStorage; 225 loadPtr(static_cast<void*>(protoPropertyStorage), temp); 226 loadPtr(Address(temp, cachedOffset * sizeof(JSValue)), result); 227 } 184 228 } 185 229 … … 254 298 255 299 // write the value 256 loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0); 257 storePtr(regT1, Address(regT0, cachedOffset * sizeof(JSValue))); 300 compilePutDirectOffset(regT0, regT1, newStructure, cachedOffset); 258 301 259 302 ret(); … … 283 326 returnAddress.relinkCallerToFunction(JITStubs::cti_op_get_by_id_self_fail); 284 327 328 int offset = sizeof(JSValue) * cachedOffset; 329 330 // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load 331 // and makes the subsequent load's offset automatically correct 332 if (structure->isUsingInlineStorage()) 333 stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad).patchLoadToLEA(); 334 285 335 // Patch the offset into the propoerty map to load from, then patch the Structure to look for. 286 336 stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure).repatch(structure); 287 stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset).repatch( cachedOffset * sizeof(JSValue));337 stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset).repatch(offset); 288 338 } 289 339 … … 294 344 returnAddress.relinkCallerToFunction(JITStubs::cti_op_put_by_id_generic); 295 345 346 int offset = sizeof(JSValue) * cachedOffset; 347 348 // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load 349 // and makes the subsequent load's offset automatically correct 350 if (structure->isUsingInlineStorage()) 351 stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad).patchLoadToLEA(); 352 296 353 // Patch the offset into the propoerty map to load from, then patch the Structure to look for. 297 354 stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure).repatch(structure); 298 stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset).repatch( cachedOffset * sizeof(JSValue));355 stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset).repatch(offset); 299 356 } 300 357 … … 345 402 346 403 // Checks out okay! - getDirectOffset 347 loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0); 348 loadPtr(Address(regT0, cachedOffset * sizeof(JSValue)), regT0); 404 compileGetDirectOffset(regT0, regT0, structure, cachedOffset); 349 405 ret(); 350 406 … … 386 442 387 443 // Checks out okay! - getDirectOffset 388 PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; 389 loadPtr(static_cast<void*>(protoPropertyStorage), regT1); 390 loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0); 444 compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); 391 445 392 446 Jump success = jump(); … … 424 478 425 479 // Checks out okay! - getDirectOffset 426 PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; 427 loadPtr(protoPropertyStorage, regT1); 428 loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0); 480 compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); 429 481 430 482 ret(); … … 447 499 { 448 500 Jump failureCase = checkStructure(regT0, structure); 449 loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0); 450 loadPtr(Address(regT0, cachedOffset * sizeof(JSValue)), regT0); 501 compileGetDirectOffset(regT0, regT0, structure, cachedOffset); 451 502 Jump success = jump(); 452 503 … … 494 545 495 546 // Checks out okay! - getDirectOffset 496 PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; 497 loadPtr(protoPropertyStorage, regT1); 498 loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0); 547 compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); 499 548 500 549 Jump success = jump(); … … 550 599 ASSERT(protoObject); 551 600 552 PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; 553 loadPtr(protoPropertyStorage, regT1); 554 loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0); 601 compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); 555 602 Jump success = jump(); 556 603 … … 610 657 ASSERT(protoObject); 611 658 612 PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; 613 loadPtr(protoPropertyStorage, regT1); 614 loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0); 659 compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); 615 660 Jump success = jump(); 616 661 … … 658 703 ASSERT(protoObject); 659 704 660 PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; 661 loadPtr(protoPropertyStorage, regT1); 662 loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0); 705 compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); 706 compilePutDirectOffset(regT0, regT1, structure, cachedOffset); 663 707 ret(); 664 708 … … 680 724 681 725 // checks out okay! - putDirectOffset 682 loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0); 683 storePtr(regT1, Address(regT0, cachedOffset * sizeof(JSValue))); 726 compilePutDirectOffset(regT0, regT1, structure, cachedOffset); 684 727 ret(); 685 728 -
trunk/JavaScriptCore/runtime/JSObject.cpp
r43153 r43432 70 70 m_structure->mark(); 71 71 72 PropertyStorage storage = propertyStorage(); 73 72 74 size_t storageSize = m_structure->propertyStorageSize(); 73 75 for (size_t i = 0; i < storageSize; ++i) { 74 JSValue v = m_propertyStorage[i];76 JSValue v = JSValue::decode(storage[i]); 75 77 if (!v.marked()) 76 78 v.mark(); … … 472 474 offset = m_structure->removePropertyWithoutTransition(propertyName); 473 475 if (offset != WTF::notFound) 474 m_propertyStorage[offset] = jsUndefined();476 putDirectOffset(offset, jsUndefined()); 475 477 return; 476 478 } 477 479 478 480 RefPtr<Structure> structure = Structure::removePropertyTransition(m_structure, propertyName, offset); 481 setStructure(structure.release()); 479 482 if (offset != WTF::notFound) 480 m_propertyStorage[offset] = jsUndefined(); 481 setStructure(structure.release()); 483 putDirectOffset(offset, jsUndefined()); 482 484 } 483 485 -
trunk/JavaScriptCore/runtime/JSObject.h
r43153 r43432 52 52 }; 53 53 54 typedef JSValue* PropertyStorage; 54 typedef EncodedJSValue* PropertyStorage; 55 typedef EncodedJSValue const * ConstPropertyStorage; 55 56 56 57 class JSObject : public JSCell { … … 76 77 Structure* inheritorID(); 77 78 78 PropertyStorage& propertyStorage() { return m_propertyStorage; } 79 ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } 80 PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } 79 81 80 82 virtual UString className() const; … … 126 128 { 127 129 size_t offset = m_structure->get(propertyName); 128 return offset != WTF::notFound ? m_propertyStorage[offset] : JSValue(); 130 return offset != WTF::notFound ? getDirectOffset(offset) : JSValue(); 131 } 132 133 size_t getOffset(const Identifier& propertyName) 134 { 135 return m_structure->get(propertyName); 129 136 } 130 137 … … 141 148 } 142 149 143 size_t offsetForLocation(JSValue* location) 144 { 145 return location - m_propertyStorage; 150 size_t offsetForLocation(JSValue* location) const 151 { 152 return location - reinterpret_cast<JSValue const *>(propertyStorage()); 153 } 154 155 JSValue const * locationForOffset(size_t offset) const 156 { 157 return reinterpret_cast<JSValue const *>(&propertyStorage()[offset]); 146 158 } 147 159 148 160 JSValue* locationForOffset(size_t offset) 149 161 { 150 return &m_propertyStorage[offset];162 return reinterpret_cast<JSValue*>(&propertyStorage()[offset]); 151 163 } 152 164 … … 164 176 165 177 // Fast access to known property offsets. 166 JSValue getDirectOffset(size_t offset) { return m_propertyStorage[offset]; }167 void putDirectOffset(size_t offset, JSValue value) { m_propertyStorage[offset] = value; }178 JSValue getDirectOffset(size_t offset) const { return JSValue::decode(propertyStorage()[offset]); } 179 void putDirectOffset(size_t offset, JSValue value) { propertyStorage()[offset] = JSValue::encode(value); } 168 180 169 181 void fillGetterPropertySlot(PropertySlot&, JSValue* location); … … 182 194 void allocatePropertyStorage(size_t oldSize, size_t newSize); 183 195 void allocatePropertyStorageInline(size_t oldSize, size_t newSize); 184 bool usingInlineStorage() const { return m_propertyStorage == m_inlineStorage; }185 186 static const size_t inlineStorageCapacity = 2;196 bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); } 197 198 static const size_t inlineStorageCapacity = 3; 187 199 static const size_t nonInlineBaseStorageCapacity = 16; 188 200 … … 203 215 RefPtr<Structure> m_inheritorID; 204 216 205 PropertyStorage m_propertyStorage; 206 JSValue m_inlineStorage[inlineStorageCapacity]; 217 union { 218 PropertyStorage m_externalStorage; 219 EncodedJSValue m_inlineStorage[inlineStorageCapacity]; 220 }; 207 221 }; 208 222 … … 219 233 inline JSObject::JSObject(PassRefPtr<Structure> structure) 220 234 : JSCell(structure.releaseRef()) // ~JSObject balances this ref() 221 , m_propertyStorage(m_inlineStorage)222 235 { 223 236 ASSERT(m_structure); … … 230 243 { 231 244 ASSERT(m_structure); 232 if ( m_propertyStorage != m_inlineStorage)233 delete [] m_ propertyStorage;245 if (!isUsingInlineStorage()) 246 delete [] m_externalStorage; 234 247 m_structure->deref(); 235 248 } … … 258 271 return m_inheritorID.get(); 259 272 return createInheritorID(); 273 } 274 275 inline bool Structure::isUsingInlineStorage() const 276 { 277 return (propertyStorageCapacity() == JSObject::inlineStorageCapacity); 260 278 } 261 279 … … 395 413 if (checkReadOnly && currentAttributes & ReadOnly) 396 414 return; 397 m_propertyStorage[offset] = value;415 putDirectOffset(offset, value); 398 416 slot.setExistingProperty(this, offset); 399 417 return; … … 406 424 407 425 ASSERT(offset < m_structure->propertyStorageCapacity()); 408 m_propertyStorage[offset] = value;426 putDirectOffset(offset, value); 409 427 slot.setNewProperty(this, offset); 410 428 return; … … 418 436 419 437 ASSERT(offset < structure->propertyStorageCapacity()); 420 m_propertyStorage[offset] = value; 438 setStructure(structure.release()); 439 putDirectOffset(offset, value); 421 440 slot.setNewProperty(this, offset); 422 441 slot.setWasTransition(true); 423 setStructure(structure.release());424 442 return; 425 443 } … … 430 448 if (checkReadOnly && currentAttributes & ReadOnly) 431 449 return; 432 m_propertyStorage[offset] = value;450 putDirectOffset(offset, value); 433 451 slot.setExistingProperty(this, offset); 434 452 return; … … 440 458 441 459 ASSERT(offset < structure->propertyStorageCapacity()); 442 m_propertyStorage[offset] = value; 460 setStructure(structure.release()); 461 putDirectOffset(offset, value); 443 462 slot.setNewProperty(this, offset); 444 463 slot.setWasTransition(true); 445 setStructure(structure.release());446 464 } 447 465 … … 452 470 if (currentCapacity != m_structure->propertyStorageCapacity()) 453 471 allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); 454 m_propertyStorage[offset] = value;472 putDirectOffset(offset, value); 455 473 } 456 474 … … 541 559 ASSERT(newSize > oldSize); 542 560 543 JSValue* oldPropertyStorage = m_propertyStorage; 544 m_propertyStorage = new JSValue[newSize]; 561 // It's important that this function not rely on m_structure, since 562 // we might be in the middle of a transition. 563 bool wasInline = (oldSize == JSObject::inlineStorageCapacity); 564 565 PropertyStorage oldPropertyStorage = (wasInline ? m_inlineStorage : m_externalStorage); 566 PropertyStorage newPropertyStorage = new EncodedJSValue[newSize]; 545 567 546 568 for (unsigned i = 0; i < oldSize; ++i) 547 m_propertyStorage[i] = oldPropertyStorage[i];548 549 if ( oldPropertyStorage != m_inlineStorage)569 newPropertyStorage[i] = oldPropertyStorage[i]; 570 571 if (!wasInline) 550 572 delete [] oldPropertyStorage; 573 574 m_externalStorage = newPropertyStorage; 551 575 } 552 576 -
trunk/JavaScriptCore/runtime/Structure.h
r43317 r43432 96 96 size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; } 97 97 size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; } 98 bool isUsingInlineStorage() const; 98 99 99 100 size_t get(const Identifier& propertyName);
Note:
See TracChangeset
for help on using the changeset viewer.