<!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>[204162] trunk</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/204162">204162</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-08-04 23:46:55 -0700 (Thu, 04 Aug 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Restore CodeBlock jettison code to jettison when a CodeBlock has been alive for a long time
https://bugs.webkit.org/show_bug.cgi?id=151241

Reviewed by Benjamin Poulain.

Source/JavaScriptCore:

This patch rolls back in the jettisoning policy from https://bugs.webkit.org/show_bug.cgi?id=149727.
We can now jettison a CodeBlock when it has been alive for a long time
and is only pointed to by its owner executable. I haven't been able to get this
patch to crash on anything it used to crash on, so I suspect we've fixed the bugs that
were causing this before. I've also added some stress options for this feature that
will cause us to either eagerly old-age jettison or to old-age jettison whenever it's legal.
These options helped me find a bug where we would ask an Executable to create a CodeBlock,
and then the Executable would do some other allocations, causing a GC, immediately causing
the CodeBlock to jettison. There is a small chance that this was the bug we were seeing before,
however, it's unlikely given that the previous timing metrics require at least 5 second between
compiling to jettisoning.

This patch also enables the stress options for various modes
of JSC stress tests.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::shouldJettisonDueToWeakReference):
(JSC::timeToLive):
(JSC::CodeBlock::shouldJettisonDueToOldAge):
* interpreter/CallFrame.h:
(JSC::ExecState::callee):
(JSC::ExecState::unsafeCallee):
(JSC::ExecState::codeBlock):
(JSC::ExecState::addressOfCodeBlock):
(JSC::ExecState::unsafeCodeBlock):
(JSC::ExecState::scope):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setUpCall):
* runtime/Executable.cpp:
(JSC::ScriptExecutable::installCode):
(JSC::setupJIT):
(JSC::ScriptExecutable::prepareForExecutionImpl):
* runtime/Executable.h:
(JSC::ScriptExecutable::prepareForExecution):
* runtime/Options.h:

Tools:

