DFG tier-up should happen in prologues, not epilogues
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Jun 2012 23:32:59 +0000 (23:32 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Jun 2012 23:32:59 +0000 (23:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=89752

Reviewed by Geoffrey Garen.

This change has two outcomes:

1) Slightly reduces the likelihood that a function will be optimized both
standalone and via inlining.  Previously, if you had a call sequence like foo()
calls bar() exactly once, and nobody else calls bar(), then bar() would get
optimized first (because it returns first) and then foo() gets optimized.  If foo()
can inline bar() then that means that bar() gets optimized twice.  But now, if we
optimize in prologues, then foo() will be optimized first.  If it inlines bar(),
that means that there will no longer be any calls to bar().

2) It lets us kill some code in JITStubs.  Epilogue tier-up was very different from
loop tier-up, since epilogue tier-up should not attempt OSR.  But prologue tier-up
requires OSR (albeit really easy OSR since it's the top of the compilation unit),
so it becomes just like loop tier-up.  As a result, we now have one optimization
hook (cti_optimize) instead of two (cti_optimize_from_loop and
cti_optimize_from_ret).

As a consequence of not having an optimization check in epilogues, the OSR exit
code must now trigger reoptimization itself instead of just signaling the epilogue
check to fire.

This also adds the ability to count the number of DFG compilations, which was
useful for debugging this patch and might be useful for other things in the future.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::reoptimize):
(JSC):
* bytecode/CodeBlock.h:
(CodeBlock):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseCodeBlock):
* dfg/DFGDriver.cpp:
(DFG):
(JSC::DFG::getNumCompilations):
(JSC::DFG::compile):
* dfg/DFGDriver.h:
(DFG):
* dfg/DFGOSRExitCompiler.cpp:
(JSC::DFG::OSRExitCompiler::handleExitCounts):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* jit/JIT.cpp:
(JSC::JIT::emitOptimizationCheck):
* jit/JIT.h:
* jit/JITCall32_64.cpp:
(JSC::JIT::emit_op_ret):
(JSC::JIT::emit_op_ret_object_or_this):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_ret):
(JSC::JIT::emit_op_ret_object_or_this):
(JSC::JIT::emit_op_enter):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_enter):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* jit/JITStubs.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121073 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGDriver.cpp
Source/JavaScriptCore/dfg/DFGDriver.h
Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGOperations.h
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITCall32_64.cpp
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/jit/JITStubs.h

index 4dceacf..e200923 100644 (file)
@@ -1,3 +1,67 @@
+2012-06-22  Filip Pizlo  <fpizlo@apple.com>
+
+        DFG tier-up should happen in prologues, not epilogues
+        https://bugs.webkit.org/show_bug.cgi?id=89752
+
+        Reviewed by Geoffrey Garen.
+
+        This change has two outcomes:
+        
+        1) Slightly reduces the likelihood that a function will be optimized both
+        standalone and via inlining.  Previously, if you had a call sequence like foo() 
+        calls bar() exactly once, and nobody else calls bar(), then bar() would get
+        optimized first (because it returns first) and then foo() gets optimized.  If foo()
+        can inline bar() then that means that bar() gets optimized twice.  But now, if we
+        optimize in prologues, then foo() will be optimized first.  If it inlines bar(),
+        that means that there will no longer be any calls to bar().
+        
+        2) It lets us kill some code in JITStubs.  Epilogue tier-up was very different from
+        loop tier-up, since epilogue tier-up should not attempt OSR.  But prologue tier-up
+        requires OSR (albeit really easy OSR since it's the top of the compilation unit),
+        so it becomes just like loop tier-up.  As a result, we now have one optimization
+        hook (cti_optimize) instead of two (cti_optimize_from_loop and
+        cti_optimize_from_ret).
+        
+        As a consequence of not having an optimization check in epilogues, the OSR exit
+        code must now trigger reoptimization itself instead of just signaling the epilogue
+        check to fire.
+        
+        This also adds the ability to count the number of DFG compilations, which was
+        useful for debugging this patch and might be useful for other things in the future.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::reoptimize):
+        (JSC):
+        * bytecode/CodeBlock.h:
+        (CodeBlock):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseCodeBlock):
+        * dfg/DFGDriver.cpp:
+        (DFG):
+        (JSC::DFG::getNumCompilations):
+        (JSC::DFG::compile):
+        * dfg/DFGDriver.h:
+        (DFG):
+        * dfg/DFGOSRExitCompiler.cpp:
+        (JSC::DFG::OSRExitCompiler::handleExitCounts):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * jit/JIT.cpp:
+        (JSC::JIT::emitOptimizationCheck):
+        * jit/JIT.h:
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::emit_op_ret):
+        (JSC::JIT::emit_op_ret_object_or_this):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_ret):
+        (JSC::JIT::emit_op_ret_object_or_this):
+        (JSC::JIT::emit_op_enter):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_enter):
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        * jit/JITStubs.h:
+
 2012-06-20  Mark Hahnenberg  <mhahnenberg@apple.com>
 
         JSLock should be per-JSGlobalData
