Title: [197861] trunk/Source/_javascript_Core
Revision
197861
Author
benja...@webkit.org
Date
2016-03-09 09:51:38 -0800 (Wed, 09 Mar 2016)

Log Message

[JSC] Pick how to OSR Enter to FTL at runtime instead of compile time
https://bugs.webkit.org/show_bug.cgi?id=155217

Reviewed by Filip Pizlo.

This patch addresses 2 types of problems with tiering up to FTL
with OSR Entry in a loop:
-When there are nested loops, it is generally valuable to enter
 an outer loop rather than an inner loop.
-When tiering up at a point that cannot OSR Enter, we are at
 the mercy of the outer loop frequency to compile the right
 entry point.

The first case is significant in the test "gaussian-blur".
That test has 4 nested loops. When we have an OSR Entry,
the analysis phases have to be pesimistic where we enter:
we do not really know what constraint can be proven from
the DFG code that was running.

In "gaussian-blur", integer-range analysis removes pretty
much all overflow checks in the inner loops of where we entered.
The more outside we enter, the better code we generate.

Since we spend the most iterations in the inner loop, we naturally
tend to OSR Enter into the 2 most inner loops, making the most
pessimistic assumptions.

To avoid such problems, I changed how we decide where to OSR Enter.
Previously, the last CheckTierUpAndOSREnter to cross the threshold
was where we take the entry point for FTL.

What happens now is that the entry point is not decied when
compiling the CheckTierUp variants. Instead, all the information
we need is gathered during compilation and keept on the JITCode
to be used at runtime.

When we try to tier up and decide to OSR Enter, we use the information
we have to pick a good outer loop for OSR Entry.

Now the problem is outer loop do not CheckTierUpAndOSREnter often,
wasting several miliseconds before entering the newly compiled FTL code.

To solve that, every CheckTierUpAndOSREnter has its own trigger that
bypass the counter. When the FTL Code is compiled, the trigger is set
and we enter through the right CheckTierUpAndOSREnter immediately.

---

This new mechanism also solves a problem of ai-astar.
When we try to tier up in ai-astar, we had nothing to compile until
the outer loop is reached.

To make sure we reached the CheckTierUpAndOSREnter in a reasonable time,
we had CheckTierUpWithNestedTriggerAndOSREnter with a special trigger.

With the new mechanism, we can do much better:
-When we keep hitting CheckTierUpInLoop, we now have all the information
 we need to already start compiling the outer loop.
 Instead of waiting for the outer loop to be reached a few times, we compile
 it as soon as the inner loop is hammering CheckTierUpInLoop.
-With the new triggers, the very next time we hit the outer loop, we OSR Enter.

