Changeset 38688 in webkit
- Timestamp:
- Nov 21, 2008 7:34:43 PM (15 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r38682 r38688 1 2008-11-21 Gavin Barraclough <barraclough@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 Add (really) polymorphic caching for get by id self. 6 Very similar to caching of prototype accesses, described below. 7 8 Oh, also, probably shouldn't have been leaking those structure list objects. 9 10 4% preogression on deltablue. 11 12 * bytecode/CodeBlock.cpp: 13 (JSC::CodeBlock::dump): 14 (JSC::CodeBlock::derefStructures): 15 (JSC::PrototypeStructureList::derefStructures): 16 * bytecode/Instruction.h: 17 * bytecode/Opcode.h: 18 * interpreter/Interpreter.cpp: 19 (JSC::Interpreter::privateExecute): 20 (JSC::Interpreter::cti_op_get_by_id_self_fail): 21 * jit/JIT.cpp: 22 (JSC::JIT::privateCompileMainPass): 23 (JSC::JIT::privateCompileGetByIdSelfList): 24 (JSC::JIT::patchGetByIdSelf): 25 * jit/JIT.h: 26 (JSC::JIT::compileGetByIdSelfList): 27 1 28 2008-11-21 Geoffrey Garen <ggaren@apple.com> 2 29 -
trunk/JavaScriptCore/bytecode/CodeBlock.cpp
r38652 r38688 643 643 break; 644 644 } 645 case op_get_by_id_self_list: { 646 printGetByIdOp(location, it, identifiers, "get_by_id_self_list"); 647 break; 648 } 645 649 case op_get_by_id_proto: { 646 650 printGetByIdOp(location, it, identifiers, "get_by_id_proto"); … … 1024 1028 return; 1025 1029 } 1026 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list)) { 1027 PrototypeStructureList* prototypeStructures = vPC[4].u.prototypeStructure; 1028 int count = vPC[5].u.operand; 1029 for (int i = 0; i < count; ++i) { 1030 PrototypeStructureList::ProtoStubInfo& info = prototypeStructures->list[i]; 1031 ASSERT(info.base); 1032 ASSERT(info.proto); 1033 ASSERT(info.stubRoutine); 1034 info.base->deref(); 1035 info.proto->deref(); 1036 WTF::fastFreeExecutable(info.stubRoutine); 1037 } 1030 if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list)) 1031 || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) { 1032 PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures; 1033 polymorphicStructures->derefStructures(vPC[5].u.operand); 1034 delete polymorphicStructures; 1038 1035 return; 1039 1036 } -
trunk/JavaScriptCore/bytecode/Instruction.h
r38652 r38688 34 34 #include <wtf/VectorTraits.h> 35 35 36 #define P ROTOTYPE_LIST_CACHE_SIZE 436 #define POLYMORPHIC_LIST_CACHE_SIZE 4 37 37 38 38 namespace JSC { … … 43 43 44 44 // Structure used by op_get_by_id_proto_list instruction to hold data off the main opcode stream. 45 struct P rototypeStructureList {46 struct P rotoStubInfo {45 struct PolymorphicAccessStructureList { 46 struct PolymorphicStubInfo { 47 47 Structure* base; 48 48 Structure* proto; … … 57 57 stubRoutine = _stubRoutine; 58 58 } 59 } list[P ROTOTYPE_LIST_CACHE_SIZE];59 } list[POLYMORPHIC_LIST_CACHE_SIZE]; 60 60 61 P rototypeStructureList(Structure* firstBase, Structure* firstProto, int cachedOffset, void* stubRoutine)61 PolymorphicAccessStructureList(Structure* firstBase, Structure* firstProto, int cachedOffset, void* stubRoutine) 62 62 { 63 63 list[0].set(firstBase, firstProto, cachedOffset, stubRoutine); 64 } 65 66 void derefStructures(int count) 67 { 68 for (int i = 0; i < count; ++i) { 69 PolymorphicStubInfo& info = list[i]; 70 71 ASSERT(info.base); 72 info.base->deref(); 73 74 if (info.proto) 75 info.proto->deref(); 76 77 if (info.stubRoutine) 78 WTF::fastFreeExecutable(info.stubRoutine); 79 } 64 80 } 65 81 }; … … 78 94 Instruction(StructureChain* structureChain) { u.structureChain = structureChain; } 79 95 Instruction(JSCell* jsCell) { u.jsCell = jsCell; } 80 Instruction(P rototypeStructureList* prototypeStructure) { u.prototypeStructure = prototypeStructure; }96 Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; } 81 97 82 98 union { … … 87 103 JSCell* jsCell; 88 104 ResultType::Type resultType; 89 P rototypeStructureList* prototypeStructure;105 PolymorphicAccessStructureList* polymorphicStructures; 90 106 } u; 91 107 }; -
trunk/JavaScriptCore/bytecode/Opcode.h
r38652 r38688 102 102 macro(op_get_by_id) \ 103 103 macro(op_get_by_id_self) \ 104 macro(op_get_by_id_self_list) \ 104 105 macro(op_get_by_id_proto) \ 105 106 macro(op_get_by_id_proto_list) \ -
trunk/JavaScriptCore/interpreter/Interpreter.cpp
r38652 r38688 2587 2587 NEXT_INSTRUCTION(); 2588 2588 } 2589 DEFINE_OPCODE(op_get_by_id_self_list) { 2590 // Polymorphic self access caching currently only supported when JITting. 2591 ASSERT_NOT_REACHED(); 2592 // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)! 2593 vPC += 8; 2594 NEXT_INSTRUCTION(); 2595 } 2589 2596 DEFINE_OPCODE(op_get_by_id_proto_list) { 2590 2597 // Polymorphic prototype access caching currently only supported when JITting. … … 4594 4601 JSValue* result = baseValue->get(callFrame, ident, slot); 4595 4602 4596 CHECK_FOR_EXCEPTION_AT_END(); 4603 CHECK_FOR_EXCEPTION(); 4604 4605 if (baseValue->isObject() 4606 && slot.isCacheable() 4607 && !asCell(baseValue)->structure()->isDictionary() 4608 && slot.slotBase() == baseValue) { 4609 4610 CodeBlock* codeBlock = callFrame->codeBlock(); 4611 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); 4612 Instruction* vPC = codeBlock->instructions.begin() + vPCIndex; 4613 4614 ASSERT(slot.slotBase()->isObject()); 4615 4616 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(CTI_RETURN_ADDRESS); 4617 4618 PolymorphicAccessStructureList* polymorphicStructureList; 4619 int listIndex = 1; 4620 4621 if (vPC[0].u.opcode == ARG_globalData->interpreter->getOpcode(op_get_by_id_self)) { 4622 ASSERT(!stubInfo->stubRoutine); 4623 polymorphicStructureList = new PolymorphicAccessStructureList(vPC[4].u.structure, 0, vPC[5].u.operand, 0); 4624 4625 vPC[0] = ARG_globalData->interpreter->getOpcode(op_get_by_id_self_list); 4626 vPC[4] = polymorphicStructureList; 4627 vPC[5] = 2; 4628 } else { 4629 polymorphicStructureList = vPC[4].u.polymorphicStructures; 4630 listIndex = vPC[5].u.operand; 4631 4632 vPC[5] = listIndex + 1; 4633 } 4634 4635 JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset()); 4636 4637 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 4638 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic)); 4639 } else { 4640 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic)); 4641 } 4597 4642 return result; 4598 4643 } … … 4635 4680 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(CTI_RETURN_ADDRESS); 4636 4681 4637 P rototypeStructureList* prototypeStructureList;4682 PolymorphicAccessStructureList* prototypeStructureList; 4638 4683 int listIndex = 1; 4639 4684 4640 4685 if (vPC[0].u.opcode == ARG_globalData->interpreter->getOpcode(op_get_by_id_proto)) { 4641 prototypeStructureList = new P rototypeStructureList(vPC[4].u.structure, vPC[5].u.structure, vPC[6].u.operand, stubInfo->stubRoutine);4686 prototypeStructureList = new PolymorphicAccessStructureList(vPC[4].u.structure, vPC[5].u.structure, vPC[6].u.operand, stubInfo->stubRoutine); 4642 4687 stubInfo->stubRoutine = 0; 4643 4688 … … 4646 4691 vPC[5] = 2; 4647 4692 } else { 4648 prototypeStructureList = vPC[4].u.p rototypeStructure;4693 prototypeStructureList = vPC[4].u.polymorphicStructures; 4649 4694 listIndex = vPC[5].u.operand; 4650 4695 … … 4654 4699 JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset()); 4655 4700 4656 if (listIndex == (P ROTOTYPE_LIST_CACHE_SIZE - 1))4701 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 4657 4702 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full)); 4658 4703 } else { -
trunk/JavaScriptCore/jit/JIT.cpp
r38669 r38688 2360 2360 case op_get_by_id_proto_list: 2361 2361 case op_get_by_id_self: 2362 case op_get_by_id_self_list: 2362 2363 case op_get_string_length: 2363 2364 case op_put_by_id_generic: … … 3231 3232 3232 3233 #if USE(CTI_REPATCH_PIC) 3233 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PrototypeStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame) 3234 void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset) 3235 { 3236 JmpSrc failureCase = checkStructure(X86::eax, structure); 3237 __ movl_mr(FIELD_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax); 3238 __ movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax); 3239 JmpSrc success = __ jmp(); 3240 3241 void* code = __ executableCopy(); 3242 ASSERT(code); 3243 3244 // Use the repatch information to link the failure cases back to the original slow case routine. 3245 void* lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine; 3246 if (!lastProtoBegin) 3247 lastProtoBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - repatchOffsetGetByIdSlowCaseCall; 3248 3249 X86Assembler::link(code, failureCase, lastProtoBegin); 3250 3251 // On success return back to the hot patch code, at a point it will perform the store to dest for us. 3252 intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset; 3253 X86Assembler::link(code, success, reinterpret_cast<void*>(successDest)); 3254 3255 structure->ref(); 3256 polymorphicStructures->list[currentIndex].set(structure, 0, cachedOffset, 0/*code*/); 3257 3258 // Finally repatch the jump to slow case back in the hot path to jump here instead. 3259 intptr_t jmpLocation = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase; 3260 X86Assembler::repatchBranchOffset(jmpLocation, code); 3261 } 3262 3263 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame) 3234 3264 { 3235 3265 // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is … … 3667 3697 // We don't want to repatch more than once - in future go to cti_op_get_by_id_generic. 3668 3698 // Should probably go to Interpreter::cti_op_get_by_id_fail, but that doesn't do anything interesting right now. 3669 ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_ generic));3699 ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail)); 3670 3700 3671 3701 // Repatch the offset into the propoerty map to load from, then repatch the Structure to look for. -
trunk/JavaScriptCore/jit/JIT.h
r38652 r38688 110 110 struct Instruction; 111 111 struct OperandTypes; 112 struct P rototypeStructureList;112 struct PolymorphicAccessStructureList; 113 113 struct StructureStubInfo; 114 114 … … 321 321 322 322 #if USE(CTI_REPATCH_PIC) 323 static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PrototypeStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset) 323 static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset) 324 { 325 JIT jit(globalData, codeBlock); 326 jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, cachedOffset); 327 } 328 static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset) 324 329 { 325 330 JIT jit(globalData, codeBlock); … … 380 385 void privateCompileGetByIdProto(Structure*, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame); 381 386 #if USE(CTI_REPATCH_PIC) 382 void privateCompileGetByIdProtoList(StructureStubInfo*, PrototypeStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame); 387 void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset); 388 void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame); 383 389 #endif 384 390 void privateCompileGetByIdChain(Structure*, StructureChain*, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
Note: See TracChangeset
for help on using the changeset viewer.