index 2cf19b5..bcbb51f 100644 (file)
@@ -2464,6 +2464,16 @@ void CodeBlock::copyPostParseDataFromAlternative()
 }
 
 #if ENABLE(JIT)
+void CodeBlock::reoptimize()
+{
+    ASSERT(replacement() != this);
+    ASSERT(replacement()->alternative() == this);
+    replacement()->tallyFrequentExitSites();
+    replacement()->jettison();
+    countReoptimization();
+    optimizeAfterWarmUp();
+}
+
 CodeBlock* ProgramCodeBlock::replacement()
 {
     return &static_cast<ProgramExecutable*>(ownerExecutable())->generatedBytecode();
index af002f6..b73dcb2 100644 (file)
@@ -1105,15 +1105,7 @@ namespace JSC {
 #endif
         
 #if ENABLE(JIT)
-        void reoptimize()
-        {
-            ASSERT(replacement() != this);
-            ASSERT(replacement()->alternative() == this);
-            replacement()->tallyFrequentExitSites();
-            replacement()->jettison();
-            countReoptimization();
-            optimizeAfterWarmUp();
-        }
+        void reoptimize();
 #endif
 
 #if ENABLE(VERBOSE_VALUE_PROFILE)
index 6299594..7561197 100644 (file)
@@ -3257,6 +3257,9 @@ void ByteCodeParser::parseCodeBlock()
                     ASSERT(m_inlineStackTop->m_unlinkedBlocks.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_unlinkedBlocks.last().m_blockIndex]->bytecodeBegin < m_currentIndex);
                     m_inlineStackTop->m_unlinkedBlocks.append(UnlinkedBlock(m_graph.m_blocks.size()));
                     m_inlineStackTop->m_blockLinkingTargets.append(m_graph.m_blocks.size());
+                    // The first block is definitely an OSR target.
+                    if (!m_graph.m_blocks.size())
+                        block->isOSRTarget = true;
                     m_graph.m_blocks.append(block.release());
                     prepareToParseBlock();
                 }
index cbf0d8e..5033aa2 100644 (file)
 
 namespace JSC { namespace DFG {
 
+static unsigned numCompilations;
+
+unsigned getNumCompilations()
+{
+    return numCompilations;
+}
+
 enum CompileMode { CompileFunction, CompileOther };
 inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
 {
     SamplingRegion samplingRegion("DFG Compilation (Driver)");
     
+    numCompilations++;
+    
     ASSERT(codeBlock);
     ASSERT(codeBlock->alternative());
     ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT);
index ce798d0..a6e82fe 100644 (file)
@@ -38,6 +38,8 @@ class MacroAssemblerCodePtr;
 
 namespace DFG {
 
+JS_EXPORT_PRIVATE unsigned getNumCompilations();
+
 #if ENABLE(DFG_JIT)
 bool tryCompile(ExecState*, CodeBlock*, JITCode&);
 bool tryCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
index d46d596..e617b54 100644 (file)
@@ -115,7 +115,10 @@ void OSRExitCompiler::handleExitCounts(const OSRExit& exit)
         m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfForcedOSRExitCounter()));
         m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()));
         
+        m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0);
+
         tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(Options::forcedOSRExitCountForReoptimization)));