This allow us to compile what we need sooner and enter sooner.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): Deleted.
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize): Deleted.
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC): Deleted.
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode): Deleted.
* dfg/DFGJITCode.h:
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::JITCompiler):
(JSC::DFG::JITCompiler::compileEntryExecutionFlag):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPlan.h:
(JSC::DFG::Plan::canTierUpAndOSREnter):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate): Deleted.
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute): Deleted.
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile): Deleted.
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGTierUpCheckInjectionPhase.cpp:
(JSC::DFG::TierUpCheckInjectionPhase::run):
(JSC::DFG::TierUpCheckInjectionPhase::buildNaturalLoopToLoopHintMap):
(JSC::DFG::TierUpCheckInjectionPhase::findLoopsContainingLoopHintWithoutOSREnter): Deleted.
* dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp:
(JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback):
(JSC::DFG::Ref<ToFTLForOSREntryDeferredCompilationCallback>ToFTLForOSREntryDeferredCompilationCallback::create):
(JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously):
(JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete):
* dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (197860 => 197861)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-09 17:51:38 UTC (rev 197861)
@@ -1,3 +1,105 @@
+2016-03-09  Benjamin Poulain  <benja...@webkit.org>
+
+        [JSC] Pick how to OSR Enter to FTL at runtime instead of compile time
+        https://bugs.webkit.org/show_bug.cgi?id=155217
+
+        Reviewed by Filip Pizlo.
+
+        This patch addresses 2 types of problems with tiering up to FTL
+        with OSR Entry in a loop:
+        -When there are nested loops, it is generally valuable to enter
+         an outer loop rather than an inner loop.
+        -When tiering up at a point that cannot OSR Enter, we are at
+         the mercy of the outer loop frequency to compile the right
+         entry point.
+
+        The first case is significant in the test "gaussian-blur".
+        That test has 4 nested loops. When we have an OSR Entry,
+        the analysis phases have to be pesimistic where we enter:
+        we do not really know what constraint can be proven from
+        the DFG code that was running.
+
+        In "gaussian-blur", integer-range analysis removes pretty
+        much all overflow checks in the inner loops of where we entered.
+        The more outside we enter, the better code we generate.
+
+        Since we spend the most iterations in the inner loop, we naturally
+        tend to OSR Enter into the 2 most inner loops, making the most
+        pessimistic assumptions.
+
+        To avoid such problems, I changed how we decide where to OSR Enter.
+        Previously, the last CheckTierUpAndOSREnter to cross the threshold
+        was where we take the entry point for FTL.
+
+        What happens now is that the entry point is not decied when
+        compiling the CheckTierUp variants. Instead, all the information
+        we need is gathered during compilation and keept on the JITCode
+        to be used at runtime.
+
+        When we try to tier up and decide to OSR Enter, we use the information
+        we have to pick a good outer loop for OSR Entry.
+
+        Now the problem is outer loop do not CheckTierUpAndOSREnter often,
+        wasting several miliseconds before entering the newly compiled FTL code.
+
+        To solve that, every CheckTierUpAndOSREnter has its own trigger that
+        bypass the counter. When the FTL Code is compiled, the trigger is set
+        and we enter through the right CheckTierUpAndOSREnter immediately.
+
+        ---
+
+        This new mechanism also solves a problem of ai-astar.
+        When we try to tier up in ai-astar, we had nothing to compile until
+        the outer loop is reached.
+
+        To make sure we reached the CheckTierUpAndOSREnter in a reasonable time,
+        we had CheckTierUpWithNestedTriggerAndOSREnter with a special trigger.
+
+        With the new mechanism, we can do much better:
+        -When we keep hitting CheckTierUpInLoop, we now have all the information
+         we need to already start compiling the outer loop.
+         Instead of waiting for the outer loop to be reached a few times, we compile
+         it as soon as the inner loop is hammering CheckTierUpInLoop.
+        -With the new triggers, the very next time we hit the outer loop, we OSR Enter.
+
+        This allow us to compile what we need sooner and enter sooner.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): Deleted.
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize): Deleted.
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC): Deleted.
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode): Deleted.
+        * dfg/DFGJITCode.h:
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::JITCompiler):
+        (JSC::DFG::JITCompiler::compileEntryExecutionFlag):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPlan.h:
+        (JSC::DFG::Plan::canTierUpAndOSREnter):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate): Deleted.
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute): Deleted.
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile): Deleted.
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGTierUpCheckInjectionPhase.cpp:
+        (JSC::DFG::TierUpCheckInjectionPhase::run):
+        (JSC::DFG::TierUpCheckInjectionPhase::buildNaturalLoopToLoopHintMap):
+        (JSC::DFG::TierUpCheckInjectionPhase::findLoopsContainingLoopHintWithoutOSREnter): Deleted.
+        * dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp:
+        (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback):
+        (JSC::DFG::Ref<ToFTLForOSREntryDeferredCompilationCallback>ToFTLForOSREntryDeferredCompilationCallback::create):
+        (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously):
+        (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete):
+        * dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h:
+
 2016-03-08  Filip Pizlo  <fpi...@apple.com>
 
         DFG should be able to constant-fold strings

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-03-09 17:51:38 UTC (rev 197861)
@@ -2660,7 +2660,6 @@
     }
 
     case CheckTierUpAndOSREnter:
-    case CheckTierUpWithNestedTriggerAndOSREnter:
     case LoopHint:
     case ZombieHint:
     case ExitOK:

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-03-09 17:51:38 UTC (rev 197861)
@@ -343,7 +343,6 @@
     case CheckTierUpInLoop:
     case CheckTierUpAtReturn:
     case CheckTierUpAndOSREnter:
-    case CheckTierUpWithNestedTriggerAndOSREnter:
     case LoopHint:
     case Breakpoint:
     case ProfileWillCall:

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-03-09 17:51:38 UTC (rev 197861)
@@ -180,7 +180,6 @@
     case CheckTierUpInLoop:
     case CheckTierUpAtReturn:
     case CheckTierUpAndOSREnter:
-    case CheckTierUpWithNestedTriggerAndOSREnter:
     case LoopHint:
     case StoreBarrier:
     case InvalidationPoint:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-03-09 17:51:38 UTC (rev 197861)
@@ -1270,7 +1270,6 @@
         case CheckTierUpInLoop:
         case CheckTierUpAtReturn:
         case CheckTierUpAndOSREnter:
