<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[189889] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/189889">189889</a></dd>
<dt>Author</dt> <dd>ggaren@apple.com</dd>
<dt>Date</dt> <dd>2015-09-16 17:28:34 -0700 (Wed, 16 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>JavaScriptCore should discard baseline code after some time
https://bugs.webkit.org/show_bug.cgi?id=149220

Reviewed by Saam Barati.

This is a bit more complicated than discarding optimized code because
the engine previously assumed that we would never discard baseline code.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock): Record creation time (and compute time since
creation) instead of install time because CodeBlocks can be installed
more than once, and we don't want to have to worry about edge cases
created by CodeBlocks seeming to get younger.

(JSC::CodeBlock::visitAggregate): Be explicit about only doing the 
weak reference fixpoint for optimized CodeBlocks. We used to avoid the
fixpoint for baseline CodeBlocks implicitly, since they would always
visit themselves strongly right away. But now baseline CodeBlocks might
not visit themselves strongly, since they might choose to jettison due
to old age.

(JSC::CodeBlock::shouldVisitStrongly): Add old age as a reason not to
visit ourselves strongly, so that baseline CodeBlocks can jettison due
to old age.

(JSC::CodeBlock::shouldJettisonDueToWeakReference): Be explicit about
only jettisoning optimized CodeBlocks due to weak references so that we
don't confuse ourselves into thinking that we will jettison a baseline
CodeBlock due to weak references.

(JSC::CodeBlock::shouldJettisonDueToOldAge): Updated to use creation time.

(JSC::CodeBlock::visitOSRExitTargets): Clarify a comment and add an
ASSERT to help record some things I discovered while debugging.

(JSC::CodeBlock::jettison): Allow a baseline CodeBlock to jettison. Don't
assume that we have an alternative or a profiler.

(JSC::CodeBlock::install): Deleted.
* bytecode/CodeBlock.h:
(JSC::CodeBlock::releaseAlternative): Deleted.
(JSC::CodeBlock::setInstallTime): Deleted.
(JSC::CodeBlock::timeSinceInstall): Deleted.

* dfg/DFGOSRExitPreparation.cpp:
(JSC::DFG::prepareCodeOriginForOSRExit): Simplified the computation of
baseline CodeBlock.

* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::checkLivenessAndVisitChildren): Be sure to strongly
visit our inline callframes because we assume that an optimized CodeBlock
will keep its OSR exit targets alive, but the CodeBlock object won't be
able to mark them for itself until compilation has completed (since it
won't have a JITCode object yet).

* dfg/DFGToFTLDeferredCompilationCallback.cpp:
(JSC::DFG::ToFTLDeferredCompilationCallback::compilationDidComplete):
Updated for interface change.

* jit/JITCode.h:
(JSC::JITCode::timeToLive): Provide a time to live for interpreter and
baseline code, so they will jettison when old. Use seconds in our
code so that we don't need comments. Make DFG 2X interpreter+baseline,
and FTL 2X DFG+interpreter+baseline, also matching the time we allot
before throwing away all code.

* jit/JITToDFGDeferredCompilationCallback.cpp:
(JSC::JITToDFGDeferredCompilationCallback::compilationDidComplete):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::jitCompileAndSetHeuristics): Updated for interface change.

* runtime/Executable.cpp:
(JSC::ScriptExecutable::installCode): Allow our caller to install nullptr,
since we need to do this when jettisoning a baseline CodeBlock. Require
our caller to specify the details of the installation because we can't
rely on a non-null CodeBlock in order to compute them.

(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::prepareForExecutionImpl):
* runtime/Executable.h:
(JSC::ScriptExecutable::recordParse): Updated for interface change.

