<!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 <sbarati@apple.com>
+
+ 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 <utatane.tea@gmail.com>
</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<std::chrono::milliseconds>(std::chrono::seconds(5));
+ case JITCode::BaselineJIT:
+ // Effectively 10 additional seconds, since BaselineJIT and
+ // InterpreterThunk share a CodeBlock.
+ return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds(5 + 10));
+ case JITCode::DFGJIT:
+ return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds(20));
+ case JITCode::FTLJIT:
+ return std::chrono::duration_cast<std::chrono::milliseconds>(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() < 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<CodeBlock**>(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->initializeGlobalProperties(vm, callFrame, scope))
</span><span class="cx"> return checkedReturn(callFrame->vm().throwException(callFrame, error));
</span><span class="cx">
</span><del>- if (JSObject* error = program->prepareForExecution(callFrame, nullptr, scope, CodeForCall))
- return checkedReturn(callFrame->vm().throwException(callFrame, error));
</del><ins>+ ProgramCodeBlock* codeBlock;
+ {
+ CodeBlock* tempCodeBlock;
+ if (JSObject* error = program->prepareForExecution<ProgramExecutable>(callFrame, nullptr, scope, CodeForCall, tempCodeBlock))
+ return checkedReturn(callFrame->vm().throwException(callFrame, error));
+ codeBlock = jsCast<ProgramCodeBlock*>(tempCodeBlock);
+ }
</ins><span class="cx">
</span><del>- ProgramCodeBlock* codeBlock = program->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->prepareForExecution(callFrame, jsCast<JSFunction*>(function), scope, CodeForCall);
- if (UNLIKELY(!!compileError)) {
</del><ins>+ JSObject* compileError = callData.js.functionExecutable->prepareForExecution<FunctionExecutable>(callFrame, jsCast<JSFunction*>(function), scope, CodeForCall, newCodeBlock);
+ if (UNLIKELY(!!compileError))
</ins><span class="cx"> return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
</span><del>- }
- newCodeBlock = callData.js.functionExecutable->codeBlockForCall();
</del><ins>+
</ins><span class="cx"> ASSERT(!!newCodeBlock);
</span><span class="cx"> newCodeBlock->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->prepareForExecution(callFrame, jsCast<JSFunction*>(constructor), scope, CodeForConstruct);
- if (UNLIKELY(!!compileError)) {
</del><ins>+ JSObject* compileError = constructData.js.functionExecutable->prepareForExecution<FunctionExecutable>(callFrame, jsCast<JSFunction*>(constructor), scope, CodeForConstruct, newCodeBlock);
+ if (UNLIKELY(!!compileError))
</ins><span class="cx"> return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
</span><del>- }
- newCodeBlock = constructData.js.functionExecutable->codeBlockForConstruct();
</del><ins>+
</ins><span class="cx"> ASSERT(!!newCodeBlock);
</span><span class="cx"> newCodeBlock->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->prepareForExecution(callFrame, function, scope, CodeForCall);
</del><ins>+ CodeBlock* newCodeBlock;
+ JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(callFrame, function, scope, CodeForCall, newCodeBlock);
</ins><span class="cx"> if (error) {
</span><span class="cx"> callFrame->vm().throwException(callFrame, error);
</span><span class="cx"> return CallFrameClosure();
</span><span class="cx"> }
</span><del>- CodeBlock* newCodeBlock = functionExecutable->codeBlockForCall();
</del><span class="cx"> newCodeBlock->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->prepareForExecution(callFrame, nullptr, scope, CodeForCall);
- if (UNLIKELY(!!compileError))
- return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
- EvalCodeBlock* codeBlock = eval->codeBlock();
</del><ins>+ EvalCodeBlock* codeBlock;
+ {
+ CodeBlock* tempCodeBlock;
+ JSObject* compileError = eval->prepareForExecution<EvalExecutable>(callFrame, nullptr, scope, CodeForCall, tempCodeBlock);
+ if (UNLIKELY(!!compileError))
+ return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
+ codeBlock = jsCast<EvalCodeBlock*>(tempCodeBlock);
+ }
</ins><span class="cx">
</span><span class="cx"> // We can't declare a "var"/"function" that overwrites a global "let"/"const"/"class" in a sloppy-mode eval.
</span><span class="cx"> if (variableObject->isGlobalObject() && !eval->isStrictMode() && (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->prepareForExecution(callFrame, nullptr, scope, CodeForCall);
- if (UNLIKELY(!!compileError))
- return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
- ModuleProgramCodeBlock* codeBlock = executable->codeBlock();
</del><ins>+ ModuleProgramCodeBlock* codeBlock;
+ {
+ CodeBlock* tempCodeBlock;
+ JSObject* compileError = executable->prepareForExecution<ModuleProgramExecutable>(callFrame, nullptr, scope, CodeForCall, tempCodeBlock);
+ if (UNLIKELY(!!compileError))
+ return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
+ codeBlock = jsCast<ModuleProgramCodeBlock*>(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<void*>(KeepTheFrame));
</span><span class="cx"> }
</span><span class="cx">
</span><del>- JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
</del><ins>+ CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
+ JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(execCallee, callee, scope, kind, *codeBlockSlot);
</ins><span class="cx"> if (error) {
</span><span class="cx"> exec->vm().throwException(exec, error);
</span><span class="cx"> return encodeResult(
</span><span class="lines">@@ -907,7 +908,7 @@
</span><span class="cx"> vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
</span><span class="cx"> reinterpret_cast<void*>(KeepTheFrame));
</span><span class="cx"> }
</span><del>- codeBlock = functionExecutable->codeBlockFor(kind);
</del><ins>+ codeBlock = *codeBlockSlot;
</ins><span class="cx"> ArityCheckMode arity;
</span><span class="cx"> if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->isVarargs())
</span><span class="cx"> arity = MustCheckArity;
</span><span class="lines">@@ -954,7 +955,8 @@
</span><span class="cx"> reinterpret_cast<void*>(KeepTheFrame));
</span><span class="cx"> }
</span><span class="cx">
</span><del>- JSObject* error = functionExecutable->prepareForExecution(execCallee, function, scope, kind);
</del><ins>+ CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
+ JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(execCallee, function, scope, kind, *codeBlockSlot);
</ins><span class="cx"> if (error) {
</span><span class="cx"> exec->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) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct)
</span><span class="cx"> LLINT_CALL_THROW(exec, createNotAConstructorError(exec, callee));
</span><span class="cx">
</span><del>- JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
</del><ins>+ CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
+ JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(execCallee, callee, scope, kind, *codeBlockSlot);
</ins><span class="cx"> if (error)
</span><span class="cx"> LLINT_CALL_THROW(exec, error);
</span><del>- codeBlock = functionExecutable->codeBlockFor(kind);
</del><ins>+ codeBlock = *codeBlockSlot;
</ins><span class="cx"> ASSERT(codeBlock);
</span><span class="cx"> ArityCheckMode arity;
</span><span class="cx"> if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->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, "installCode", ());
</del><ins>+ if (genericCodeBlock)
+ CODEBLOCK_LOG_EVENT(genericCodeBlock, "installCode", ());
</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*& resultCodeBlock)
</ins><span class="cx"> {
</span><span class="cx"> VM& vm = exec->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->callerFrame(), ASCIILiteral("Forced Failure"));
</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->vm(), codeBlock, codeBlock->codeType(), codeBlock->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 = { "EvalExecutable", &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&, CodeBlock*, CodeType, CodeSpecializationKind);
</span><span class="cx"> CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& 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*& 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 <typename ExecutableType>
+ JSObject* prepareForExecution(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*& resultCodeBlock);
+
</ins><span class="cx"> template <typename Functor> void forEachCodeBlock(Functor&&);
</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*&);
</ins><span class="cx">
</span><span class="cx"> protected:
</span><span class="cx"> ScriptExecutable(Structure*, VM&, const SourceCode&, 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 <typename ExecutableType>
+JSObject* ScriptExecutable::prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*& resultCodeBlock)
+{
+ if (hasJITCodeFor(kind)) {
+ if (std::is_same<ExecutableType, EvalExecutable>::value)
+ resultCodeBlock = jsCast<CodeBlock*>(jsCast<EvalExecutable*>(this)->codeBlock());
+ else if (std::is_same<ExecutableType, ProgramExecutable>::value)
+ resultCodeBlock = jsCast<CodeBlock*>(jsCast<ProgramExecutable*>(this)->codeBlock());
+ else if (std::is_same<ExecutableType, ModuleProgramExecutable>::value)
+ resultCodeBlock = jsCast<CodeBlock*>(jsCast<ModuleProgramExecutable*>(this)->codeBlock());
+ else if (std::is_same<ExecutableType, FunctionExecutable>::value)
+ resultCodeBlock = jsCast<CodeBlock*>(jsCast<FunctionExecutable*>(this)->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, "If true, this means that anytime we can jettison a CodeBlock due to old age, we do.") \
+ v(bool, useEagerCodeBlockJettisonTiming, false, Normal, "If true, the time slices for jettisoning a CodeBlock due to old age are shrunk significantly.") \
</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 <sbarati@apple.com>
+
+ 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 <dean_johnson@apple.com>
</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 = ["--useFTLJIT=false", "--useFunctionDotArguments=true", "--maxPerThreadStackUsage=1572864"]
</span><del>-EAGER_OPTIONS = ["--thresholdForJITAfterWarmUp=10", "--thresholdForJITSoon=10", "--thresholdForOptimizeAfterWarmUp=20", "--thresholdForOptimizeAfterLongWarmUp=20", "--thresholdForOptimizeSoon=20", "--thresholdForFTLOptimizeAfterWarmUp=20", "--thresholdForFTLOptimizeSoon=20", "--maximumEvalCacheableSourceLength=150000"]
</del><ins>+EAGER_OPTIONS = ["--thresholdForJITAfterWarmUp=10", "--thresholdForJITSoon=10", "--thresholdForOptimizeAfterWarmUp=20", "--thresholdForOptimizeAfterLongWarmUp=20", "--thresholdForOptimizeSoon=20", "--thresholdForFTLOptimizeAfterWarmUp=20", "--thresholdForFTLOptimizeSoon=20", "--maximumEvalCacheableSourceLength=150000", "--useEagerCodeBlockJettisonTiming=true"]
</ins><span class="cx"> NO_CJIT_OPTIONS = ["--useConcurrentJIT=false", "--thresholdForJITAfterWarmUp=100"]
</span><span class="cx"> FTL_OPTIONS = ["--useFTLJIT=true"]
</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("dfg-maximal-flush-validate-no-cjit", "--validateGraph=true", "--useMaximalFlushInsertionPhase=true", *NO_CJIT_OPTIONS)
</del><ins>+ run("dfg-maximal-flush-validate-no-cjit", "--forceCodeBlockToJettisonDueToOldAge=true", "--validateGraph=true", "--useMaximalFlushInsertionPhase=true", *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>