-        case CheckTierUpWithNestedTriggerAndOSREnter:
         case InvalidationPoint:
         case CheckArray:
         case CheckInBounds:

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCode.h (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGJITCode.h	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCode.h	2016-03-09 17:51:38 UTC (rev 197861)
@@ -138,9 +138,28 @@
     DFG::VariableEventStream variableEventStream;
     DFG::MinifiedGraph minifiedDFG;
 #if ENABLE(FTL_JIT)
-    uint8_t nestedTriggerIsSet { 0 };
     uint8_t neverExecutedEntry { 1 };
+
     UpperTierExecutionCounter tierUpCounter;
+
+    // For osrEntryPoint that are in inner loop, this maps their bytecode to the bytecode
+    // of the outerloop entry points in order (from innermost to outermost).
+    //
+    // The key may not always be a target for OSR Entry but the list in the value is guaranteed
+    // to be usable for OSR Entry.
+    HashMap<unsigned, Vector<unsigned>> tierUpInLoopHierarchy;
+
+    // Map each bytecode of CheckTierUpAndOSREnter to its stream index.
+    HashMap<unsigned, unsigned, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> bytecodeIndexToStreamIndex;
+
+    // Map each bytecode of CheckTierUpAndOSREnter to its trigger forcing OSR Entry.
+    // This can never be modified after it has been initialized since the addresses of the triggers
+    // are used by the JIT.
+    HashMap<unsigned, uint8_t> tierUpEntryTriggers;
+
+    // Set of bytecode that were the target of a TierUp operation.
+    HashSet<unsigned, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> tierUpEntrySeen;
+
     WriteBarrier<CodeBlock> m_osrEntryBlock;
     unsigned osrEntryRetry;
     bool abandonOSREntry;

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2016-03-09 17:51:38 UTC (rev 197861)
@@ -56,6 +56,11 @@
 {
     if (shouldDumpDisassembly() || m_graph.m_vm.m_perBytecodeProfiler)
         m_disassembler = std::make_unique<Disassembler>(dfg);
+#if ENABLE(FTL_JIT)
+    m_jitCode->tierUpInLoopHierarchy = WTFMove(m_graph.m_plan.tierUpInLoopHierarchy);
+    for (unsigned tierUpBytecode : m_graph.m_plan.tierUpAndOSREnterBytecodes)
+        m_jitCode->tierUpEntryTriggers.add(tierUpBytecode, 0);
+#endif
 }
 
 JITCompiler::~JITCompiler()
@@ -114,7 +119,7 @@
 void JITCompiler::compileEntryExecutionFlag()
 {
 #if ENABLE(FTL_JIT)
-    if (m_graph.m_plan.canTierUpAndOSREnter)
+    if (m_graph.m_plan.canTierUpAndOSREnter())
         store8(TrustedImm32(0), &m_jitCode->neverExecutedEntry);
 #endif // ENABLE(FTL_JIT)
 }

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-03-09 17:51:38 UTC (rev 197861)
@@ -95,7 +95,6 @@
     /* Tier-up checks from the DFG to the FTL. */\
     macro(CheckTierUpInLoop, NodeMustGenerate) \
     macro(CheckTierUpAndOSREnter, NodeMustGenerate) \
-    macro(CheckTierUpWithNestedTriggerAndOSREnter, NodeMustGenerate) \
     macro(CheckTierUpAtReturn, NodeMustGenerate) \
     \
     /* Get the value of a local variable, without linking into the VariableAccessData */\

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-03-09 17:51:38 UTC (rev 197861)
@@ -1554,7 +1554,7 @@
         codeBlock, CompilationDeferred);
 }
 
-static void triggerTierUpNowCommon(ExecState* exec, bool inLoop)
+void JIT_OPERATION triggerTierUpNow(ExecState* exec)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
@@ -1573,45 +1573,64 @@
             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
             jitCode->tierUpCounter, "\n");
     }
-    if (inLoop)
-        jitCode->nestedTriggerIsSet = 1;
 
     if (shouldTriggerFTLCompile(codeBlock, jitCode))
         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
-}
 
-void JIT_OPERATION triggerTierUpNow(ExecState* exec)
-{
-    triggerTierUpNowCommon(exec, false);
+    if (codeBlock->hasOptimizedReplacement()) {
+        if (jitCode->tierUpEntryTriggers.isEmpty()) {
+            // There is nothing more we can do, the only way this will be entered
+            // is through the function entry point.
+            jitCode->dontOptimizeAnytimeSoon(codeBlock);
+            return;
+        }
+        if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
+            // There is only one outer loop and its trigger must have been set
+            // when the plan completed.
+            // Exiting the inner loop is useless, we can ignore the counter and leave
+            // the trigger do its job.
+            jitCode->dontOptimizeAnytimeSoon(codeBlock);
+            return;
+        }
+    }
 }
 