+
     } else {
         // Proceed based on the assumption that we can handle these exits so long as they
         // don't get too frequent.
@@ -136,8 +139,14 @@ void OSRExitCompiler::handleExitCounts(const OSRExit& exit)
     }
 
     // Reoptimize as soon as possible.
-    m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()));
-    m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold()));
+#if !NUMBER_OF_ARGUMENT_REGISTERS
+    m_jit.poke(GPRInfo::regT0);
+#else
+    m_jit.move(GPRInfo::regT0, GPRInfo::argumentGPR0);
+    ASSERT(GPRInfo::argumentGPR0 != GPRInfo::regT1);
+#endif
+    m_jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(triggerReoptimizationNow)), GPRInfo::regT1);
+    m_jit.call(GPRInfo::regT1);
     AssemblyHelpers::Jump doneAdjusting = m_jit.jump();
     
     tooFewFails.link(&m_jit);
index eaf0c72..b056a3c 100644 (file)
 #include "DFGRepatch.h"
 #include "HostCallReturnValue.h"
 #include "GetterSetter.h"
-#include <wtf/InlineASM.h>
 #include "Interpreter.h"
+#include "JIT.h"
 #include "JITExceptions.h"
 #include "JSActivation.h"
 #include "JSGlobalData.h"
 #include "JSStaticScopeObject.h"
 #include "NameInstance.h"
 #include "Operations.h"
+#include <wtf/InlineASM.h>
 
 #if ENABLE(DFG_JIT)
 
@@ -1251,6 +1252,27 @@ void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void*
 }
 #endif
 
+extern "C" void DFG_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock)
+{
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("%p: Entered reoptimize\n", codeBlock);
+#endif
+    // We must be called with the baseline code block.
+    ASSERT(JITCode::isBaselineCode(codeBlock->getJITType()));
+
+    // If I am my own replacement, then reoptimization has already been triggered.
+    // This can happen in recursive functions.
+    if (codeBlock->replacement() == codeBlock)
+        return;
+
+    // Otherwise, the replacement must be optimized code. Use this as an opportunity
+    // to check our logic.
+    ASSERT(codeBlock->hasOptimizedReplacement());
+    ASSERT(codeBlock->replacement()->getJITType() == JITCode::DFGJIT);
+
+    codeBlock->reoptimize();
+}
+
 } // extern "C"
 } } // namespace JSC::DFG
 
index 1ed2db8..7477ab2 100644 (file)
@@ -227,6 +227,8 @@ size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue) WTF_
 void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*) WTF_INTERNAL;
 #endif
 
+void DFG_OPERATION triggerReoptimizationNow(CodeBlock*) WTF_INTERNAL;
+
 } // extern "C"
 } } // namespace JSC::DFG
 
index 2aca351..e1e034b 100644 (file)
@@ -100,9 +100,10 @@ void JIT::emitOptimizationCheck(OptimizationCheckKind kind)
         return;
     
     Jump skipOptimize = branchAdd32(Signed, TrustedImm32(kind == LoopOptimizationCheck ? Options::executionCounterIncrementForLoop : Options::executionCounterIncrementForReturn), AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter()));
-    JITStubCall stubCall(this, kind == LoopOptimizationCheck ? cti_optimize_from_loop : cti_optimize_from_ret);
-    if (kind == LoopOptimizationCheck)
-        stubCall.addArgument(TrustedImm32(m_bytecodeOffset));
+    JITStubCall stubCall(this, cti_optimize);
+    stubCall.addArgument(TrustedImm32(m_bytecodeOffset));
+    if (kind == EnterOptimizationCheck)
+        ASSERT(!m_bytecodeOffset);
     stubCall.call();
     skipOptimize.link(this);
 }
index 6491edb..6d4c578 100644 (file)
@@ -806,7 +806,7 @@ namespace JSC {
         // Loads the character value of a single character string into dst.
         void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures);
         
-        enum OptimizationCheckKind { LoopOptimizationCheck, RetOptimizationCheck };
+        enum OptimizationCheckKind { LoopOptimizationCheck, EnterOptimizationCheck };
 #if ENABLE(DFG_JIT)
         void emitOptimizationCheck(OptimizationCheckKind);
 #else
