Changeset 37831 in webkit for trunk/JavaScriptCore
- Timestamp:
- Oct 23, 2008, 3:29:54 PM (17 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r37820 r37831 1 2008-10-23 Gavin Barraclough <[email protected]> 2 3 Reviewed by Oliver Hunt. 4 5 Fix hideous pathological case performance when looking up repatch info, bug #21727. 6 7 When repatching JIT code to optimize we look up records providing information about 8 the generated code (also used to track recsources used in linking to be later released). 9 The lookup was being performed using a linear scan of all such records. 10 11 (1) Split up the different types of reptach information. This means we can search them 12 separately, and in some cases should reduce their size. 13 (2) In the case of property accesses, search with a binary chop over the data. 14 (3) In the case of calls, pass a pointer to the repatch info into the relink function. 15 16 * VM/CTI.cpp: 17 (JSC::CTI::CTI): 18 (JSC::CTI::compileOpCall): 19 (JSC::CTI::privateCompileMainPass): 20 (JSC::CTI::privateCompileSlowCases): 21 (JSC::CTI::privateCompile): 22 (JSC::CTI::unlinkCall): 23 (JSC::CTI::linkCall): 24 * VM/CTI.h: 25 * VM/CodeBlock.cpp: 26 (JSC::CodeBlock::dump): 27 (JSC::CodeBlock::~CodeBlock): 28 (JSC::CodeBlock::unlinkCallers): 29 (JSC::CodeBlock::derefStructureIDs): 30 * VM/CodeBlock.h: 31 (JSC::StructureStubInfo::StructureStubInfo): 32 (JSC::CallLinkInfo::CallLinkInfo): 33 (JSC::CallLinkInfo::setUnlinked): 34 (JSC::CallLinkInfo::isLinked): 35 (JSC::getStructureStubInfoReturnLocation): 36 (JSC::binaryChop): 37 (JSC::CodeBlock::addCaller): 38 (JSC::CodeBlock::getStubInfo): 39 * VM/CodeGenerator.cpp: 40 (JSC::CodeGenerator::emitResolve): 41 (JSC::CodeGenerator::emitGetById): 42 (JSC::CodeGenerator::emitPutById): 43 (JSC::CodeGenerator::emitCall): 44 (JSC::CodeGenerator::emitConstruct): 45 * VM/Machine.cpp: 46 (JSC::Machine::cti_vm_lazyLinkCall): 47 1 48 2008-10-23 Peter Kasting <[email protected]> 2 49 -
trunk/JavaScriptCore/VM/CTI.cpp
r37812 r37831 514 514 , m_codeBlock(codeBlock) 515 515 , m_labels(codeBlock ? codeBlock->instructions.size() : 0) 516 , m_structureStubCompilationInfo(codeBlock ? codeBlock->structureIDInstructions.size() : 0) 516 , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->propertyAccessInstructions.size() : 0) 517 , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->callLinkInfos.size() : 0) 517 518 { 518 519 } … … 577 578 } 578 579 579 void CTI::compileOpCall(Instruction* instruction, unsigned i, unsigned structureIDInstructionIndex, CompileOpCallType type)580 void CTI::compileOpCall(Instruction* instruction, unsigned i, unsigned callLinkInfoIndex, CompileOpCallType type) 580 581 { 581 582 int dst = instruction[1].u.operand; … … 615 616 m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); 616 617 ASSERT(X86Assembler::getDifferenceBetweenLabels(addressOfLinkedFunctionCheck, m_jit.label()) == repatchOffsetOpCallCall); 617 m_ structureStubCompilationInfo[structureIDInstructionIndex].hotPathBegin = addressOfLinkedFunctionCheck;618 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck; 618 619 619 620 // The following is the fast case, only used whan a callee can be linked. … … 639 640 640 641 // Call to the callee 641 m_ structureStubCompilationInfo[structureIDInstructionIndex].hotPathOther = emitNakedCall(i, unreachable);642 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(i, unreachable); 642 643 643 644 if (type == OpCallEval) … … 950 951 unsigned instructionCount = m_codeBlock->instructions.size(); 951 952 952 unsigned structureIDInstructionIndex = 0; 953 unsigned propertyAccessInstructionIndex = 0; 954 unsigned callLinkInfoIndex = 0; 953 955 954 956 for (unsigned i = 0; i < instructionCount; ) { … … 1095 1097 emitGetArg(instruction[i + 3].u.operand, X86::edx); 1096 1098 1097 ASSERT(m_codeBlock-> structureIDInstructions[structureIDInstructionIndex].opcodeIndex == i);1099 ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].opcodeIndex == i); 1098 1100 X86Assembler::JmpDst hotPathBegin = m_jit.label(); 1099 m_ structureStubCompilationInfo[structureIDInstructionIndex].hotPathBegin = hotPathBegin;1100 ++ structureIDInstructionIndex;1101 m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin; 1102 ++propertyAccessInstructionIndex; 1101 1103 1102 1104 // Jump to a slow case if either the base object is an immediate, or if the StructureID does not match. … … 1123 1125 emitGetArg(instruction[i + 2].u.operand, X86::eax); 1124 1126 1125 ASSERT(m_codeBlock-> structureIDInstructions[structureIDInstructionIndex].opcodeIndex == i);1127 ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].opcodeIndex == i); 1126 1128 1127 1129 X86Assembler::JmpDst hotPathBegin = m_jit.label(); 1128 m_ structureStubCompilationInfo[structureIDInstructionIndex].hotPathBegin = hotPathBegin;1129 ++ structureIDInstructionIndex;1130 m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin; 1131 ++propertyAccessInstructionIndex; 1130 1132 1131 1133 emitJumpSlowCaseIfNotJSCell(X86::eax, i); … … 1253 1255 } 1254 1256 case op_call: { 1255 compileOpCall(instruction + i, i, structureIDInstructionIndex++);1257 compileOpCall(instruction + i, i, callLinkInfoIndex++); 1256 1258 i += 7; 1257 1259 break; … … 1349 1351 } 1350 1352 case op_construct: { 1351 compileOpCall(instruction + i, i, structureIDInstructionIndex++, OpConstruct);1353 compileOpCall(instruction + i, i, callLinkInfoIndex++, OpConstruct); 1352 1354 i += 7; 1353 1355 break; … … 1491 1493 m_jit.movl_mr(structureIDAddr, X86::edx); 1492 1494 m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSCell, m_structureID), X86::eax); 1493 X86Assembler::JmpSrc slowCase = m_jit.emitUnlinkedJne(); // StructureIDs don't match 1494 m_slowCases.append(SlowCaseEntry(slowCase, i)); 1495 X86Assembler::JmpSrc noMatch = m_jit.emitUnlinkedJne(); // StructureIDs don't match 1495 1496 1496 1497 // Load cached property … … 1502 1503 1503 1504 // Slow case 1504 m_jit.link( slowCase, m_jit.label());1505 m_jit.link(noMatch, m_jit.label()); 1505 1506 emitPutArgConstant(globalObject, 0); 1506 1507 emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4); … … 1510 1511 m_jit.link(end, m_jit.label()); 1511 1512 i += 6; 1512 ++structureIDInstructionIndex;1513 1513 break; 1514 1514 } … … 1842 1842 } 1843 1843 case op_call_eval: { 1844 compileOpCall(instruction + i, i, structureIDInstructionIndex++, OpCallEval);1844 compileOpCall(instruction + i, i, callLinkInfoIndex++, OpCallEval); 1845 1845 i += 7; 1846 1846 break; … … 2193 2193 } 2194 2194 2195 ASSERT(structureIDInstructionIndex == m_codeBlock->structureIDInstructions.size()); 2195 ASSERT(propertyAccessInstructionIndex == m_codeBlock->propertyAccessInstructions.size()); 2196 ASSERT(callLinkInfoIndex == m_codeBlock->callLinkInfos.size()); 2196 2197 } 2197 2198 … … 2218 2219 void CTI::privateCompileSlowCases() 2219 2220 { 2220 unsigned structureIDInstructionIndex = 0; 2221 unsigned propertyAccessInstructionIndex = 0; 2222 unsigned callLinkInfoIndex = 0; 2221 2223 2222 2224 Instruction* instruction = m_codeBlock->instructions.begin(); … … 2362 2364 2363 2365 // Track the location of the call; this will be used to recover repatch information. 2364 ASSERT(m_codeBlock-> structureIDInstructions[structureIDInstructionIndex].opcodeIndex == i);2365 m_ structureStubCompilationInfo[structureIDInstructionIndex].callReturnLocation = call;2366 ++ structureIDInstructionIndex;2366 ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].opcodeIndex == i); 2367 m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call; 2368 ++propertyAccessInstructionIndex; 2367 2369 2368 2370 i += 8; … … 2390 2392 2391 2393 // Track the location of the call; this will be used to recover repatch information. 2392 ASSERT(m_codeBlock-> structureIDInstructions[structureIDInstructionIndex].opcodeIndex == i);2393 m_ structureStubCompilationInfo[structureIDInstructionIndex].callReturnLocation = call;2394 ++ structureIDInstructionIndex;2394 ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].opcodeIndex == i); 2395 m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call; 2396 ++propertyAccessInstructionIndex; 2395 2397 2396 2398 i += 8; 2397 break;2398 }2399 case op_resolve_global: {2400 ++structureIDInstructionIndex;2401 i += 6;2402 2399 break; 2403 2400 } … … 2711 2708 2712 2709 // Try to link & repatch this call. 2713 m_structureStubCompilationInfo[structureIDInstructionIndex].callReturnLocation = 2710 CallLinkInfo* info = &(m_codeBlock->callLinkInfos[callLinkInfoIndex]); 2711 emitPutArgConstant(reinterpret_cast<unsigned>(info), 4); 2712 m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = 2714 2713 emitCTICall(i, Machine::cti_vm_lazyLinkCall); 2715 2714 emitNakedCall(i, X86::eax); … … 2717 2716 2718 2717 // This is the address for the cold path *after* the first run (which tries to link the call). 2719 m_ structureStubCompilationInfo[structureIDInstructionIndex].coldPathOther = m_jit.label();2718 m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther = m_jit.label(); 2720 2719 2721 2720 // The arguments have been set up on the hot path for op_call_eval … … 2764 2763 emitPutResult(dst); 2765 2764 2766 ++ structureIDInstructionIndex;2765 ++callLinkInfoIndex; 2767 2766 i += 7; 2768 2767 break; … … 2788 2787 } 2789 2788 2790 ASSERT(structureIDInstructionIndex == m_codeBlock->structureIDInstructions.size()); 2789 ASSERT(propertyAccessInstructionIndex == m_codeBlock->propertyAccessInstructions.size()); 2790 ASSERT(callLinkInfoIndex == m_codeBlock->callLinkInfos.size()); 2791 2791 } 2792 2792 … … 2867 2867 X86Assembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target); 2868 2868 2869 for (unsigned i = 0; i < m_codeBlock->structureIDInstructions.size(); ++i) { 2870 StructureStubInfo& info = m_codeBlock->structureIDInstructions[i]; 2871 info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].callReturnLocation); 2872 info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].hotPathBegin); 2873 info.hotPathOther = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].hotPathOther); 2874 info.coldPathOther = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].coldPathOther); 2869 for (unsigned i = 0; i < m_codeBlock->propertyAccessInstructions.size(); ++i) { 2870 StructureStubInfo& info = m_codeBlock->propertyAccessInstructions[i]; 2871 info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].callReturnLocation); 2872 info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].hotPathBegin); 2873 } 2874 for (unsigned i = 0; i < m_codeBlock->callLinkInfos.size(); ++i) { 2875 CallLinkInfo& info = m_codeBlock->callLinkInfos[i]; 2876 info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].callReturnLocation); 2877 info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathBegin); 2878 info.hotPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathOther); 2879 info.coldPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].coldPathOther); 2875 2880 } 2876 2881 … … 3155 3160 } 3156 3161 3157 void CTI::unlinkCall( StructureStubInfo* structureStubInfo)3162 void CTI::unlinkCall(CallLinkInfo* callLinkInfo) 3158 3163 { 3159 3164 // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid 3160 3165 // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive 3161 3166 // match). Reset the check so it no longer matches. 3162 reinterpret_cast<void**>(structureStubInfo->hotPathBegin)[-1] = asPointer(JSImmediate::impossibleValue()); 3163 } 3164 3165 void CTI::linkCall(CodeBlock* callerCodeBlock, JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, void* returnAddress, int callerArgCount) 3166 { 3167 StructureStubInfo& stubInfo = callerCodeBlock->getStubInfo(returnAddress); 3168 3167 reinterpret_cast<void**>(callLinkInfo->hotPathBegin)[-1] = asPointer(JSImmediate::impossibleValue()); 3168 } 3169 3170 void CTI::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount) 3171 { 3169 3172 // Currently we only link calls with the exact number of arguments. 3170 3173 if (callerArgCount == calleeCodeBlock->numParameters) { 3171 ASSERT(! stubInfo.linkInfoPtr);3174 ASSERT(!callLinkInfo->isLinked()); 3172 3175 3173 calleeCodeBlock->addCaller( &stubInfo);3176 calleeCodeBlock->addCaller(callLinkInfo); 3174 3177 3175 reinterpret_cast<void**>( stubInfo.hotPathBegin)[-1] = callee;3176 ctiRepatchCallByReturnAddress( stubInfo.hotPathOther, ctiCode);3178 reinterpret_cast<void**>(callLinkInfo->hotPathBegin)[-1] = callee; 3179 ctiRepatchCallByReturnAddress(callLinkInfo->hotPathOther, ctiCode); 3177 3180 } 3178 3181 3179 3182 // repatch the instruction that jumps out to the cold path, so that we only try to link once. 3180 void* repatchCheck = reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>( stubInfo.hotPathBegin) + repatchOffsetOpCallCall);3181 ctiRepatchCallByReturnAddress(repatchCheck, stubInfo.coldPathOther);3183 void* repatchCheck = reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(callLinkInfo->hotPathBegin) + repatchOffsetOpCallCall); 3184 ctiRepatchCallByReturnAddress(repatchCheck, callLinkInfo->coldPathOther); 3182 3185 } 3183 3186 -
trunk/JavaScriptCore/VM/CTI.h
r37728 r37831 80 80 #define ARG_instr5 static_cast<Instruction*>(ARGS[5]) 81 81 #define ARG_instr6 static_cast<Instruction*>(ARGS[6]) 82 #define ARG_linkInfo2 static_cast<CallLinkInfo*>(ARGS[2]) 82 83 83 84 #define CTI_RETURN_ADDRESS_SLOT (ARGS[-1]) … … 95 96 class StructureIDChain; 96 97 98 struct CallLinkInfo; 97 99 struct Instruction; 98 100 struct OperandTypes; 99 struct StructureStubInfo;100 101 101 102 typedef JSValue* (SFX_CALL *CTIHelper_j)(CTI_ARGS); … … 335 336 } 336 337 337 static void linkCall( CodeBlock* callerCodeBlock, JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, void* returnAddress, int callerArgCount);338 static void unlinkCall( StructureStubInfo*);338 static void linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount); 339 static void unlinkCall(CallLinkInfo*); 339 340 340 341 inline static JSValuePtr execute(void* code, RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValuePtr* exception) … … 434 435 Vector<CallRecord> m_calls; 435 436 Vector<X86Assembler::JmpDst> m_labels; 436 Vector<StructureStubCompilationInfo> m_structureStubCompilationInfo; 437 Vector<StructureStubCompilationInfo> m_propertyAccessCompilationInfo; 438 Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo; 437 439 Vector<JmpTable> m_jmpTable; 438 440 -
trunk/JavaScriptCore/VM/CodeBlock.cpp
r37804 r37831 276 276 } 277 277 278 if ( structureIDInstructions.size()) {278 if (globalResolveInstructions.size() || propertyAccessInstructions.size()) 279 279 printf("\nStructureIDs:\n"); 280 281 if (globalResolveInstructions.size()) { 280 282 size_t i = 0; 281 283 do { 282 printStructureIDs(&instructions[ structureIDInstructions[i].opcodeIndex]);284 printStructureIDs(&instructions[globalResolveInstructions[i]]); 283 285 ++i; 284 } while (i < structureIDInstructions.size()); 286 } while (i < globalResolveInstructions.size()); 287 } 288 if (propertyAccessInstructions.size()) { 289 size_t i = 0; 290 do { 291 printStructureIDs(&instructions[propertyAccessInstructions[i].opcodeIndex]); 292 ++i; 293 } while (i < propertyAccessInstructions.size()); 285 294 } 286 295 … … 942 951 CodeBlock::~CodeBlock() 943 952 { 944 size_t size = structureIDInstructions.size(); 945 for (size_t i = 0; i < size; ++i) { 946 derefStructureIDs(&instructions[structureIDInstructions[i].opcodeIndex]); 947 if (structureIDInstructions[i].stubRoutine) 948 WTF::fastFreeExecutable(structureIDInstructions[i].stubRoutine); 949 if (CallLinkInfo* callLinkInfo = structureIDInstructions[i].linkInfoPtr) { 953 for (size_t size = globalResolveInstructions.size(), i = 0; i < size; ++i) { 954 derefStructureIDs(&instructions[globalResolveInstructions[i]]); 955 } 956 957 for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) { 958 derefStructureIDs(&instructions[propertyAccessInstructions[i].opcodeIndex]); 959 if (propertyAccessInstructions[i].stubRoutine) 960 WTF::fastFreeExecutable(propertyAccessInstructions[i].stubRoutine); 961 } 962 963 for (size_t size = callLinkInfos.size(), i = 0; i < size; ++i) { 964 CallLinkInfo* callLinkInfo = &callLinkInfos[i]; 965 if (callLinkInfo->isLinked()) 950 966 callLinkInfo->callee->removeCaller(callLinkInfo); 951 delete callLinkInfo;952 }953 967 } 954 968 … … 967 981 for (size_t i = 0; i < size; ++i) { 968 982 CallLinkInfo* currentCaller = linkedCallerList[i]; 969 CTI::unlinkCall(currentCaller->callerStructureStubInfo); 970 currentCaller->callerStructureStubInfo->linkInfoPtr = 0; 971 delete currentCaller; 983 CTI::unlinkCall(currentCaller); 984 currentCaller->setUnlinked(); 972 985 } 973 986 linkedCallerList.clear(); … … 1010 1023 1011 1024 // These instructions don't ref their StructureIDs. 1012 ASSERT(vPC[0].u.opcode == machine->getOpcode(op_get_by_id) || vPC[0].u.opcode == machine->getOpcode(op_put_by_id) || vPC[0].u.opcode == machine->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == machine->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == machine->getOpcode(op_get_array_length) || vPC[0].u.opcode == machine->getOpcode(op_get_string_length) 1013 || vPC[0].u.opcode == machine->getOpcode(op_call_eval) || vPC[0].u.opcode == machine->getOpcode(op_call) || vPC[0].u.opcode == machine->getOpcode(op_construct)); 1025 ASSERT(vPC[0].u.opcode == machine->getOpcode(op_get_by_id) || vPC[0].u.opcode == machine->getOpcode(op_put_by_id) || vPC[0].u.opcode == machine->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == machine->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == machine->getOpcode(op_get_array_length) || vPC[0].u.opcode == machine->getOpcode(op_get_string_length)); 1014 1026 } 1015 1027 -
trunk/JavaScriptCore/VM/CodeBlock.h
r37684 r37831 79 79 }; 80 80 81 struct CallLinkInfo;82 83 81 struct StructureStubInfo { 84 82 StructureStubInfo(unsigned opcodeIndex) … … 87 85 , callReturnLocation(0) 88 86 , hotPathBegin(0) 89 , hotPathOther(0)90 , coldPathOther(0)91 , linkInfoPtr(0)92 87 { 93 88 } … … 97 92 void* callReturnLocation; 98 93 void* hotPathBegin; 94 }; 95 96 struct CallLinkInfo { 97 CallLinkInfo() 98 : callReturnLocation(0) 99 , hotPathBegin(0) 100 , hotPathOther(0) 101 , coldPathOther(0) 102 , callee(0) 103 { 104 } 105 106 unsigned opcodeIndex; 107 void* callReturnLocation; 108 void* hotPathBegin; 99 109 void* hotPathOther; 100 110 void* coldPathOther; 101 CallLinkInfo* linkInfoPtr;102 };103 104 struct CallLinkInfo {105 111 CodeBlock* callee; 106 StructureStubInfo* callerStructureStubInfo;107 112 unsigned position; 108 109 CallLinkInfo(CodeBlock* c, StructureStubInfo* css) 110 { 111 callee = c; 112 callerStructureStubInfo = css; 113 } 114 }; 113 114 void setUnlinked() { callee = 0; } 115 bool isLinked() { return callee; } 116 }; 117 118 inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo) 119 { 120 return structureStubInfo->callReturnLocation; 121 } 122 123 // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array, 124 // compares result with key (KeyTypes should be comparable with '--', '<', '>'). 125 // Optimized for cases where the array contains the key, checked by assertions. 126 template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)> 127 inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key) 128 { 129 // The array must contain at least one element (pre-condition, array does conatin key). 130 // If the array only contains one element, no need to do the comparison. 131 while (size > 1) { 132 // Pick an element to check, half way through the array, and read the value. 133 int pos = (size - 1) >> 1; 134 KeyType val = valueAtPosition(&array[pos]); 135 136 // If the key matches, success! 137 if (val == key) 138 return &array[pos]; 139 // The item we are looking for is smaller than the item being check; reduce the value of 'size', 140 // chopping off the right hand half of the array. 141 else if (key < val) 142 size = pos; 143 // Discard all values in the left hand half of the array, up to and including the item at pos. 144 else { 145 size -= (pos + 1); 146 array += (pos + 1); 147 } 148 149 // 'size' should never reach zero. 150 ASSERT(size); 151 } 152 153 // If we reach this point we've chopped down to one element, no need to check it matches 154 ASSERT(size == 1); 155 ASSERT(key == valueAtPosition(&array[0])); 156 return &array[0]; 157 } 115 158 116 159 struct StringJumpTable { … … 228 271 #endif 229 272 230 void addCaller(StructureStubInfo* caller) 231 { 232 CallLinkInfo* callLinkInfo = new CallLinkInfo(this, caller); 233 caller->linkInfoPtr = callLinkInfo; 234 callLinkInfo->position = linkedCallerList.size(); 235 linkedCallerList.append(callLinkInfo); 273 void addCaller(CallLinkInfo* caller) 274 { 275 caller->callee = this; 276 caller->position = linkedCallerList.size(); 277 linkedCallerList.append(caller); 236 278 } 237 279 … … 264 306 StructureStubInfo& getStubInfo(void* returnAddress) 265 307 { 266 // FIXME: would a binary chop be faster here? 267 for (unsigned i = 0; ; ++i) { 268 ASSERT(i < structureIDInstructions.size()); 269 if (structureIDInstructions[i].callReturnLocation == returnAddress) 270 return structureIDInstructions[i]; 271 } 308 return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(propertyAccessInstructions.begin(), propertyAccessInstructions.size(), returnAddress)); 272 309 } 273 310 … … 296 333 297 334 Vector<Instruction> instructions; 298 Vector<StructureStubInfo> structureIDInstructions; 335 Vector<unsigned> globalResolveInstructions; 336 Vector<StructureStubInfo> propertyAccessInstructions; 337 Vector<CallLinkInfo> callLinkInfos; 299 338 Vector<CallLinkInfo*> linkedCallerList; 300 339 -
trunk/JavaScriptCore/VM/CodeGenerator.cpp
r37812 r37831 966 966 967 967 if (globalObject) { 968 m_codeBlock-> structureIDInstructions.append(instructions().size());968 m_codeBlock->globalResolveInstructions.append(instructions().size()); 969 969 emitOpcode(op_resolve_global); 970 970 instructions().append(dst->index()); … … 1046 1046 RegisterID* CodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property) 1047 1047 { 1048 m_codeBlock-> structureIDInstructions.append(instructions().size());1048 m_codeBlock->propertyAccessInstructions.append(instructions().size()); 1049 1049 1050 1050 emitOpcode(op_get_by_id); … … 1061 1061 RegisterID* CodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value) 1062 1062 { 1063 m_codeBlock-> structureIDInstructions.append(instructions().size());1063 m_codeBlock->propertyAccessInstructions.append(instructions().size()); 1064 1064 1065 1065 emitOpcode(op_put_by_id); … … 1220 1220 1221 1221 emitExpressionInfo(divot, startOffset, endOffset); 1222 m_codeBlock-> structureIDInstructions.append(instructions().size());1222 m_codeBlock->callLinkInfos.append(CallLinkInfo()); 1223 1223 emitOpcode(opcodeID); 1224 1224 instructions().append(dst->index()); … … 1284 1284 1285 1285 emitExpressionInfo(divot, startOffset, endOffset); 1286 m_codeBlock-> structureIDInstructions.append(instructions().size());1286 m_codeBlock->callLinkInfos.append(CallLinkInfo()); 1287 1287 emitOpcode(op_construct); 1288 1288 instructions().append(dst->index()); -
trunk/JavaScriptCore/VM/Machine.cpp
r37812 r37831 4742 4742 Machine* machine = ARG_globalData->machine; 4743 4743 CallFrame* callFrame = CallFrame::create(ARG_callFrame); 4744 CallFrame* callerCallFrame = callFrame->callerFrame();4745 CodeBlock* callerCodeBlock = callerCallFrame->codeBlock();4746 4744 4747 4745 JSFunction* callee = asFunction(ARG_src1); … … 4750 4748 CTI::compile(machine, callFrame, codeBlock); 4751 4749 4752 int argCount = ARG_int3; 4753 CTI::linkCall(callerCodeBlock, callee, codeBlock, codeBlock->ctiCode, CTI_RETURN_ADDRESS, argCount); 4750 CTI::linkCall(callee, codeBlock, codeBlock->ctiCode, ARG_linkInfo2, ARG_int3); 4754 4751 4755 4752 return codeBlock->ctiCode;
Note:
See TracChangeset
for help on using the changeset viewer.