-void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec)
+static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigned osrEntryBytecodeIndex)
 {
-    triggerTierUpNowCommon(exec, true);
-}
-
-char* JIT_OPERATION triggerOSREntryNow(
-    ExecState* exec, int32_t bytecodeIndex, int32_t streamIndex)
-{
     VM* vm = &exec->vm();
-    NativeCallFrameTracer tracer(vm, exec);
-    DeferGC deferGC(vm->heap);
     CodeBlock* codeBlock = exec->codeBlock();
-    
-    if (codeBlock->jitType() != JITCode::DFGJIT) {
-        dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-    
+
+    // Resolve any pending plan for OSR Enter on this function.
+    Worklist::State worklistState;
+    if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
+        worklistState = worklist->completeAllReadyPlansForVM(
+            *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
+    } else
+        worklistState = Worklist::NotKnown;
+
     JITCode* jitCode = codeBlock->jitCode()->dfg();
-    jitCode->nestedTriggerIsSet = 0;
-    
-    if (Options::verboseOSR()) {
-        dataLog(
-            *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
-            jitCode->tierUpCounter, "\n");
+    if (worklistState == Worklist::Compiling) {
+        jitCode->setOptimizationThresholdBasedOnCompilationResult(
+            codeBlock, CompilationDeferred);
+        return nullptr;
     }
-    
+
+    if (worklistState == Worklist::Compiled) {
+        // This means that compilation failed and we already set the thresholds.
+        if (Options::verboseOSR())
+            dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
+        return nullptr;
+    }
+
+    // If we can OSR Enter, do it right away.
+    if (originBytecodeIndex == osrEntryBytecodeIndex) {
+        unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
+        if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
+            if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex))
+                return static_cast<char*>(address);
+        }
+    }
+
     // - If we don't have an FTL code block, then try to compile one.
     // - If we do have an FTL code block, then try to enter for a while.
     // - If we couldn't enter for a while, then trigger OSR entry.
@@ -1630,29 +1649,13 @@
             return nullptr;
         }
     }
-    
+
     // It's time to try to compile code for OSR entry.
-    Worklist::State worklistState;
-    if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
-        worklistState = worklist->completeAllReadyPlansForVM(
-            *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
-    } else
-        worklistState = Worklist::NotKnown;
-    
-    if (worklistState == Worklist::Compiling) {
-        jitCode->setOptimizationThresholdBasedOnCompilationResult(
-            codeBlock, CompilationDeferred);
-        return nullptr;
-    }
-    
     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
-        void* address = FTL::prepareOSREntry(
-            exec, codeBlock, entryBlock, bytecodeIndex, streamIndex);
-        if (address)
-            return static_cast<char*>(address);
-
         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
             jitCode->osrEntryRetry++;
+            jitCode->setOptimizationThresholdBasedOnCompilationResult(
+                codeBlock, CompilationDeferred);
             return nullptr;
         }
 
@@ -1660,33 +1663,47 @@
         entryCode->countEntryFailure();
         if (entryCode->entryFailureCount() <
             Options::ftlOSREntryFailureCountForReoptimization()) {
-            jitCode->optimizeSoon(codeBlock);
+            jitCode->setOptimizationThresholdBasedOnCompilationResult(
+                codeBlock, CompilationDeferred);
             return nullptr;
         }
-        
+
         // OSR entry failed. Oh no! This implies that we need to retry. We retry
         // without exponential backoff and we only do this for the entry code block.
+        unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
         jitCode->clearOSREntryBlock();
         jitCode->osrEntryRetry = 0;
+        jitCode->tierUpEntryTriggers.set(osrEntryBytecode, 0);
+        jitCode->setOptimizationThresholdBasedOnCompilationResult(
+            codeBlock, CompilationDeferred);
         return nullptr;
     }
-    
-    if (worklistState == Worklist::Compiled) {
-        // This means that compilation failed and we already set the thresholds.
-        if (Options::verboseOSR())
-            dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
-        return nullptr;
+
+    unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
+    auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(osrEntryBytecodeIndex);
+    if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()) {
+        for (unsigned osrEntryCandidate : tierUpHierarchyEntry->value) {
+            if (jitCode->tierUpEntrySeen.contains(osrEntryCandidate)) {
+                osrEntryBytecodeIndex = osrEntryCandidate;
+                streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
+            }
+        }
     }
 
     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
     // something.
+    auto triggerIterator = jitCode->tierUpEntryTriggers.find(osrEntryBytecodeIndex);
+    RELEASE_ASSERT(triggerIterator != jitCode->tierUpEntryTriggers.end());
+    uint8_t* triggerAddress = &(triggerIterator->value);
+
     Operands<JSValue> mustHandleValues;
     jitCode->reconstruct(
-        exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues);
+        exec, codeBlock, CodeOrigin(osrEntryBytecodeIndex), streamIndex, mustHandleValues);
     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