* runtime/Options.h: Renamed the CodeBlock liveness option since it now
controls baseline and optimized code.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitPreparationcpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlancpp">trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGToFTLDeferredCompilationCallbackcpp">trunk/Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCodeh">trunk/Source/JavaScriptCore/jit/JITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITToDFGDeferredCompilationCallbackcpp">trunk/Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeExecutablecpp">trunk/Source/JavaScriptCore/runtime/Executable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeExecutableh">trunk/Source/JavaScriptCore/runtime/Executable.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -1,5 +1,92 @@
</span><span class="cx"> 2015-09-16  Geoffrey Garen  &lt;ggaren@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        JavaScriptCore should discard baseline code after some time
+        https://bugs.webkit.org/show_bug.cgi?id=149220
+
+        Reviewed by Saam Barati.
+
+        This is a bit more complicated than discarding optimized code because
+        the engine previously assumed that we would never discard baseline code.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock): Record creation time (and compute time since
+        creation) instead of install time because CodeBlocks can be installed
+        more than once, and we don't want to have to worry about edge cases
+        created by CodeBlocks seeming to get younger.
+
+        (JSC::CodeBlock::visitAggregate): Be explicit about only doing the 
+        weak reference fixpoint for optimized CodeBlocks. We used to avoid the
+        fixpoint for baseline CodeBlocks implicitly, since they would always
+        visit themselves strongly right away. But now baseline CodeBlocks might
+        not visit themselves strongly, since they might choose to jettison due
+        to old age.
+
+        (JSC::CodeBlock::shouldVisitStrongly): Add old age as a reason not to
+        visit ourselves strongly, so that baseline CodeBlocks can jettison due
+        to old age.
+
+        (JSC::CodeBlock::shouldJettisonDueToWeakReference): Be explicit about
+        only jettisoning optimized CodeBlocks due to weak references so that we
+        don't confuse ourselves into thinking that we will jettison a baseline
+        CodeBlock due to weak references.
+
+        (JSC::CodeBlock::shouldJettisonDueToOldAge): Updated to use creation time.
+
+        (JSC::CodeBlock::visitOSRExitTargets): Clarify a comment and add an
+        ASSERT to help record some things I discovered while debugging.
+
+        (JSC::CodeBlock::jettison): Allow a baseline CodeBlock to jettison. Don't
+        assume that we have an alternative or a profiler.
+
+        (JSC::CodeBlock::install): Deleted.
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::releaseAlternative): Deleted.
+        (JSC::CodeBlock::setInstallTime): Deleted.
+        (JSC::CodeBlock::timeSinceInstall): Deleted.
+
+        * dfg/DFGOSRExitPreparation.cpp:
+        (JSC::DFG::prepareCodeOriginForOSRExit): Simplified the computation of
+        baseline CodeBlock.
+
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::checkLivenessAndVisitChildren): Be sure to strongly
+        visit our inline callframes because we assume that an optimized CodeBlock
+        will keep its OSR exit targets alive, but the CodeBlock object won't be
+        able to mark them for itself until compilation has completed (since it
+        won't have a JITCode object yet).
+
+        * dfg/DFGToFTLDeferredCompilationCallback.cpp:
+        (JSC::DFG::ToFTLDeferredCompilationCallback::compilationDidComplete):
+        Updated for interface change.
+
+        * jit/JITCode.h:
+        (JSC::JITCode::timeToLive): Provide a time to live for interpreter and
+        baseline code, so they will jettison when old. Use seconds in our
+        code so that we don't need comments. Make DFG 2X interpreter+baseline,
+        and FTL 2X DFG+interpreter+baseline, also matching the time we allot
+        before throwing away all code.
+
+        * jit/JITToDFGDeferredCompilationCallback.cpp:
+        (JSC::JITToDFGDeferredCompilationCallback::compilationDidComplete):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::jitCompileAndSetHeuristics): Updated for interface change.
+
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::installCode): Allow our caller to install nullptr,
+        since we need to do this when jettisoning a baseline CodeBlock. Require
+        our caller to specify the details of the installation because we can't
+        rely on a non-null CodeBlock in order to compute them.
+
+        (JSC::ScriptExecutable::newCodeBlockFor):
+        (JSC::ScriptExecutable::prepareForExecutionImpl):
+        * runtime/Executable.h:
+        (JSC::ScriptExecutable::recordParse): Updated for interface change.
+
+        * runtime/Options.h: Renamed the CodeBlock liveness option since it now
+        controls baseline and optimized code.
+
+2015-09-16  Geoffrey Garen  &lt;ggaren@apple.com&gt;
+
</ins><span class="cx">         Remove obsolete code for deleting CodeBlocks
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=149231
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -1617,6 +1617,7 @@
</span><span class="cx">     , m_osrExitCounter(0)
</span><span class="cx">     , m_optimizationDelayCounter(0)
</span><span class="cx">     , m_reoptimizationRetryCounter(0)
</span><ins>+    , m_creationTime(std::chrono::steady_clock::now())
</ins><span class="cx">     , m_hash(other.m_hash)
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
</span><span class="lines">@@ -1672,6 +1673,7 @@
</span><span class="cx">     , m_osrExitCounter(0)
</span><span class="cx">     , m_optimizationDelayCounter(0)
</span><span class="cx">     , m_reoptimizationRetryCounter(0)
</span><ins>+    , m_creationTime(std::chrono::steady_clock::now())
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
</span><span class="cx"> #endif
</span><span class="lines">@@ -2150,6 +2152,7 @@
</span><span class="cx">     , m_osrExitCounter(0)
</span><span class="cx">     , m_optimizationDelayCounter(0)
</span><span class="cx">     , m_reoptimizationRetryCounter(0)
</span><ins>+    , m_creationTime(std::chrono::steady_clock::now())
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     , m_capabilityLevelState(DFG::CannotCompile)
</span><span class="cx"> #endif
</span><span class="lines">@@ -2272,6 +2275,9 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    if (!JITCode::isOptimizingJIT(jitType()))
+        return;
+
</ins><span class="cx">     // There are two things that we use weak reference harvesters for: DFG fixpoint for
</span><span class="cx">     // jettisoning, and trying to find structures that would be live based on some
</span><span class="cx">     // inline cache. So it makes sense to register them regardless.
</span><span class="lines">@@ -2291,27 +2297,24 @@
</span><span class="cx">     
</span><span class="cx">     propagateTransitions(visitor);
</span><span class="cx">     determineLiveness(visitor);
</span><del>-#else // ENABLE(DFG_JIT)
-    RELEASE_ASSERT_NOT_REACHED();
</del><span class="cx"> #endif // ENABLE(DFG_JIT)
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool CodeBlock::shouldVisitStrongly()
</span><span class="cx"> {
</span><del>-#if ENABLE(DFG_JIT)
</del><ins>+    if (Options::forceCodeBlockLiveness())
+        return true;
+
+    if (shouldJettisonDueToOldAge())
+        return false;
+
</ins><span class="cx">     // Interpreter and Baseline JIT CodeBlocks don't need to be jettisoned when
</span><span class="cx">     // their weak references go stale. So if a basline JIT CodeBlock gets
</span><span class="cx">     // scanned, we can assume that this means that it's live.
</span><span class="cx">     if (!JITCode::isOptimizingJIT(jitType()))
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    if (Options::forceDFGCodeBlockLiveness())
-        return true;
-
</del><span class="cx">     return false;
</span><del>-#else
-    return true;
-#endif
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool CodeBlock::isKnownToBeLiveDuringGC()
</span><span class="lines">@@ -2339,6 +2342,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool CodeBlock::shouldJettisonDueToWeakReference()
</span><span class="cx"> {
</span><ins>+    if (!JITCode::isOptimizingJIT(jitType()))
+        return false;
</ins><span class="cx">     return !isKnownToBeLiveDuringGC();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2347,12 +2352,9 @@
</span><span class="cx">     if (m_visitStronglyHasBeenCalled.load(std::memory_order_relaxed))
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (!JITCode::isOptimizingJIT(jitType()))
</del><ins>+    if (timeSinceCreation() &lt; JITCode::timeToLive(jitType()))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (timeSinceInstall() &lt; JITCode::timeToLive(jitType()))
-        return false;
-
</del><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2739,17 +2741,20 @@
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::visitOSRExitTargets(SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><del>-    // OSR exits, once compiled, link themselves directly to their targets.
-    // We need to keep those targets alive in order to keep OSR exit from
-    // jumping to an invalid destination.
</del><ins>+    // We strongly visit OSR exits targets because we don't want to deal with
+    // the complexity of generating an exit target CodeBlock on demand and
+    // guaranteeing that it matches the details of the CodeBlock we compiled
+    // the OSR exit against.
</ins><span class="cx"> 
</span><span class="cx">     alternative()-&gt;visitStrongly(visitor);
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     DFG::CommonData* dfgCommon = m_jitCode-&gt;dfgCommon();
</span><span class="cx">     if (dfgCommon-&gt;inlineCallFrames) {
</span><del>-        for (auto* inlineCallFrame : *dfgCommon-&gt;inlineCallFrames)
</del><ins>+        for (auto* inlineCallFrame : *dfgCommon-&gt;inlineCallFrames) {
+            ASSERT(inlineCallFrame-&gt;baselineCodeBlock());
</ins><span class="cx">             inlineCallFrame-&gt;baselineCodeBlock()-&gt;visitStrongly(visitor);
</span><ins>+        }
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="lines">@@ -2967,11 +2972,6 @@
</span><span class="cx">     m_incomingLLIntCalls.push(incoming);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CodeBlock::install()
-{
-    ownerScriptExecutable()-&gt;installCode(this);
-}
-
</del><span class="cx"> PassRefPtr&lt;CodeBlock&gt; CodeBlock::newReplacement()
</span><span class="cx"> {
</span><span class="cx">     return ownerScriptExecutable()-&gt;newReplacementCodeBlockFor(specializationKind());
</span><span class="lines">@@ -3035,6 +3035,11 @@
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
</span><span class="cx"> {
</span><ins>+#if !ENABLE(DFG_JIT)
+    UNUSED_PARAM(mode);
+    UNUSED_PARAM(detail);
+#endif
+
</ins><span class="cx">     RELEASE_ASSERT(reason != Profiler::NotJettisoned);
</span><span class="cx">     
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="lines">@@ -3069,19 +3074,20 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+#endif // ENABLE(DFG_JIT)
</ins><span class="cx"> 
</span><span class="cx">     DeferGCForAWhile deferGC(*m_heap);
</span><del>-    RELEASE_ASSERT(JITCode::isOptimizingJIT(jitType()));
</del><span class="cx">     
</span><del>-    if (Profiler::Compilation* compilation = jitCode()-&gt;dfgCommon()-&gt;compilation.get())
-        compilation-&gt;setJettisonReason(reason, detail);
-    
</del><span class="cx">     // We want to accomplish two things here:
</span><span class="cx">     // 1) Make sure that if this CodeBlock is on the stack right now, then if we return to it
</span><span class="cx">     //    we should OSR exit at the top of the next bytecode instruction after the return.
</span><span class="cx">     // 2) Make sure that if we call the owner executable, then we shouldn't call this CodeBlock.
</span><span class="cx"> 
</span><ins>+#if ENABLE(DFG_JIT)
</ins><span class="cx">     if (reason != Profiler::JettisonDueToOldAge) {
</span><ins>+        if (Profiler::Compilation* compilation = jitCode()-&gt;dfgCommon()-&gt;compilation.get())
+            compilation-&gt;setJettisonReason(reason, detail);
+        
</ins><span class="cx">         // This accomplishes (1), and does its own book-keeping about whether it has already happened.
</span><span class="cx">         if (!jitCode()-&gt;dfgCommon()-&gt;invalidate()) {
</span><span class="cx">             // We've already been invalidated.
</span><span class="lines">@@ -3102,24 +3108,26 @@
</span><span class="cx">             dataLog(&quot;    Did count reoptimization for &quot;, *this, &quot;\n&quot;);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    // This accomplishes (2).
</del><span class="cx">     if (this != replacement()) {
</span><span class="cx">         // This means that we were never the entrypoint. This can happen for OSR entry code
</span><span class="cx">         // blocks.
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    alternative()-&gt;optimizeAfterWarmUp();
</del><span class="cx"> 
</span><ins>+    if (alternative())
+        alternative()-&gt;optimizeAfterWarmUp();
+
</ins><span class="cx">     if (reason != Profiler::JettisonDueToOldAge)
</span><span class="cx">         tallyFrequentExitSites();
</span><ins>+#endif // ENABLE(DFG_JIT)
</ins><span class="cx"> 
</span><del>-    alternative()-&gt;install();
</del><ins>+    // This accomplishes (2).
+    ownerScriptExecutable()-&gt;installCode(
+        m_globalObject-&gt;vm(), alternative(), codeType(), specializationKind());
+
+#if ENABLE(DFG_JIT)
</ins><span class="cx">     if (DFG::shouldShowDisassembly())
</span><span class="cx">         dataLog(&quot;    Did install baseline version of &quot;, *this, &quot;\n&quot;);
</span><del>-#else // ENABLE(DFG_JIT)
-    UNUSED_PARAM(mode);
-    UNUSED_PARAM(detail);
-    UNREACHABLE_FOR_PLATFORM();
</del><span class="cx"> #endif // ENABLE(DFG_JIT)
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -126,7 +126,6 @@
</span><span class="cx">     static ptrdiff_t offsetOfNumParameters() { return OBJECT_OFFSETOF(CodeBlock, m_numParameters); }
</span><span class="cx"> 
</span><span class="cx">     CodeBlock* alternative() { return m_alternative.get(); }
</span><del>-    PassRefPtr&lt;CodeBlock&gt; releaseAlternative() { return m_alternative.release(); }
</del><span class="cx">     void setAlternative(PassRefPtr&lt;CodeBlock&gt; alternative) { m_alternative = alternative; }
</span><span class="cx"> 
</span><span class="cx">     template &lt;typename Functor&gt; void forEachRelatedCodeBlock(Functor&amp;&amp; functor)
</span><span class="lines">@@ -265,9 +264,6 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned instructionCount() const { return m_instructions.size(); }
</span><span class="cx"> 
</span><del>-    // Exactly equivalent to codeBlock-&gt;ownerExecutable()-&gt;installCode(codeBlock);
-    void install();
-    
</del><span class="cx">     // Exactly equivalent to codeBlock-&gt;ownerExecutable()-&gt;newReplacementCodeBlockFor(codeBlock-&gt;specializationKind())
</span><span class="cx">     PassRefPtr&lt;CodeBlock&gt; newReplacement();
</span><span class="cx">     
</span><span class="lines">@@ -834,8 +830,6 @@
</span><span class="cx">     void updateAllArrayPredictions();
</span><span class="cx">     void updateAllPredictions();
</span><span class="cx"> 
</span><del>-    void setInstallTime(std::chrono::steady_clock::time_point installTime) { m_installTime = installTime; }
-
</del><span class="cx">     unsigned frameRegisterCount();
</span><span class="cx">     int stackPointerOffset();
</span><span class="cx"> 
</span><span class="lines">@@ -989,10 +983,10 @@
</span><span class="cx">     void stronglyVisitWeakReferences(SlotVisitor&amp;);
</span><span class="cx">     void visitOSRExitTargets(SlotVisitor&amp;);
</span><span class="cx"> 
</span><del>-    std::chrono::milliseconds timeSinceInstall()
</del><ins>+    std::chrono::milliseconds timeSinceCreation()
</ins><span class="cx">     {
</span><span class="cx">         return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(
</span><del>-            std::chrono::steady_clock::now() - m_installTime);
</del><ins>+            std::chrono::steady_clock::now() - m_creationTime);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void createRareDataIfNecessary()
</span><span class="lines">@@ -1077,7 +1071,7 @@
</span><span class="cx">     uint16_t m_optimizationDelayCounter;
</span><span class="cx">     uint16_t m_reoptimizationRetryCounter;
</span><span class="cx"> 
</span><del>-    std::chrono::steady_clock::time_point m_installTime;
</del><ins>+    std::chrono::steady_clock::time_point m_creationTime;
</ins><span class="cx"> 
</span><span class="cx">     mutable CodeBlockHash m_hash;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitPreparationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -42,16 +42,13 @@
</span><span class="cx">     DeferGC deferGC(vm.heap);
</span><span class="cx">     
</span><span class="cx">     for (; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame-&gt;caller) {
</span><del>-        FunctionExecutable* executable =
-            static_cast&lt;FunctionExecutable*&gt;(codeOrigin.inlineCallFrame-&gt;executable.get());
-        CodeBlock* codeBlock = executable-&gt;baselineCodeBlockFor(
-            codeOrigin.inlineCallFrame-&gt;specializationKind());
-        
</del><ins>+        CodeBlock* codeBlock = codeOrigin.inlineCallFrame-&gt;baselineCodeBlock();
</ins><span class="cx">         if (codeBlock-&gt;jitType() == JSC::JITCode::BaselineJIT)
</span><span class="cx">             continue;
</span><ins>+
</ins><span class="cx">         ASSERT(codeBlock-&gt;jitType() == JSC::JITCode::InterpreterThunk);
</span><span class="cx">         JIT::compile(&amp;vm, codeBlock, JITCompilationMustSucceed);
</span><del>-        codeBlock-&gt;install();
</del><ins>+        codeBlock-&gt;ownerScriptExecutable()-&gt;installCode(codeBlock);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -626,6 +626,13 @@
</span><span class="cx">     if (profiledDFGCodeBlock)
</span><span class="cx">         profiledDFGCodeBlock-&gt;visitStrongly(visitor);
</span><span class="cx"> 
</span><ins>+    if (inlineCallFrames) {
+        for (auto* inlineCallFrame : *inlineCallFrames) {
+            ASSERT(inlineCallFrame-&gt;baselineCodeBlock());
+            inlineCallFrame-&gt;baselineCodeBlock()-&gt;visitStrongly(visitor);
+        }
+    }
+
</ins><span class="cx">     weakReferences.visitChildren(visitor);
</span><span class="cx">     transitions.visitChildren(visitor);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGToFTLDeferredCompilationCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -80,7 +80,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (result == CompilationSuccessful)
</span><del>-        codeBlock-&gt;install();
</del><ins>+        codeBlock-&gt;ownerScriptExecutable()-&gt;installCode(codeBlock);
</ins><span class="cx">     
</span><span class="cx">     m_dfgCodeBlock-&gt;jitCode()-&gt;dfg()-&gt;setOptimizationThresholdBasedOnCompilationResult(
</span><span class="cx">         m_dfgCodeBlock.get(), result);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCode.h (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCode.h        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/jit/JITCode.h        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -125,10 +125,20 @@
</span><span class="cx">     static std::chrono::milliseconds timeToLive(JITType jitType)
</span><span class="cx">     {
</span><span class="cx">         switch (jitType) {
</span><ins>+        case InterpreterThunk:
+            return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(
+                std::chrono::seconds(5));
+        case BaselineJIT:
+            // Effectively 10 additional seconds, since BaselineJIT and
+            // InterpreterThunk share a CodeBlock.
+            return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(
+                std::chrono::seconds(15));
</ins><span class="cx">         case DFGJIT:
</span><del>-            return std::chrono::milliseconds(10000); // 10s
</del><ins>+            return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(
+                std::chrono::seconds(20));
</ins><span class="cx">         case FTLJIT:
</span><del>-            return std::chrono::milliseconds(100000); // 100s
</del><ins>+            return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(
+                std::chrono::seconds(60));
</ins><span class="cx">         default:
</span><span class="cx">             return std::chrono::milliseconds::max();
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITToDFGDeferredCompilationCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx">         dataLog(&quot;Optimizing compilation of &quot;, *codeBlock, &quot; result: &quot;, result, &quot;\n&quot;);
</span><span class="cx">     
</span><span class="cx">     if (result == CompilationSuccessful)
</span><del>-        codeBlock-&gt;install();
</del><ins>+        codeBlock-&gt;ownerScriptExecutable()-&gt;installCode(codeBlock);
</ins><span class="cx">     
</span><span class="cx">     codeBlock-&gt;alternative()-&gt;setOptimizationThresholdBasedOnCompilationResult(result);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -324,7 +324,7 @@
</span><span class="cx">         case CompilationSuccessful:
</span><span class="cx">             if (Options::verboseOSR())
</span><span class="cx">                 dataLogF(&quot;    JIT compilation successful.\n&quot;);
</span><del>-            codeBlock-&gt;install();
</del><ins>+            codeBlock-&gt;ownerScriptExecutable()-&gt;installCode(codeBlock);
</ins><span class="cx">             codeBlock-&gt;jitSoon();
</span><span class="cx">             return true;
</span><span class="cx">         default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Executable.cpp (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Executable.cpp        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/runtime/Executable.cpp        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -116,41 +116,18 @@
</span><span class="cx">     static_cast&lt;ScriptExecutable*&gt;(cell)-&gt;ScriptExecutable::~ScriptExecutable();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
</del><ins>+void ScriptExecutable::installCode(CodeBlock* codeBlock)
</ins><span class="cx"> {
</span><del>-    RELEASE_ASSERT(genericCodeBlock-&gt;ownerExecutable() == this);
-    RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock-&gt;jitType()));
-    
-    if (Options::verboseOSR())
-        dataLog(&quot;Installing &quot;, *genericCodeBlock, &quot;\n&quot;);
-    
-    VM&amp; vm = *genericCodeBlock-&gt;vm();
-    
-    if (vm.m_perBytecodeProfiler)
-        vm.m_perBytecodeProfiler-&gt;ensureBytecodesFor(genericCodeBlock);
-    
</del><ins>+    installCode(*codeBlock-&gt;vm(), codeBlock, codeBlock-&gt;codeType(), codeBlock-&gt;specializationKind());
+}
+
+void ScriptExecutable::installCode(VM&amp; vm, CodeBlock* genericCodeBlock, CodeType codeType, CodeSpecializationKind kind)
+{
</ins><span class="cx">     ASSERT(vm.heap.isDeferred());
</span><span class="cx">     
</span><del>-    CodeSpecializationKind kind = genericCodeBlock-&gt;specializationKind();
-    
</del><span class="cx">     RefPtr&lt;CodeBlock&gt; oldCodeBlock;
</span><span class="cx">     
</span><del>-    switch (kind) {
-    case CodeForCall:
-        m_jitCodeForCall = genericCodeBlock-&gt;jitCode();
-        m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
-        m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
-        m_numParametersForCall = genericCodeBlock-&gt;numParameters();
-        break;
-    case CodeForConstruct:
-        m_jitCodeForConstruct = genericCodeBlock-&gt;jitCode();
-        m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
-        m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
-        m_numParametersForConstruct = genericCodeBlock-&gt;numParameters();
-        break;
-    }
-    
-    switch (genericCodeBlock-&gt;codeType()) {
</del><ins>+    switch (codeType) {
</ins><span class="cx">     case GlobalCode: {
</span><span class="cx">         ProgramExecutable* executable = jsCast&lt;ProgramExecutable*&gt;(this);
</span><span class="cx">         ProgramCodeBlock* codeBlock = static_cast&lt;ProgramCodeBlock*&gt;(genericCodeBlock);
</span><span class="lines">@@ -199,18 +176,42 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         break;
</span><del>-    } }
</del><ins>+    }
+    }
</ins><span class="cx"> 
</span><ins>+    switch (kind) {
+    case CodeForCall:
+        m_jitCodeForCall = genericCodeBlock ? genericCodeBlock-&gt;jitCode() : nullptr;
+        m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
+        m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
+        m_numParametersForCall = genericCodeBlock ? genericCodeBlock-&gt;numParameters() : NUM_PARAMETERS_NOT_COMPILED;
+        break;
+    case CodeForConstruct:
+        m_jitCodeForConstruct = genericCodeBlock ? genericCodeBlock-&gt;jitCode() : nullptr;
+        m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
+        m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
+        m_numParametersForConstruct = genericCodeBlock ? genericCodeBlock-&gt;numParameters() : NUM_PARAMETERS_NOT_COMPILED;
+        break;
+    }
+
+    if (genericCodeBlock) {
+        RELEASE_ASSERT(genericCodeBlock-&gt;ownerExecutable() == this);
+        RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock-&gt;jitType()));
+        
+        if (Options::verboseOSR())
+            dataLog(&quot;Installing &quot;, *genericCodeBlock, &quot;\n&quot;);
+        
+        if (vm.m_perBytecodeProfiler)
+            vm.m_perBytecodeProfiler-&gt;ensureBytecodesFor(genericCodeBlock);
+        
+        if (Debugger* debugger = genericCodeBlock-&gt;globalObject()-&gt;debugger())
+            debugger-&gt;registerCodeBlock(genericCodeBlock);
+    }
+
</ins><span class="cx">     if (oldCodeBlock)
</span><span class="cx">         oldCodeBlock-&gt;unlinkIncomingCalls();
</span><span class="cx"> 
</span><del>-    Debugger* debugger = genericCodeBlock-&gt;globalObject()-&gt;debugger();
-    if (debugger)
-        debugger-&gt;registerCodeBlock(genericCodeBlock);
-
-    genericCodeBlock-&gt;setInstallTime(std::chrono::steady_clock::now());
-
-    Heap::heap(this)-&gt;writeBarrier(this);
</del><ins>+    vm.heap.writeBarrier(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RefPtr&lt;CodeBlock&gt; ScriptExecutable::newCodeBlockFor(
</span><span class="lines">@@ -367,7 +368,7 @@
</span><span class="cx">     else
</span><span class="cx">         setupJIT(vm, codeBlock.get());
</span><span class="cx">     
</span><del>-    installCode(codeBlock.get());
</del><ins>+    installCode(*codeBlock-&gt;vm(), codeBlock.get(), codeBlock-&gt;codeType(), codeBlock-&gt;specializationKind());
</ins><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Executable.h (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Executable.h        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/runtime/Executable.h        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -420,6 +420,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void installCode(CodeBlock*);
</span><ins>+    void installCode(VM&amp;, CodeBlock*, CodeType, CodeSpecializationKind);
</ins><span class="cx">     RefPtr&lt;CodeBlock&gt; newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*&amp; exception);
</span><span class="cx">     PassRefPtr&lt;CodeBlock&gt; newReplacementCodeBlockFor(CodeSpecializationKind);
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (189888 => 189889)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2015-09-17 00:16:35 UTC (rev 189888)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2015-09-17 00:28:34 UTC (rev 189889)
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx">     v(bool, crashIfCantAllocateJITMemory, false, nullptr) \
</span><span class="cx">     v(unsigned, jitMemoryReservationSize, 0, nullptr) \
</span><span class="cx">     \
</span><del>-    v(bool, forceDFGCodeBlockLiveness, false, nullptr) \
</del><ins>+    v(bool, forceCodeBlockLiveness, false, nullptr) \
</ins><span class="cx">     v(bool, forceICFailure, false, nullptr) \
</span><span class="cx">     \
</span><span class="cx">     v(bool, dumpGeneratedBytecodes, false, nullptr) \
</span></span></pre>
</div>
</div>

</body>
</html>