Changeset 121073 in webkit for trunk/Source/JavaScriptCore
- Timestamp:
- Jun 22, 2012, 4:32:59 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r121058 r121073 1 2012-06-22 Filip Pizlo <[email protected]> 2 3 DFG tier-up should happen in prologues, not epilogues 4 https://bugs.webkit.org/show_bug.cgi?id=89752 5 6 Reviewed by Geoffrey Garen. 7 8 This change has two outcomes: 9 10 1) Slightly reduces the likelihood that a function will be optimized both 11 standalone and via inlining. Previously, if you had a call sequence like foo() 12 calls bar() exactly once, and nobody else calls bar(), then bar() would get 13 optimized first (because it returns first) and then foo() gets optimized. If foo() 14 can inline bar() then that means that bar() gets optimized twice. But now, if we 15 optimize in prologues, then foo() will be optimized first. If it inlines bar(), 16 that means that there will no longer be any calls to bar(). 17 18 2) It lets us kill some code in JITStubs. Epilogue tier-up was very different from 19 loop tier-up, since epilogue tier-up should not attempt OSR. But prologue tier-up 20 requires OSR (albeit really easy OSR since it's the top of the compilation unit), 21 so it becomes just like loop tier-up. As a result, we now have one optimization 22 hook (cti_optimize) instead of two (cti_optimize_from_loop and 23 cti_optimize_from_ret). 24 25 As a consequence of not having an optimization check in epilogues, the OSR exit 26 code must now trigger reoptimization itself instead of just signaling the epilogue 27 check to fire. 28 29 This also adds the ability to count the number of DFG compilations, which was 30 useful for debugging this patch and might be useful for other things in the future. 31 32 * bytecode/CodeBlock.cpp: 33 (JSC::CodeBlock::reoptimize): 34 (JSC): 35 * bytecode/CodeBlock.h: 36 (CodeBlock): 37 * dfg/DFGByteCodeParser.cpp: 38 (JSC::DFG::ByteCodeParser::parseCodeBlock): 39 * dfg/DFGDriver.cpp: 40 (DFG): 41 (JSC::DFG::getNumCompilations): 42 (JSC::DFG::compile): 43 * dfg/DFGDriver.h: 44 (DFG): 45 * dfg/DFGOSRExitCompiler.cpp: 46 (JSC::DFG::OSRExitCompiler::handleExitCounts): 47 * dfg/DFGOperations.cpp: 48 * dfg/DFGOperations.h: 49 * jit/JIT.cpp: 50 (JSC::JIT::emitOptimizationCheck): 51 * jit/JIT.h: 52 * jit/JITCall32_64.cpp: 53 (JSC::JIT::emit_op_ret): 54 (JSC::JIT::emit_op_ret_object_or_this): 55 * jit/JITOpcodes.cpp: 56 (JSC::JIT::emit_op_ret): 57 (JSC::JIT::emit_op_ret_object_or_this): 58 (JSC::JIT::emit_op_enter): 59 * jit/JITOpcodes32_64.cpp: 60 (JSC::JIT::emit_op_enter): 61 * jit/JITStubs.cpp: 62 (JSC::DEFINE_STUB_FUNCTION): 63 * jit/JITStubs.h: 64 1 65 2012-06-20 Mark Hahnenberg <[email protected]> 2 66 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r120989 r121073 2465 2465 2466 2466 #if ENABLE(JIT) 2467 void CodeBlock::reoptimize() 2468 { 2469 ASSERT(replacement() != this); 2470 ASSERT(replacement()->alternative() == this); 2471 replacement()->tallyFrequentExitSites(); 2472 replacement()->jettison(); 2473 countReoptimization(); 2474 optimizeAfterWarmUp(); 2475 } 2476 2467 2477 CodeBlock* ProgramCodeBlock::replacement() 2468 2478 { -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r120941 r121073 1106 1106 1107 1107 #if ENABLE(JIT) 1108 void reoptimize() 1109 { 1110 ASSERT(replacement() != this); 1111 ASSERT(replacement()->alternative() == this); 1112 replacement()->tallyFrequentExitSites(); 1113 replacement()->jettison(); 1114 countReoptimization(); 1115 optimizeAfterWarmUp(); 1116 } 1108 void reoptimize(); 1117 1109 #endif 1118 1110 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r120989 r121073 3258 3258 m_inlineStackTop->m_unlinkedBlocks.append(UnlinkedBlock(m_graph.m_blocks.size())); 3259 3259 m_inlineStackTop->m_blockLinkingTargets.append(m_graph.m_blocks.size()); 3260 // The first block is definitely an OSR target. 3261 if (!m_graph.m_blocks.size()) 3262 block->isOSRTarget = true; 3260 3263 m_graph.m_blocks.append(block.release()); 3261 3264 prepareToParseBlock(); -
trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp
r120834 r121073 44 44 namespace JSC { namespace DFG { 45 45 46 static unsigned numCompilations; 47 48 unsigned getNumCompilations() 49 { 50 return numCompilations; 51 } 52 46 53 enum CompileMode { CompileFunction, CompileOther }; 47 54 inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck) 48 55 { 49 56 SamplingRegion samplingRegion("DFG Compilation (Driver)"); 57 58 numCompilations++; 50 59 51 60 ASSERT(codeBlock); -
trunk/Source/JavaScriptCore/dfg/DFGDriver.h
r117823 r121073 39 39 namespace DFG { 40 40 41 JS_EXPORT_PRIVATE unsigned getNumCompilations(); 42 41 43 #if ENABLE(DFG_JIT) 42 44 bool tryCompile(ExecState*, CodeBlock*, JITCode&); -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
r120786 r121073 116 116 m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter())); 117 117 118 m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0); 119 118 120 tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(Options::forcedOSRExitCountForReoptimization))); 121 119 122 } else { 120 123 // Proceed based on the assumption that we can handle these exits so long as they … … 137 140 138 141 // Reoptimize as soon as possible. 139 m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); 140 m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); 142 #if !NUMBER_OF_ARGUMENT_REGISTERS 143 m_jit.poke(GPRInfo::regT0); 144 #else 145 m_jit.move(GPRInfo::regT0, GPRInfo::argumentGPR0); 146 ASSERT(GPRInfo::argumentGPR0 != GPRInfo::regT1); 147 #endif 148 m_jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(triggerReoptimizationNow)), GPRInfo::regT1); 149 m_jit.call(GPRInfo::regT1); 141 150 AssemblyHelpers::Jump doneAdjusting = m_jit.jump(); 142 151 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r120989 r121073 33 33 #include "HostCallReturnValue.h" 34 34 #include "GetterSetter.h" 35 #include <wtf/InlineASM.h>36 35 #include "Interpreter.h" 36 #include "JIT.h" 37 37 #include "JITExceptions.h" 38 38 #include "JSActivation.h" … … 41 41 #include "NameInstance.h" 42 42 #include "Operations.h" 43 #include <wtf/InlineASM.h> 43 44 44 45 #if ENABLE(DFG_JIT) … … 1251 1252 } 1252 1253 #endif 1254 1255 extern "C" void DFG_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock) 1256 { 1257 #if ENABLE(JIT_VERBOSE_OSR) 1258 dataLog("%p: Entered reoptimize\n", codeBlock); 1259 #endif 1260 // We must be called with the baseline code block. 1261 ASSERT(JITCode::isBaselineCode(codeBlock->getJITType())); 1262 1263 // If I am my own replacement, then reoptimization has already been triggered. 1264 // This can happen in recursive functions. 1265 if (codeBlock->replacement() == codeBlock) 1266 return; 1267 1268 // Otherwise, the replacement must be optimized code. Use this as an opportunity 1269 // to check our logic. 1270 ASSERT(codeBlock->hasOptimizedReplacement()); 1271 ASSERT(codeBlock->replacement()->getJITType() == JITCode::DFGJIT); 1272 1273 codeBlock->reoptimize(); 1274 } 1253 1275 1254 1276 } // extern "C" -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r120989 r121073 228 228 #endif 229 229 230 void DFG_OPERATION triggerReoptimizationNow(CodeBlock*) WTF_INTERNAL; 231 230 232 } // extern "C" 231 233 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r120786 r121073 101 101 102 102 Jump skipOptimize = branchAdd32(Signed, TrustedImm32(kind == LoopOptimizationCheck ? Options::executionCounterIncrementForLoop : Options::executionCounterIncrementForReturn), AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter())); 103 JITStubCall stubCall(this, kind == LoopOptimizationCheck ? cti_optimize_from_loop : cti_optimize_from_ret); 104 if (kind == LoopOptimizationCheck) 105 stubCall.addArgument(TrustedImm32(m_bytecodeOffset)); 103 JITStubCall stubCall(this, cti_optimize); 104 stubCall.addArgument(TrustedImm32(m_bytecodeOffset)); 105 if (kind == EnterOptimizationCheck) 106 ASSERT(!m_bytecodeOffset); 106 107 stubCall.call(); 107 108 skipOptimize.link(this); -
trunk/Source/JavaScriptCore/jit/JIT.h
r120244 r121073 807 807 void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures); 808 808 809 enum OptimizationCheckKind { LoopOptimizationCheck, RetOptimizationCheck };809 enum OptimizationCheckKind { LoopOptimizationCheck, EnterOptimizationCheck }; 810 810 #if ENABLE(DFG_JIT) 811 811 void emitOptimizationCheck(OptimizationCheckKind); -
trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp
r114959 r121073 57 57 void JIT::emit_op_ret(Instruction* currentInstruction) 58 58 { 59 emitOptimizationCheck(RetOptimizationCheck);60 61 59 unsigned dst = currentInstruction[1].u.operand; 62 60 … … 71 69 void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) 72 70 { 73 emitOptimizationCheck(RetOptimizationCheck);74 75 71 unsigned result = currentInstruction[1].u.operand; 76 72 unsigned thisReg = currentInstruction[2].u.operand; -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r120786 r121073 577 577 void JIT::emit_op_ret(Instruction* currentInstruction) 578 578 { 579 emitOptimizationCheck(RetOptimizationCheck);580 581 579 ASSERT(callFrameRegister != regT1); 582 580 ASSERT(regT1 != returnValueRegister); … … 599 597 void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) 600 598 { 601 emitOptimizationCheck(RetOptimizationCheck);602 603 599 ASSERT(callFrameRegister != regT1); 604 600 ASSERT(regT1 != returnValueRegister); … … 1219 1215 void JIT::emit_op_enter(Instruction*) 1220 1216 { 1217 emitOptimizationCheck(EnterOptimizationCheck); 1218 1221 1219 // Even though CTI doesn't use them, we initialize our constant 1222 1220 // registers to zap stale pointers, to avoid unnecessarily prolonging … … 1225 1223 for (size_t j = 0; j < count; ++j) 1226 1224 emitInitRegister(j); 1227 1228 1225 } 1229 1226 -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r120786 r121073 1488 1488 void JIT::emit_op_enter(Instruction*) 1489 1489 { 1490 emitOptimizationCheck(EnterOptimizationCheck); 1491 1490 1492 // Even though JIT code doesn't use them, we initialize our constant 1491 1493 // registers to zap stale pointers, to avoid unnecessarily prolonging -
trunk/Source/JavaScriptCore/jit/JITStubs.cpp
r120499 r121073 1920 1920 1921 1921 #if ENABLE(DFG_JIT) 1922 DEFINE_STUB_FUNCTION(void, optimize _from_loop)1922 DEFINE_STUB_FUNCTION(void, optimize) 1923 1923 { 1924 1924 STUB_INIT_STACK_FRAME(stackFrame); … … 1926 1926 CallFrame* callFrame = stackFrame.callFrame; 1927 1927 CodeBlock* codeBlock = callFrame->codeBlock(); 1928 1929 1928 unsigned bytecodeIndex = stackFrame.args[0].int32(); 1930 1929 1931 1930 #if ENABLE(JIT_VERBOSE_OSR) 1932 dataLog("%p: Entered optimize _from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());1931 dataLog("%p: Entered optimize with bytecodeIndex = %u, executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, bytecodeIndex, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter()); 1933 1932 #endif 1934 1933 … … 1938 1937 if (codeBlock->hasOptimizedReplacement()) { 1939 1938 #if ENABLE(JIT_VERBOSE_OSR) 1940 dataLog("Considering loopOSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());1939 dataLog("Considering OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); 1941 1940 #endif 1942 1941 if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) { … … 1960 1959 #if ENABLE(JIT_VERBOSE_OSR) 1961 1960 if (error) 1962 dataLog("WARNING: optimized compilation f rom loop failed.\n");1961 dataLog("WARNING: optimized compilation failed.\n"); 1963 1962 #else 1964 1963 UNUSED_PARAM(error); … … 1967 1966 if (codeBlock->replacement() == codeBlock) { 1968 1967 #if ENABLE(JIT_VERBOSE_OSR) 1969 dataLog("Optimizing %p f rom loop failed.\n", codeBlock);1968 dataLog("Optimizing %p failed.\n", codeBlock); 1970 1969 #endif 1971 1970 … … 1981 1980 if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) { 1982 1981 #if ENABLE(JIT_VERBOSE_OSR) 1983 dataLog("Optimizing %p from loopsucceeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());1982 dataLog("Optimizing %p succeeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter()); 1984 1983 #endif 1985 1984 … … 1991 1990 1992 1991 #if ENABLE(JIT_VERBOSE_OSR) 1993 dataLog("Optimizing %p from loopsucceeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());1992 dataLog("Optimizing %p succeeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter()); 1994 1993 #endif 1995 1994 … … 1999 1998 2000 1999 #if ENABLE(JIT_VERBOSE_OSR) 2001 dataLog("Encountered loopOSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());2000 dataLog("Encountered OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); 2002 2001 #endif 2003 2002 … … 2012 2011 if (optimizedCodeBlock->shouldReoptimizeNow()) { 2013 2012 #if ENABLE(JIT_VERBOSE_OSR) 2014 dataLog("Triggering reoptimization of %p(%p) ( in loopafter OSR fail).\n", codeBlock, codeBlock->replacement());2013 dataLog("Triggering reoptimization of %p(%p) (after OSR fail).\n", codeBlock, codeBlock->replacement()); 2015 2014 #endif 2016 2015 codeBlock->reoptimize(); … … 2021 2020 // longer and then try again. 2022 2021 codeBlock->optimizeAfterWarmUp(); 2023 }2024 2025 DEFINE_STUB_FUNCTION(void, optimize_from_ret)2026 {2027 STUB_INIT_STACK_FRAME(stackFrame);2028 2029 CallFrame* callFrame = stackFrame.callFrame;2030 CodeBlock* codeBlock = callFrame->codeBlock();2031 2032 #if ENABLE(JIT_VERBOSE_OSR)2033 dataLog("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());2034 #endif2035 2036 if (!codeBlock->checkIfOptimizationThresholdReached())2037 return;2038 2039 if (codeBlock->hasOptimizedReplacement()) {2040 #if ENABLE(JIT_VERBOSE_OSR)2041 dataLog("Returning from old JIT call frame with optimized replacement %p(%p), with success/fail %u/%u", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());2042 CallFrame* callerFrame = callFrame->callerFrame();2043 if (callerFrame)2044 dataLog(", callerFrame = %p, returnPC = %p, caller code block = %p", callerFrame, callFrame->returnPC().value(), callerFrame->codeBlock());2045 dataLog("\n");2046 #endif2047 if (codeBlock->replacement()->shouldReoptimizeNow()) {2048 #if ENABLE(JIT_VERBOSE_OSR)2049 dataLog("Triggering reoptimization of %p(%p) (in return).\n", codeBlock, codeBlock->replacement());2050 #endif2051 codeBlock->reoptimize();2052 }2053 2054 codeBlock->optimizeSoon();2055 return;2056 }2057 2058 if (!codeBlock->shouldOptimizeNow()) {2059 #if ENABLE(JIT_VERBOSE_OSR)2060 dataLog("Delaying optimization for %p (in return) because of insufficient profiling.\n", codeBlock);2061 #endif2062 return;2063 }2064 2065 ScopeChainNode* scopeChain = callFrame->scopeChain();2066 2067 JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain);2068 if (error)2069 dataLog("WARNING: optimized compilation from ret failed.\n");2070 2071 if (codeBlock->replacement() == codeBlock) {2072 #if ENABLE(JIT_VERBOSE_OSR)2073 dataLog("Optimizing %p from return failed.\n", codeBlock);2074 #endif2075 2076 ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);2077 codeBlock->dontOptimizeAnytimeSoon();2078 return;2079 }2080 2081 ASSERT(codeBlock->replacement()->getJITType() == JITCode::DFGJIT);2082 2083 #if ENABLE(JIT_VERBOSE_OSR)2084 dataLog("Optimizing %p from return succeeded after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());2085 #endif2086 2087 codeBlock->optimizeSoon();2088 2022 } 2089 2023 #endif // ENABLE(DFG_JIT) -
trunk/Source/JavaScriptCore/jit/JITStubs.h
r120244 r121073 451 451 void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION) WTF_INTERNAL; 452 452 #if ENABLE(DFG_JIT) 453 void JIT_STUB cti_optimize_from_loop(STUB_ARGS_DECLARATION) WTF_INTERNAL; 454 void JIT_STUB cti_optimize_from_ret(STUB_ARGS_DECLARATION) WTF_INTERNAL; 453 void JIT_STUB cti_optimize(STUB_ARGS_DECLARATION) WTF_INTERNAL; 455 454 #endif 456 455 void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION) WTF_INTERNAL;
Note:
See TracChangeset
for help on using the changeset viewer.