+
     CompilationResult forEntryResult = compile(
-        *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, bytecodeIndex,
-        mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create());
+        *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, osrEntryBytecodeIndex,
+        mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
 
     if (jitCode->neverExecutedEntry)
         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
@@ -1701,10 +1718,66 @@
     // entry will succeed unless we ran out of stack. It's not clear what we should do.
     // We signal to try again after a while if that happens.
     void* address = FTL::prepareOSREntry(
-        exec, codeBlock, jitCode->osrEntryBlock(), bytecodeIndex, streamIndex);
+        exec, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
     return static_cast<char*>(address);
 }
 
+void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
+{
+    VM* vm = &exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    DeferGC deferGC(vm->heap);
+    CodeBlock* codeBlock = exec->codeBlock();
+
+    if (codeBlock->jitType() != JITCode::DFGJIT) {
+        dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+
+    JITCode* jitCode = codeBlock->jitCode()->dfg();
+
+    if (Options::verboseOSR()) {
+        dataLog(
+            *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
+            jitCode->tierUpCounter, "\n");
+    }
+
+    auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(bytecodeIndex);
+    if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()
+        && !tierUpHierarchyEntry->value.isEmpty()) {
+        tierUpCommon(exec, bytecodeIndex, tierUpHierarchyEntry->value.first());
+    } else if (shouldTriggerFTLCompile(codeBlock, jitCode))
+        triggerFTLReplacementCompile(vm, codeBlock, jitCode);
+
+    // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
+    if (codeBlock->hasOptimizedReplacement())
+        jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
+}
+
+char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
+{
+    VM* vm = &exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    DeferGC deferGC(vm->heap);
+    CodeBlock* codeBlock = exec->codeBlock();
+
+    if (codeBlock->jitType() != JITCode::DFGJIT) {
+        dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+
+    JITCode* jitCode = codeBlock->jitCode()->dfg();
+    jitCode->tierUpEntrySeen.add(bytecodeIndex);
+
+    if (Options::verboseOSR()) {
+        dataLog(
+            *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
+            jitCode->tierUpCounter, "\n");
+    }
+
+    return tierUpCommon(exec, bytecodeIndex, bytecodeIndex);
+}
+
 #endif // ENABLE(FTL_JIT)
 
 } // extern "C"

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2016-03-09 17:51:38 UTC (rev 197861)
@@ -169,8 +169,8 @@
 
 #if ENABLE(FTL_JIT)
 void JIT_OPERATION triggerTierUpNow(ExecState*) WTF_INTERNAL;
-void JIT_OPERATION triggerTierUpNowInLoop(ExecState*) WTF_INTERNAL;
-char* JIT_OPERATION triggerOSREntryNow(ExecState*, int32_t bytecodeIndex, int32_t streamIndex) WTF_INTERNAL;
+void JIT_OPERATION triggerTierUpNowInLoop(ExecState*, unsigned bytecodeIndex) WTF_INTERNAL;
+char* JIT_OPERATION triggerOSREntryNow(ExecState*, unsigned bytecodeIndex) WTF_INTERNAL;
 #endif // ENABLE(FTL_JIT)
 
 } // extern "C"

Modified: trunk/Source/_javascript_Core/dfg/DFGPlan.h (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGPlan.h	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGPlan.h	2016-03-09 17:51:38 UTC (rev 197861)
@@ -75,6 +75,8 @@
     void checkLivenessAndVisitChildren(SlotVisitor&);
     bool isKnownToBeLiveDuringGC();
     void cancel();
+
+    bool canTierUpAndOSREnter() const { return !tierUpAndOSREnterBytecodes.isEmpty(); }
     
     VM& vm;
 
@@ -99,8 +101,10 @@
     DesiredTransitions transitions;
     
     bool willTryToTierUp { false };
-    bool canTierUpAndOSREnter { false };
 
+    HashMap<unsigned, Vector<unsigned>> tierUpInLoopHierarchy;
+    Vector<unsigned> tierUpAndOSREnterBytecodes;
+
     enum Stage { Preparing, Compiling, Compiled, Ready, Cancelled };
     Stage stage;
 

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-03-09 17:51:38 UTC (rev 197861)
@@ -641,7 +641,6 @@
         case CheckTierUpInLoop:
         case CheckTierUpAtReturn:
         case CheckTierUpAndOSREnter:
-        case CheckTierUpWithNestedTriggerAndOSREnter:
         case InvalidationPoint:
         case CheckInBounds:
         case ValueToInt32:

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-03-09 17:51:38 UTC (rev 197861)
@@ -296,7 +296,6 @@
     case CheckTierUpInLoop:
     case CheckTierUpAtReturn:
     case CheckTierUpAndOSREnter:
-    case CheckTierUpWithNestedTriggerAndOSREnter:
     case LoopHint:
     case StoreBarrier:
     case InvalidationPoint:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-03-09 17:51:38 UTC (rev 197861)
@@ -4990,7 +4990,6 @@
     case CheckTierUpInLoop:
     case CheckTierUpAtReturn:
     case CheckTierUpAndOSREnter:
-    case CheckTierUpWithNestedTriggerAndOSREnter:
     case Int52Rep:
     case FiatInt52:
     case Int52Constant:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-03-09 17:51:38 UTC (rev 197861)
@@ -4979,7 +4979,8 @@
             MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->tierUpCounter.m_counter));
         
         silentSpillAllRegisters(InvalidGPRReg);