index 8126605..7d86e61 100644 (file)
@@ -56,8 +56,6 @@ void JIT::emit_op_call_put_result(Instruction* instruction)
 
 void JIT::emit_op_ret(Instruction* currentInstruction)
 {
-    emitOptimizationCheck(RetOptimizationCheck);
-    
     unsigned dst = currentInstruction[1].u.operand;
 
     emitLoad(dst, regT1, regT0);
@@ -70,8 +68,6 @@ void JIT::emit_op_ret(Instruction* currentInstruction)
 
 void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
 {
-    emitOptimizationCheck(RetOptimizationCheck);
-    
     unsigned result = currentInstruction[1].u.operand;
     unsigned thisReg = currentInstruction[2].u.operand;
 
index ad7a56e..2e448dd 100644 (file)
@@ -576,8 +576,6 @@ void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)
 
 void JIT::emit_op_ret(Instruction* currentInstruction)
 {
-    emitOptimizationCheck(RetOptimizationCheck);
-    
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
     ASSERT(returnValueRegister != callFrameRegister);
@@ -598,8 +596,6 @@ void JIT::emit_op_ret(Instruction* currentInstruction)
 
 void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
 {
-    emitOptimizationCheck(RetOptimizationCheck);
-    
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
     ASSERT(returnValueRegister != callFrameRegister);
@@ -1218,13 +1214,14 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction)
 
 void JIT::emit_op_enter(Instruction*)
 {
+    emitOptimizationCheck(EnterOptimizationCheck);
+    
     // Even though CTI doesn't use them, we initialize our constant
     // registers to zap stale pointers, to avoid unnecessarily prolonging
     // object lifetime and increasing GC pressure.
     size_t count = m_codeBlock->m_numVars;
     for (size_t j = 0; j < count; ++j)
         emitInitRegister(j);
-
 }
 
 void JIT::emit_op_create_activation(Instruction* currentInstruction)
index 57ef7ef..4f85895 100644 (file)
@@ -1487,6 +1487,8 @@ void JIT::emit_op_debug(Instruction* currentInstruction)
 
 void JIT::emit_op_enter(Instruction*)
 {
+    emitOptimizationCheck(EnterOptimizationCheck);
+    
     // Even though JIT code doesn't use them, we initialize our constant
     // registers to zap stale pointers, to avoid unnecessarily prolonging
     // object lifetime and increasing GC pressure.
index 12f3ec3..b0ff4a0 100644 (file)
@@ -1919,17 +1919,16 @@ DEFINE_STUB_FUNCTION(void, op_check_has_instance)
 }
 
 #if ENABLE(DFG_JIT)
-DEFINE_STUB_FUNCTION(void, optimize_from_loop)
+DEFINE_STUB_FUNCTION(void, optimize)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
     
     CallFrame* callFrame = stackFrame.callFrame;
     CodeBlock* codeBlock = callFrame->codeBlock();
-
     unsigned bytecodeIndex = stackFrame.args[0].int32();
-    
+
 #if ENABLE(JIT_VERBOSE_OSR)
-    dataLog("%p: Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+    dataLog("%p: Entered optimize with bytecodeIndex = %u, executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, bytecodeIndex, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
 #endif
 
     if (!codeBlock->checkIfOptimizationThresholdReached())
@@ -1937,7 +1936,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop)
 
     if (codeBlock->hasOptimizedReplacement()) {
 #if ENABLE(JIT_VERBOSE_OSR)
-        dataLog("Considering loop OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
+        dataLog("Considering OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
 #endif
         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
 #if ENABLE(JIT_VERBOSE_OSR)
@@ -1959,14 +1958,14 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop)
         JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain);
 #if ENABLE(JIT_VERBOSE_OSR)
         if (error)
-            dataLog("WARNING: optimized compilation from loop failed.\n");
+            dataLog("WARNING: optimized compilation failed.\n");
 #else
         UNUSED_PARAM(error);
 #endif
         
         if (codeBlock->replacement() == codeBlock) {
 #if ENABLE(JIT_VERBOSE_OSR)
-            dataLog("Optimizing %p from loop failed.\n", codeBlock);
+            dataLog("Optimizing %p failed.\n", codeBlock);
 #endif
             
             ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
@@ -1980,7 +1979,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop)
     
     if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
 #if ENABLE(JIT_VERBOSE_OSR)
-        dataLog("Optimizing %p from loop succeeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
+        dataLog("Optimizing %p succeeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
 #endif
 
         codeBlock->optimizeSoon();
@@ -1990,7 +1989,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop)
     }
     
 #if ENABLE(JIT_VERBOSE_OSR)
-    dataLog("Optimizing %p from loop succeeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
+    dataLog("Optimizing %p succeeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
 #endif
 
     // Count the OSR failure as a speculation failure. If this happens a lot, then
@@ -1998,7 +1997,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop)
     optimizedCodeBlock->countSpeculationFailure();
     
 #if ENABLE(JIT_VERBOSE_OSR)
-    dataLog("Encountered loop OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
+    dataLog("Encountered OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
 #endif
 
     // We are a lot more conservative about triggering reoptimization after OSR failure than
@@ -2011,7 +2010,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop)
     // reoptimization trigger.
     if (optimizedCodeBlock->shouldReoptimizeNow()) {
 #if ENABLE(JIT_VERBOSE_OSR)
-        dataLog("Triggering reoptimization of %p(%p) (in loop after OSR fail).\n", codeBlock, codeBlock->replacement());
+        dataLog("Triggering reoptimization of %p(%p) (after OSR fail).\n", codeBlock, codeBlock->replacement());
 #endif
         codeBlock->reoptimize();
         return;
@@ -2021,71 +2020,6 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop)
     // longer and then try again.
     codeBlock->optimizeAfterWarmUp();
 }
-
-DEFINE_STUB_FUNCTION(void, optimize_from_ret)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-    
-    CallFrame* callFrame = stackFrame.callFrame;
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    
-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
-#endif
-
-    if (!codeBlock->checkIfOptimizationThresholdReached())
-        return;
-
-    if (codeBlock->hasOptimizedReplacement()) {
-#if ENABLE(JIT_VERBOSE_OSR)
-        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());
-        CallFrame* callerFrame = callFrame->callerFrame();
-        if (callerFrame)
-            dataLog(", callerFrame = %p, returnPC = %p, caller code block = %p", callerFrame, callFrame->returnPC().value(), callerFrame->codeBlock());
-        dataLog("\n");
-#endif
-        if (codeBlock->replacement()->shouldReoptimizeNow()) {
-#if ENABLE(JIT_VERBOSE_OSR)
-            dataLog("Triggering reoptimization of %p(%p) (in return).\n", codeBlock, codeBlock->replacement());
-#endif
-            codeBlock->reoptimize();
-        }
-        
-        codeBlock->optimizeSoon();
-        return;
-    }
-    
-    if (!codeBlock->shouldOptimizeNow()) {
-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLog("Delaying optimization for %p (in return) because of insufficient profiling.\n", codeBlock);
-#endif
-        return;
-    }
-    
-    ScopeChainNode* scopeChain = callFrame->scopeChain();
-
-    JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain);
-    if (error)
-        dataLog("WARNING: optimized compilation from ret failed.\n");
-    
-    if (codeBlock->replacement() == codeBlock) {
-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLog("Optimizing %p from return failed.\n", codeBlock);
-#endif
-
-        ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
-        codeBlock->dontOptimizeAnytimeSoon();
-        return;
-    }
-    
-    ASSERT(codeBlock->replacement()->getJITType() == JITCode::DFGJIT);
-
-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog("Optimizing %p from return succeeded after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
-#endif
-    
-    codeBlock->optimizeSoon();
-}
 #endif // ENABLE(DFG_JIT)
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
index 2517760..d2bc15e 100644 (file)
@@ -450,8 +450,7 @@ extern "C" {
     void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION) WTF_INTERNAL;
     void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION) WTF_INTERNAL;
 #if ENABLE(DFG_JIT)
-    void JIT_STUB cti_optimize_from_loop(STUB_ARGS_DECLARATION) WTF_INTERNAL;
-    void JIT_STUB cti_optimize_from_ret(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+    void JIT_STUB cti_optimize(STUB_ARGS_DECLARATION) WTF_INTERNAL;
 #endif
     void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION) WTF_INTERNAL;
     void* JIT_STUB cti_op_construct_arityCheck(STUB_ARGS_DECLARATION) WTF_INTERNAL;