* Scripts/run-jsc-stress-tests:</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="#trunkSourceJavaScriptCoreinterpreterCallFrameh">trunk/Source/JavaScriptCore/interpreter/CallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.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>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsScriptsrunjscstresstests">trunk/Tools/Scripts/run-jsc-stress-tests</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -1,3 +1,52 @@
</span><ins>+2016-08-04  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        Restore CodeBlock jettison code to jettison when a CodeBlock has been alive for a long time
+        https://bugs.webkit.org/show_bug.cgi?id=151241
+
+        Reviewed by Benjamin Poulain.
+
+        This patch rolls back in the jettisoning policy from https://bugs.webkit.org/show_bug.cgi?id=149727.
+        We can now jettison a CodeBlock when it has been alive for a long time
+        and is only pointed to by its owner executable. I haven't been able to get this
+        patch to crash on anything it used to crash on, so I suspect we've fixed the bugs that
+        were causing this before. I've also added some stress options for this feature that
+        will cause us to either eagerly old-age jettison or to old-age jettison whenever it's legal.
+        These options helped me find a bug where we would ask an Executable to create a CodeBlock,
+        and then the Executable would do some other allocations, causing a GC, immediately causing
+        the CodeBlock to jettison. There is a small chance that this was the bug we were seeing before,
+        however, it's unlikely given that the previous timing metrics require at least 5 second between
+        compiling to jettisoning.
+
+        This patch also enables the stress options for various modes
+        of JSC stress tests.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::shouldJettisonDueToWeakReference):
+        (JSC::timeToLive):
+        (JSC::CodeBlock::shouldJettisonDueToOldAge):
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::callee):
+        (JSC::ExecState::unsafeCallee):
+        (JSC::ExecState::codeBlock):
+        (JSC::ExecState::addressOfCodeBlock):
+        (JSC::ExecState::unsafeCodeBlock):
+        (JSC::ExecState::scope):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::prepareForRepeatCall):
+        * jit/JITOperations.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::setUpCall):
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::installCode):
+        (JSC::setupJIT):
+        (JSC::ScriptExecutable::prepareForExecutionImpl):
+        * runtime/Executable.h:
+        (JSC::ScriptExecutable::prepareForExecution):
+        * runtime/Options.h:
+
</ins><span class="cx"> 2016-08-04  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] JSModuleNamespaceObject's Symbol.iterator function should have name
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -2651,9 +2651,51 @@
</span><span class="cx">     return !Heap::isMarked(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static std::chrono::milliseconds timeToLive(JITCode::JITType jitType)
+{
+    if (UNLIKELY(Options::useEagerCodeBlockJettisonTiming())) {
+        switch (jitType) {
+        case JITCode::InterpreterThunk:
+            return std::chrono::milliseconds(10);
+        case JITCode::BaselineJIT:
+            return std::chrono::milliseconds(10 + 20);
+        case JITCode::DFGJIT:
+            return std::chrono::milliseconds(40);
+        case JITCode::FTLJIT:
+            return std::chrono::milliseconds(120);
+        default:
+            return std::chrono::milliseconds::max();
+        }
+    }
+
+    switch (jitType) {
+    case JITCode::InterpreterThunk:
+        return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(std::chrono::seconds(5));
+    case JITCode::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(5 + 10));
+    case JITCode::DFGJIT:
+        return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(std::chrono::seconds(20));
+    case JITCode::FTLJIT:
+        return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(std::chrono::seconds(60));
+    default:
+        return std::chrono::milliseconds::max();
+    }
+}
+
</ins><span class="cx"> bool CodeBlock::shouldJettisonDueToOldAge()
</span><span class="cx"> {
</span><del>-    return false;
</del><ins>+    if (Heap::isMarked(this))
+        return false;
+
+    if (UNLIKELY(Options::forceCodeBlockToJettisonDueToOldAge()))
+        return true;
+    
+    if (timeSinceCreation() &lt; timeToLive(jitType()))
+        return false;
+    
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/CallFrame.h (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -90,6 +90,7 @@
</span><span class="cx">         JSObject* callee() const { return this[CallFrameSlot::callee].object(); }
</span><span class="cx">         SUPPRESS_ASAN JSValue unsafeCallee() const { return this[CallFrameSlot::callee].asanUnsafeJSValue(); }
</span><span class="cx">         CodeBlock* codeBlock() const { return this[CallFrameSlot::codeBlock].Register::codeBlock(); }
</span><ins>+        CodeBlock** addressOfCodeBlock() const { return bitwise_cast&lt;CodeBlock**&gt;(this + CallFrameSlot::codeBlock); }
</ins><span class="cx">         SUPPRESS_ASAN CodeBlock* unsafeCodeBlock() const { return this[CallFrameSlot::codeBlock].Register::asanUnsafeCodeBlock(); }
</span><span class="cx">         JSScope* scope(int scopeRegisterOffset) const
</span><span class="cx">         {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -944,11 +944,14 @@
</span><span class="cx">     if (JSObject* error = program-&gt;initializeGlobalProperties(vm, callFrame, scope))
</span><span class="cx">         return checkedReturn(callFrame-&gt;vm().throwException(callFrame, error));
</span><span class="cx"> 
</span><del>-    if (JSObject* error = program-&gt;prepareForExecution(callFrame, nullptr, scope, CodeForCall))
-        return checkedReturn(callFrame-&gt;vm().throwException(callFrame, error));
</del><ins>+    ProgramCodeBlock* codeBlock;
+    {
+        CodeBlock* tempCodeBlock;
+        if (JSObject* error = program-&gt;prepareForExecution&lt;ProgramExecutable&gt;(callFrame, nullptr, scope, CodeForCall, tempCodeBlock))
+            return checkedReturn(callFrame-&gt;vm().throwException(callFrame, error));
+        codeBlock = jsCast&lt;ProgramCodeBlock*&gt;(tempCodeBlock);
+    }
</ins><span class="cx"> 
</span><del>-    ProgramCodeBlock* codeBlock = program-&gt;codeBlock();
-
</del><span class="cx">     if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
</span><span class="cx">         return throwTerminatedExecutionException(callFrame);
</span><span class="cx"> 
</span><span class="lines">@@ -995,11 +998,10 @@
</span><span class="cx"> 
</span><span class="cx">     if (isJSCall) {
</span><span class="cx">         // Compile the callee:
</span><del>-        JSObject* compileError = callData.js.functionExecutable-&gt;prepareForExecution(callFrame, jsCast&lt;JSFunction*&gt;(function), scope, CodeForCall);
-        if (UNLIKELY(!!compileError)) {
</del><ins>+        JSObject* compileError = callData.js.functionExecutable-&gt;prepareForExecution&lt;FunctionExecutable&gt;(callFrame, jsCast&lt;JSFunction*&gt;(function), scope, CodeForCall, newCodeBlock);
+        if (UNLIKELY(!!compileError))
</ins><span class="cx">             return checkedReturn(callFrame-&gt;vm().throwException(callFrame, compileError));
</span><del>-        }
-        newCodeBlock = callData.js.functionExecutable-&gt;codeBlockForCall();
</del><ins>+
</ins><span class="cx">         ASSERT(!!newCodeBlock);
</span><span class="cx">         newCodeBlock-&gt;m_shouldAlwaysBeInlined = false;
</span><span class="cx">     } else
</span><span class="lines">@@ -1057,11 +1059,10 @@
</span><span class="cx"> 
</span><span class="cx">     if (isJSConstruct) {
</span><span class="cx">         // Compile the callee:
</span><del>-        JSObject* compileError = constructData.js.functionExecutable-&gt;prepareForExecution(callFrame, jsCast&lt;JSFunction*&gt;(constructor), scope, CodeForConstruct);
-        if (UNLIKELY(!!compileError)) {
</del><ins>+        JSObject* compileError = constructData.js.functionExecutable-&gt;prepareForExecution&lt;FunctionExecutable&gt;(callFrame, jsCast&lt;JSFunction*&gt;(constructor), scope, CodeForConstruct, newCodeBlock);
+        if (UNLIKELY(!!compileError))
</ins><span class="cx">             return checkedReturn(callFrame-&gt;vm().throwException(callFrame, compileError));
</span><del>-        }
-        newCodeBlock = constructData.js.functionExecutable-&gt;codeBlockForConstruct();
</del><ins>+
</ins><span class="cx">         ASSERT(!!newCodeBlock);
</span><span class="cx">         newCodeBlock-&gt;m_shouldAlwaysBeInlined = false;
</span><span class="cx">     } else
</span><span class="lines">@@ -1101,12 +1102,12 @@
</span><span class="cx">         return CallFrameClosure();
</span><span class="cx"> 
</span><span class="cx">     // Compile the callee:
</span><del>-    JSObject* error = functionExecutable-&gt;prepareForExecution(callFrame, function, scope, CodeForCall);
</del><ins>+    CodeBlock* newCodeBlock;
+    JSObject* error = functionExecutable-&gt;prepareForExecution&lt;FunctionExecutable&gt;(callFrame, function, scope, CodeForCall, newCodeBlock);
</ins><span class="cx">     if (error) {
</span><span class="cx">         callFrame-&gt;vm().throwException(callFrame, error);
</span><span class="cx">         return CallFrameClosure();
</span><span class="cx">     }
</span><del>-    CodeBlock* newCodeBlock = functionExecutable-&gt;codeBlockForCall();
</del><span class="cx">     newCodeBlock-&gt;m_shouldAlwaysBeInlined = false;
</span><span class="cx"> 
</span><span class="cx">     size_t argsCount = argumentCountIncludingThis;
</span><span class="lines">@@ -1176,10 +1177,14 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JSObject* compileError = eval-&gt;prepareForExecution(callFrame, nullptr, scope, CodeForCall);
-    if (UNLIKELY(!!compileError))
-        return checkedReturn(callFrame-&gt;vm().throwException(callFrame, compileError));
-    EvalCodeBlock* codeBlock = eval-&gt;codeBlock();
</del><ins>+    EvalCodeBlock* codeBlock;
+    {
+        CodeBlock* tempCodeBlock;
+        JSObject* compileError = eval-&gt;prepareForExecution&lt;EvalExecutable&gt;(callFrame, nullptr, scope, CodeForCall, tempCodeBlock);
+        if (UNLIKELY(!!compileError))
+            return checkedReturn(callFrame-&gt;vm().throwException(callFrame, compileError));
+        codeBlock = jsCast&lt;EvalCodeBlock*&gt;(tempCodeBlock);
+    }
</ins><span class="cx"> 
</span><span class="cx">     // We can't declare a &quot;var&quot;/&quot;function&quot; that overwrites a global &quot;let&quot;/&quot;const&quot;/&quot;class&quot; in a sloppy-mode eval.
</span><span class="cx">     if (variableObject-&gt;isGlobalObject() &amp;&amp; !eval-&gt;isStrictMode() &amp;&amp; (numVariables || numFunctions)) {
</span><span class="lines">@@ -1253,10 +1258,14 @@
</span><span class="cx">     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
</span><span class="cx">         return checkedReturn(throwStackOverflowError(callFrame));
</span><span class="cx"> 
</span><del>-    JSObject* compileError = executable-&gt;prepareForExecution(callFrame, nullptr, scope, CodeForCall);
-    if (UNLIKELY(!!compileError))
-        return checkedReturn(callFrame-&gt;vm().throwException(callFrame, compileError));
-    ModuleProgramCodeBlock* codeBlock = executable-&gt;codeBlock();
</del><ins>+    ModuleProgramCodeBlock* codeBlock;
+    {
+        CodeBlock* tempCodeBlock;
+        JSObject* compileError = executable-&gt;prepareForExecution&lt;ModuleProgramExecutable&gt;(callFrame, nullptr, scope, CodeForCall, tempCodeBlock);
+        if (UNLIKELY(!!compileError))
+            return checkedReturn(callFrame-&gt;vm().throwException(callFrame, compileError));
+        codeBlock = jsCast&lt;ModuleProgramCodeBlock*&gt;(tempCodeBlock);
+    }
</ins><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
</span><span class="cx">         return throwTerminatedExecutionException(callFrame);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -900,7 +900,8 @@
</span><span class="cx">                 reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, callee, scope, kind);
</del><ins>+        CodeBlock** codeBlockSlot = execCallee-&gt;addressOfCodeBlock();
+        JSObject* error = functionExecutable-&gt;prepareForExecution&lt;FunctionExecutable&gt;(execCallee, callee, scope, kind, *codeBlockSlot);
</ins><span class="cx">         if (error) {
</span><span class="cx">             exec-&gt;vm().throwException(exec, error);
</span><span class="cx">             return encodeResult(
</span><span class="lines">@@ -907,7 +908,7 @@
</span><span class="cx">                 vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
</span><span class="cx">                 reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</span><span class="cx">         }
</span><del>-        codeBlock = functionExecutable-&gt;codeBlockFor(kind);
</del><ins>+        codeBlock = *codeBlockSlot;
</ins><span class="cx">         ArityCheckMode arity;
</span><span class="cx">         if (execCallee-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo-&gt;isVarargs())
</span><span class="cx">             arity = MustCheckArity;
</span><span class="lines">@@ -954,7 +955,8 @@
</span><span class="cx">                     reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, function, scope, kind);
</del><ins>+            CodeBlock** codeBlockSlot = execCallee-&gt;addressOfCodeBlock();
+            JSObject* error = functionExecutable-&gt;prepareForExecution&lt;FunctionExecutable&gt;(execCallee, function, scope, kind, *codeBlockSlot);
</ins><span class="cx">             if (error) {
</span><span class="cx">                 exec-&gt;vm().throwException(exec, error);
</span><span class="cx">                 return encodeResult(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -1266,10 +1266,11 @@
</span><span class="cx">         if (!isCall(kind) &amp;&amp; functionExecutable-&gt;constructAbility() == ConstructAbility::CannotConstruct)
</span><span class="cx">             LLINT_CALL_THROW(exec, createNotAConstructorError(exec, callee));
</span><span class="cx"> 
</span><del>-        JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, callee, scope, kind);
</del><ins>+        CodeBlock** codeBlockSlot = execCallee-&gt;addressOfCodeBlock();
+        JSObject* error = functionExecutable-&gt;prepareForExecution&lt;FunctionExecutable&gt;(execCallee, callee, scope, kind, *codeBlockSlot);
</ins><span class="cx">         if (error)
</span><span class="cx">             LLINT_CALL_THROW(exec, error);
</span><del>-        codeBlock = functionExecutable-&gt;codeBlockFor(kind);
</del><ins>+        codeBlock = *codeBlockSlot;
</ins><span class="cx">         ASSERT(codeBlock);
</span><span class="cx">         ArityCheckMode arity;
</span><span class="cx">         if (execCallee-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Executable.cpp (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Executable.cpp        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Source/JavaScriptCore/runtime/Executable.cpp        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -177,7 +177,8 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(vm.heap.isDeferred());
</span><span class="cx">     
</span><del>-    CODEBLOCK_LOG_EVENT(genericCodeBlock, &quot;installCode&quot;, ());
</del><ins>+    if (genericCodeBlock)
+        CODEBLOCK_LOG_EVENT(genericCodeBlock, &quot;installCode&quot;, ());
</ins><span class="cx">     
</span><span class="cx">     CodeBlock* oldCodeBlock = nullptr;
</span><span class="cx">     
</span><span class="lines">@@ -399,10 +400,10 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSObject* ScriptExecutable::prepareForExecutionImpl(
</span><del>-    ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
</del><ins>+    ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*&amp; resultCodeBlock)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><del>-    DeferGC deferGC(vm.heap);
</del><ins>+    DeferGCForAWhile deferGC(vm.heap);
</ins><span class="cx"> 
</span><span class="cx">     if (vm.getAndClearFailNextNewCodeBlock())
</span><span class="cx">         return createError(exec-&gt;callerFrame(), ASCIILiteral(&quot;Forced Failure&quot;));
</span><span class="lines">@@ -409,6 +410,7 @@
</span><span class="cx"> 
</span><span class="cx">     JSObject* exception = 0;
</span><span class="cx">     CodeBlock* codeBlock = newCodeBlockFor(kind, function, scope, exception);
</span><ins>+    resultCodeBlock = codeBlock;
</ins><span class="cx">     if (!codeBlock) {
</span><span class="cx">         RELEASE_ASSERT(exception);
</span><span class="cx">         return exception;
</span><span class="lines">@@ -423,7 +425,7 @@
</span><span class="cx">         setupJIT(vm, codeBlock);
</span><span class="cx">     
</span><span class="cx">     installCode(*codeBlock-&gt;vm(), codeBlock, codeBlock-&gt;codeType(), codeBlock-&gt;specializationKind());
</span><del>-    return 0;
</del><ins>+    return nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo EvalExecutable::s_info = { &quot;EvalExecutable&quot;, &amp;ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(EvalExecutable) };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Executable.h (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Executable.h        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Source/JavaScriptCore/runtime/Executable.h        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -367,19 +367,21 @@
</span><span class="cx">     void installCode(VM&amp;, CodeBlock*, CodeType, CodeSpecializationKind);
</span><span class="cx">     CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*&amp; exception);
</span><span class="cx">     CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
</span><del>-    
-    JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
-    {
-        if (hasJITCodeFor(kind))
-            return 0;
-        return prepareForExecutionImpl(exec, function, scope, kind);
-    }
</del><span class="cx"> 
</span><ins>+    // This function has an interesting GC story. Callers of this function are asking us to create a CodeBlock
+    // that is not jettisoned before this function returns. Callers are essentially asking for a strong reference
+    // to the CodeBlock. Because the Executable may be allocating the CodeBlock, we require callers to pass in
+    // their CodeBlock*&amp; reference because it's safe for CodeBlock to be jettisoned if Executable is the only thing
+    // to point to it. This forces callers to have a CodeBlock* in a register or on the stack that will be marked
+    // by conservative GC if a GC happens after we create the CodeBlock.
+    template &lt;typename ExecutableType&gt;
+    JSObject* prepareForExecution(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&amp; resultCodeBlock);
+
</ins><span class="cx">     template &lt;typename Functor&gt; void forEachCodeBlock(Functor&amp;&amp;);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class ExecutableBase;
</span><del>-    JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind);
</del><ins>+    JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&amp;);
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     ScriptExecutable(Structure*, VM&amp;, const SourceCode&amp;, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, EvalContextType, Intrinsic);
</span><span class="lines">@@ -739,6 +741,25 @@
</span><span class="cx"> };
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+template &lt;typename ExecutableType&gt;
+JSObject* ScriptExecutable::prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*&amp; resultCodeBlock)
+{
+    if (hasJITCodeFor(kind)) {
+        if (std::is_same&lt;ExecutableType, EvalExecutable&gt;::value)
+            resultCodeBlock = jsCast&lt;CodeBlock*&gt;(jsCast&lt;EvalExecutable*&gt;(this)-&gt;codeBlock());
+        else if (std::is_same&lt;ExecutableType, ProgramExecutable&gt;::value)
+            resultCodeBlock = jsCast&lt;CodeBlock*&gt;(jsCast&lt;ProgramExecutable*&gt;(this)-&gt;codeBlock());
+        else if (std::is_same&lt;ExecutableType, ModuleProgramExecutable&gt;::value)
+            resultCodeBlock = jsCast&lt;CodeBlock*&gt;(jsCast&lt;ModuleProgramExecutable*&gt;(this)-&gt;codeBlock());
+        else if (std::is_same&lt;ExecutableType, FunctionExecutable&gt;::value)
+            resultCodeBlock = jsCast&lt;CodeBlock*&gt;(jsCast&lt;FunctionExecutable*&gt;(this)-&gt;codeBlockFor(kind));
+        else
+            RELEASE_ASSERT_NOT_REACHED();
+        return nullptr;
+    }
+    return prepareForExecutionImpl(exec, function, scope, kind, resultCodeBlock);
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // Executable_h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -322,6 +322,8 @@
</span><span class="cx">     v(unsigned, forceRAMSize, 0, Normal, nullptr) \
</span><span class="cx">     v(bool, recordGCPauseTimes, false, Normal, nullptr) \
</span><span class="cx">     v(bool, logHeapStatisticsAtExit, false, Normal, nullptr) \
</span><ins>+    v(bool, forceCodeBlockToJettisonDueToOldAge, false, Normal, &quot;If true, this means that anytime we can jettison a CodeBlock due to old age, we do.&quot;) \
+    v(bool, useEagerCodeBlockJettisonTiming, false, Normal, &quot;If true, the time slices for jettisoning a CodeBlock due to old age are shrunk significantly.&quot;) \
</ins><span class="cx">     \
</span><span class="cx">     v(bool, useTypeProfiler, false, Normal, nullptr) \
</span><span class="cx">     v(bool, useControlFlowProfiler, false, Normal, nullptr) \
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Tools/ChangeLog        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2016-08-04  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        Restore CodeBlock jettison code to jettison when a CodeBlock has been alive for a long time
+        https://bugs.webkit.org/show_bug.cgi?id=151241
+
+        Reviewed by Benjamin Poulain.
+
+        * Scripts/run-jsc-stress-tests:
+
</ins><span class="cx"> 2016-08-04  Dean Johnson  &lt;dean_johnson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         UI improvements to Flakiness Dashboard.
</span></span></pre></div>
<a id="trunkToolsScriptsrunjscstresstests"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/run-jsc-stress-tests (204161 => 204162)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/run-jsc-stress-tests        2016-08-05 02:59:13 UTC (rev 204161)
+++ trunk/Tools/Scripts/run-jsc-stress-tests        2016-08-05 06:46:55 UTC (rev 204162)
</span><span class="lines">@@ -419,7 +419,7 @@
</span><span class="cx"> 
</span><span class="cx"> # We force all tests to use a smaller (1.5M) stack so that stack overflow tests can run faster.
</span><span class="cx"> BASE_OPTIONS = [&quot;--useFTLJIT=false&quot;, &quot;--useFunctionDotArguments=true&quot;, &quot;--maxPerThreadStackUsage=1572864&quot;]
</span><del>-EAGER_OPTIONS = [&quot;--thresholdForJITAfterWarmUp=10&quot;, &quot;--thresholdForJITSoon=10&quot;, &quot;--thresholdForOptimizeAfterWarmUp=20&quot;, &quot;--thresholdForOptimizeAfterLongWarmUp=20&quot;, &quot;--thresholdForOptimizeSoon=20&quot;, &quot;--thresholdForFTLOptimizeAfterWarmUp=20&quot;, &quot;--thresholdForFTLOptimizeSoon=20&quot;, &quot;--maximumEvalCacheableSourceLength=150000&quot;]
</del><ins>+EAGER_OPTIONS = [&quot;--thresholdForJITAfterWarmUp=10&quot;, &quot;--thresholdForJITSoon=10&quot;, &quot;--thresholdForOptimizeAfterWarmUp=20&quot;, &quot;--thresholdForOptimizeAfterLongWarmUp=20&quot;, &quot;--thresholdForOptimizeSoon=20&quot;, &quot;--thresholdForFTLOptimizeAfterWarmUp=20&quot;, &quot;--thresholdForFTLOptimizeSoon=20&quot;, &quot;--maximumEvalCacheableSourceLength=150000&quot;, &quot;--useEagerCodeBlockJettisonTiming=true&quot;]
</ins><span class="cx"> NO_CJIT_OPTIONS = [&quot;--useConcurrentJIT=false&quot;, &quot;--thresholdForJITAfterWarmUp=100&quot;]
</span><span class="cx"> FTL_OPTIONS = [&quot;--useFTLJIT=true&quot;]
</span><span class="cx"> 
</span><span class="lines">@@ -876,7 +876,7 @@
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runDFGMaximalFlushPhase
</span><del>-    run(&quot;dfg-maximal-flush-validate-no-cjit&quot;, &quot;--validateGraph=true&quot;, &quot;--useMaximalFlushInsertionPhase=true&quot;, *NO_CJIT_OPTIONS)
</del><ins>+    run(&quot;dfg-maximal-flush-validate-no-cjit&quot;, &quot;--forceCodeBlockToJettisonDueToOldAge=true&quot;, &quot;--validateGraph=true&quot;, &quot;--useMaximalFlushInsertionPhase=true&quot;, *NO_CJIT_OPTIONS)
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runShadowChicken
</span></span></pre>
</div>
</div>

</body>
</html>