-        m_jit.setupArgumentsExecState();
+        m_jit.setupArgumentsWithExecState(
+            TrustedImm32(node->origin.semantic.bytecodeIndex));
         appendCall(triggerTierUpNowInLoop);
         silentFillAllRegisters(InvalidGPRReg);
         
@@ -5002,28 +5003,28 @@
         break;
     }
         
-    case CheckTierUpAndOSREnter:
-    case CheckTierUpWithNestedTriggerAndOSREnter: {
+    case CheckTierUpAndOSREnter: {
         ASSERT(!node->origin.semantic.inlineCallFrame);
         
         GPRTemporary temp(this);
         GPRReg tempGPR = temp.gpr();
 
-        MacroAssembler::Jump forceOSREntry;
-        if (op == CheckTierUpWithNestedTriggerAndOSREnter)
-            forceOSREntry = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->nestedTriggerIsSet));
+        unsigned bytecodeIndex = node->origin.semantic.bytecodeIndex;
+        auto triggerIterator = m_jit.jitCode()->tierUpEntryTriggers.find(bytecodeIndex);
+        RELEASE_ASSERT(triggerIterator != m_jit.jitCode()->tierUpEntryTriggers.end());
+        uint8_t* forceEntryTrigger = &(m_jit.jitCode()->tierUpEntryTriggers.find(bytecodeIndex)->value);
+        MacroAssembler::Jump forceOSREntry = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::AbsoluteAddress(forceEntryTrigger));
         
         MacroAssembler::Jump done = m_jit.branchAdd32(
             MacroAssembler::Signed,
             TrustedImm32(Options::ftlTierUpCounterIncrementForLoop()),
             MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->tierUpCounter.m_counter));
 
-        if (forceOSREntry.isSet())
-            forceOSREntry.link(&m_jit);
+        forceOSREntry.link(&m_jit);
         silentSpillAllRegisters(tempGPR);
-        m_jit.setupArgumentsWithExecState(
-            TrustedImm32(node->origin.semantic.bytecodeIndex),
-            TrustedImm32(m_stream->size()));
+        unsigned streamIndex = m_stream->size();
+        m_jit.jitCode()->bytecodeIndexToStreamIndex.add(bytecodeIndex, streamIndex);
+        m_jit.setupArgumentsWithExecState(TrustedImm32(bytecodeIndex));
         appendCallSetResult(triggerOSREntryNow, tempGPR);
         MacroAssembler::Jump dontEnter = m_jit.branchTestPtr(MacroAssembler::Zero, tempGPR);
         m_jit.emitRestoreCalleeSaves();
@@ -5038,7 +5039,6 @@
     case CheckTierUpInLoop:
     case CheckTierUpAtReturn:
     case CheckTierUpAndOSREnter:
-    case CheckTierUpWithNestedTriggerAndOSREnter:
         DFG_CRASH(m_jit.graph(), node, "Unexpected tier-up node");
         break;
 #endif // ENABLE(FTL_JIT)

Modified: trunk/Source/_javascript_Core/dfg/DFGTierUpCheckInjectionPhase.cpp (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGTierUpCheckInjectionPhase.cpp	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGTierUpCheckInjectionPhase.cpp	2016-03-09 17:51:38 UTC (rev 197861)
@@ -65,49 +65,73 @@
         if (!Options::useOSREntryToFTL())
             level = FTL::CanCompile;
 
-        // First we find all the loops that contain a LoopHint for which we cannot OSR enter.
-        // We use that information to decide if we need CheckTierUpAndOSREnter or CheckTierUpWithNestedTriggerAndOSREnter.
         m_graph.ensureNaturalLoops();
         NaturalLoops& naturalLoops = *m_graph.m_naturalLoops;
+        HashMap<const NaturalLoop*, unsigned> naturalLoopToLoopHint = buildNaturalLoopToLoopHintMap(naturalLoops);
 
-        HashSet<const NaturalLoop*> loopsContainingLoopHintWithoutOSREnter = findLoopsContainingLoopHintWithoutOSREnter(naturalLoops, level);
+        HashMap<unsigned, LoopHintDescriptor> tierUpHierarchy;
 
-        bool canTierUpAndOSREnter = false;
-        
         InsertionSet insertionSet(m_graph);
         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
             BasicBlock* block = m_graph.block(blockIndex);
             if (!block)
                 continue;
-            
+
             for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
                 Node* node = block->at(nodeIndex);
                 if (node->op() != LoopHint)
                     continue;
 
                 NodeOrigin origin = node->origin;
-                if (canOSREnterAtLoopHint(level, block, nodeIndex)) {
-                    canTierUpAndOSREnter = true;
-                    const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block);
-                    if (loop && loopsContainingLoopHintWithoutOSREnter.contains(loop))
-                        insertionSet.insertNode(nodeIndex + 1, SpecNone, CheckTierUpWithNestedTriggerAndOSREnter, origin);
-                    else
-                        insertionSet.insertNode(nodeIndex + 1, SpecNone, CheckTierUpAndOSREnter, origin);
-                } else
-                    insertionSet.insertNode(nodeIndex + 1, SpecNone, CheckTierUpInLoop, origin);
+                bool canOSREnter = canOSREnterAtLoopHint(level, block, nodeIndex);
+
+                NodeType tierUpType = CheckTierUpAndOSREnter;
+                if (!canOSREnter)
+                    tierUpType = CheckTierUpInLoop;
+                insertionSet.insertNode(nodeIndex + 1, SpecNone, tierUpType, origin);
+
+                unsigned bytecodeIndex = origin.semantic.bytecodeIndex;
+                if (canOSREnter)
+                    m_graph.m_plan.tierUpAndOSREnterBytecodes.append(bytecodeIndex);
+
+                if (const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block)) {
+                    LoopHintDescriptor descriptor;
+                    descriptor.canOSREnter = canOSREnter;
+
+                    const NaturalLoop* outerLoop = loop;
+                    while ((outerLoop = naturalLoops.innerMostOuterLoop(*outerLoop))) {
+                        auto it = naturalLoopToLoopHint.find(outerLoop);
+                        if (it != naturalLoopToLoopHint.end())
+                            descriptor.osrEntryCandidates.append(it->value);
+                    }
+                    if (!descriptor.osrEntryCandidates.isEmpty())
+                        tierUpHierarchy.add(bytecodeIndex, WTFMove(descriptor));
+                }
                 break;
             }
-            
+
             NodeAndIndex terminal = block->findTerminal();
             if (terminal.node->isFunctionTerminal()) {
                 insertionSet.insertNode(
                     terminal.index, SpecNone, CheckTierUpAtReturn, terminal.node->origin);
             }
-            
+
             insertionSet.execute(block);
         }
 
-        m_graph.m_plan.canTierUpAndOSREnter = canTierUpAndOSREnter;
+        // Add all the candidates that can be OSR Entered.
+        for (auto entry : tierUpHierarchy) {
+            Vector<unsigned> tierUpCandidates;
+            for (unsigned bytecodeIndex : entry.value.osrEntryCandidates) {
+                auto descriptorIt = tierUpHierarchy.find(bytecodeIndex);
+                if (descriptorIt != tierUpHierarchy.end()
+                    && descriptorIt->value.canOSREnter)
+                    tierUpCandidates.append(bytecodeIndex);
+            }
+
+            if (!tierUpCandidates.isEmpty())
+                m_graph.m_plan.tierUpInLoopHierarchy.add(entry.key, WTFMove(tierUpCandidates));
+        }
         m_graph.m_plan.willTryToTierUp = true;
         return true;
 #else // ENABLE(FTL_JIT)
@@ -118,6 +142,11 @@
 
 private:
 #if ENABLE(FTL_JIT)
+    struct LoopHintDescriptor {
+        Vector<unsigned> osrEntryCandidates;
+        bool canOSREnter;
+    };
+
     bool canOSREnterAtLoopHint(FTL::CapabilityLevel level, const BasicBlock* block, unsigned nodeIndex)
     {
         Node* node = block->at(nodeIndex);
@@ -137,25 +166,24 @@
         return true;
     }
 
-    HashSet<const NaturalLoop*> findLoopsContainingLoopHintWithoutOSREnter(const NaturalLoops& naturalLoops, FTL::CapabilityLevel level)
+    HashMap<const NaturalLoop*, unsigned> buildNaturalLoopToLoopHintMap(const NaturalLoops& naturalLoops)
     {
-        HashSet<const NaturalLoop*> loopsContainingLoopHintWithoutOSREnter;
+        HashMap<const NaturalLoop*, unsigned> naturalLoopsToLoopHint;
+
         for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
             for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
                 Node* node = block->at(nodeIndex);
                 if (node->op() != LoopHint)
                     continue;
 
-                if (!canOSREnterAtLoopHint(level, block, nodeIndex)) {
-                    const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block);
-                    while (loop) {
-                        loopsContainingLoopHintWithoutOSREnter.add(loop);
-                        loop = naturalLoops.innerMostOuterLoop(*loop);
-                    }
+                if (const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block)) {
+                    unsigned bytecodeIndex = node->origin.semantic.bytecodeIndex;
+                    naturalLoopsToLoopHint.add(loop, bytecodeIndex);
                 }
+                break;
             }
         }
-        return loopsContainingLoopHintWithoutOSREnter;
+        return naturalLoopsToLoopHint;
     }
 #endif
 };

Modified: trunk/Source/_javascript_Core/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp	2016-03-09 17:51:38 UTC (rev 197861)
@@ -31,11 +31,13 @@
 #include "CodeBlock.h"
 #include "DFGJITCode.h"
 #include "Executable.h"
+#include "FTLForOSREntryJITCode.h"
 #include "JSCInlines.h"
 
 namespace JSC { namespace DFG {
 
-ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback()
+ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback(uint8_t* forcedOSREntryTrigger)
+    : m_forcedOSREntryTrigger(forcedOSREntryTrigger)
 {
 }
 
@@ -43,9 +45,9 @@
 {
 }
 
-Ref<ToFTLForOSREntryDeferredCompilationCallback>ToFTLForOSREntryDeferredCompilationCallback::create()
+Ref<ToFTLForOSREntryDeferredCompilationCallback>ToFTLForOSREntryDeferredCompilationCallback::create(uint8_t* forcedOSREntryTrigger)
 {
-    return adoptRef(*new ToFTLForOSREntryDeferredCompilationCallback());
+    return adoptRef(*new ToFTLForOSREntryDeferredCompilationCallback(forcedOSREntryTrigger));
 }
 
 void ToFTLForOSREntryDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously(
@@ -56,9 +58,8 @@
             "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
             ") did become ready.\n");
     }
-    
-    profiledDFGCodeBlock->jitCode()->dfg()->forceOptimizationSlowPathConcurrently(
-        profiledDFGCodeBlock);
+
+    *m_forcedOSREntryTrigger = 1;
 }
 
 void ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete(
@@ -73,12 +74,17 @@
     JITCode* jitCode = profiledDFGCodeBlock->jitCode()->dfg();
         
     switch (result) {
-    case CompilationSuccessful:
+    case CompilationSuccessful: {
         jitCode->setOSREntryBlock(*codeBlock->vm(), profiledDFGCodeBlock, codeBlock);
+        unsigned osrEntryBytecode = codeBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
+        jitCode->tierUpEntryTriggers.set(osrEntryBytecode, 1);
         break;
+    }
     case CompilationFailed:
         jitCode->osrEntryRetry = 0;
         jitCode->abandonOSREntry = true;
+        profiledDFGCodeBlock->jitCode()->dfg()->setOptimizationThresholdBasedOnCompilationResult(
+            profiledDFGCodeBlock, result);
         break;
     case CompilationDeferred:
         RELEASE_ASSERT_NOT_REACHED();

Modified: trunk/Source/_javascript_Core/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h (197860 => 197861)


--- trunk/Source/_javascript_Core/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h	2016-03-09 17:44:24 UTC (rev 197860)
+++ trunk/Source/_javascript_Core/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h	2016-03-09 17:51:38 UTC (rev 197861)
@@ -40,15 +40,18 @@
 
 class ToFTLForOSREntryDeferredCompilationCallback : public DeferredCompilationCallback {
 protected:
-    ToFTLForOSREntryDeferredCompilationCallback();
+    ToFTLForOSREntryDeferredCompilationCallback(uint8_t* forcedOSREntryTrigger);
 
 public:
     virtual ~ToFTLForOSREntryDeferredCompilationCallback();
 
-    static Ref<ToFTLForOSREntryDeferredCompilationCallback> create();
+    static Ref<ToFTLForOSREntryDeferredCompilationCallback> create(uint8_t* forcedOSREntryTrigger);
     
     virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*, CodeBlock* profiledDFGCodeBlock);
     virtual void compilationDidComplete(CodeBlock*, CodeBlock* profiledDFGCodeBlock, CompilationResult);
+
+private:
+    uint8_t* m_forcedOSREntryTrigger;
 };
 
 } } // namespace JSC::DFG
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to