<!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>[167591] 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/167591">167591</a></dd>
<dt>Author</dt> <dd>mhahnenberg@apple.com</dd>
<dt>Date</dt> <dd>2014-04-21 08:11:33 -0700 (Mon, 21 Apr 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Inline allocate Arguments objects in the DFG
https://bugs.webkit.org/show_bug.cgi?id=131897
Reviewed by Geoffrey Garen.
Many libraries/frameworks depend on the arguments object for overloaded API entry points.
This is the first step to making Arguments fast(er). We'll duplicate the logic in Arguments::create
for now and take the slow path for complicated cases like slow arguments, tearing off for strict mode, etc.
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::emitAllocateArguments):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::emitAllocateDestructibleObject):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* runtime/Arguments.h:
(JSC::Arguments::offsetOfActivation):
(JSC::Arguments::offsetOfOverrodeLength):
(JSC::Arguments::offsetOfIsStrictMode):
(JSC::Arguments::offsetOfRegisterArray):
(JSC::Arguments::offsetOfCallee):
(JSC::Arguments::allocationSize):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArgumentsh">trunk/Source/JavaScriptCore/runtime/Arguments.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (167590 => 167591)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-04-21 15:11:33 UTC (rev 167591)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2014-04-21 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Inline allocate Arguments objects in the DFG
+ https://bugs.webkit.org/show_bug.cgi?id=131897
+
+ Reviewed by Geoffrey Garen.
+
+ Many libraries/frameworks depend on the arguments object for overloaded API entry points.
+ This is the first step to making Arguments fast(er). We'll duplicate the logic in Arguments::create
+ for now and take the slow path for complicated cases like slow arguments, tearing off for strict mode, etc.
+
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::emitAllocateArguments):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::emitAllocateDestructibleObject):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * runtime/Arguments.h:
+ (JSC::Arguments::offsetOfActivation):
+ (JSC::Arguments::offsetOfOverrodeLength):
+ (JSC::Arguments::offsetOfIsStrictMode):
+ (JSC::Arguments::offsetOfRegisterArray):
+ (JSC::Arguments::offsetOfCallee):
+ (JSC::Arguments::allocationSize):
+
</ins><span class="cx"> 2014-04-20 Andreas Kling <akling@apple.com>
</span><span class="cx">
</span><span class="cx"> Speed up jsStringWithCache() through WeakGCMap inlining.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (167590 => 167591)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-04-21 15:11:33 UTC (rev 167591)
</span><span class="lines">@@ -106,6 +106,29 @@
</span><span class="cx"> structure, numElements)));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void SpeculativeJIT::emitAllocateArguments(GPRReg resultGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
+{
+ Structure* structure = m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)->argumentsStructure();
+ emitAllocateDestructibleObject<Arguments>(resultGPR, structure, scratchGPR1, scratchGPR2, slowPath);
+
+ m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfActivation()));
+
+ m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), scratchGPR1);
+ m_jit.sub32(TrustedImm32(1), scratchGPR1);
+ m_jit.store32(scratchGPR1, MacroAssembler::Address(resultGPR, Arguments::offsetOfNumArguments()));
+
+ m_jit.store32(TrustedImm32(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfOverrodeLength()));
+ m_jit.store8(TrustedImm32(m_jit.isStrictModeFor(m_currentNode->origin.semantic)),
+ MacroAssembler::Address(resultGPR, Arguments::offsetOfIsStrictMode()));
+
+ m_jit.storePtr(GPRInfo::callFrameRegister, MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisters()));
+ m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisterArray()));
+ m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfSlowArgumentData()));
+
+ m_jit.loadPtr(JITCompiler::addressFor(JSStack::Callee), scratchGPR1);
+ m_jit.storePtr(scratchGPR1, MacroAssembler::Address(resultGPR, Arguments::offsetOfCallee()));
+}
+
</ins><span class="cx"> void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
</span><span class="cx"> {
</span><span class="cx"> if (!m_compileOkay)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (167590 => 167591)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-04-21 15:11:33 UTC (rev 167591)
</span><span class="lines">@@ -2178,7 +2178,7 @@
</span><span class="cx"> m_jit.storePtr(storage, MacroAssembler::Address(resultGPR, JSObject::butterflyOffset()));
</span><span class="cx"> }
</span><span class="cx">
</span><del>- // Convenience allocator for a buit-in object.
</del><ins>+ // Convenience allocator for a built-in object.
</ins><span class="cx"> template <typename ClassType, typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr.
</span><span class="cx"> void emitAllocateJSObject(GPRReg resultGPR, StructureType structure, StorageType storage,
</span><span class="cx"> GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
</span><span class="lines">@@ -2195,7 +2195,16 @@
</span><span class="cx"> emitAllocateJSObject(resultGPR, scratchGPR1, structure, storage, scratchGPR2, slowPath);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ template <typename T>
+ void emitAllocateDestructibleObject(GPRReg resultGPR, Structure* structure,
+ GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
+ {
+ emitAllocateJSObject<T>(resultGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratchGPR1, scratchGPR2, slowPath);
+ m_jit.storePtr(TrustedImmPtr(structure->classInfo()), MacroAssembler::Address(resultGPR, JSDestructibleObject::classInfoOffset()));
+ }
+
</ins><span class="cx"> void emitAllocateJSArray(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements);
</span><ins>+ void emitAllocateArguments(GPRReg resultGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath);
</ins><span class="cx">
</span><span class="cx"> // Add a speculation check.
</span><span class="cx"> void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (167590 => 167591)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-04-21 15:11:33 UTC (rev 167591)
</span><span class="lines">@@ -4167,26 +4167,47 @@
</span><span class="cx">
</span><span class="cx"> case CreateArguments: {
</span><span class="cx"> JSValueOperand value(this, node->child1());
</span><ins>+ GPRTemporary scratch1(this);
+ GPRTemporary scratch2(this);
</ins><span class="cx"> GPRTemporary result(this, Reuse, value, PayloadWord);
</span><span class="cx">
</span><span class="cx"> GPRReg valueTagGPR = value.tagGPR();
</span><span class="cx"> GPRReg valuePayloadGPR = value.payloadGPR();
</span><ins>+ GPRReg scratch1GPR = scratch1.gpr();
+ GPRReg scratch2GPR = scratch2.gpr();
</ins><span class="cx"> GPRReg resultGPR = result.gpr();
</span><span class="cx">
</span><span class="cx"> m_jit.move(valuePayloadGPR, resultGPR);
</span><span class="cx">
</span><del>- JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
-
</del><span class="cx"> if (node->origin.semantic.inlineCallFrame) {
</span><ins>+ JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
</ins><span class="cx"> addSlowPathGenerator(
</span><span class="cx"> slowPathCall(
</span><span class="cx"> notCreated, this, operationCreateInlinedArguments, resultGPR,
</span><span class="cx"> node->origin.semantic.inlineCallFrame));
</span><del>- } else {
</del><ins>+ cellResult(resultGPR, node);
+ break;
+ }
+
+ FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_jit.graph().executableFor(node->origin.semantic));
+ if (m_jit.codeBlock()->hasSlowArguments()
+ || executable->isStrictMode()
+ || !executable->parameterCount()) {
+ JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
</ins><span class="cx"> addSlowPathGenerator(
</span><span class="cx"> slowPathCall(notCreated, this, operationCreateArguments, resultGPR));
</span><ins>+ cellResult(resultGPR, node);
+ break;
</ins><span class="cx"> }
</span><del>-
</del><ins>+
+ JITCompiler::Jump alreadyCreated = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
+
+ MacroAssembler::JumpList slowPaths;
+ emitAllocateArguments(resultGPR, scratch1GPR, scratch2GPR, slowPaths);
+ addSlowPathGenerator(
+ slowPathCall(slowPaths, this, operationCreateArguments, resultGPR));
+
+ alreadyCreated.link(&m_jit);
</ins><span class="cx"> cellResult(resultGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (167590 => 167591)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-04-21 15:11:33 UTC (rev 167591)
</span><span class="lines">@@ -4224,25 +4224,46 @@
</span><span class="cx">
</span><span class="cx"> case CreateArguments: {
</span><span class="cx"> JSValueOperand value(this, node->child1());
</span><ins>+ GPRTemporary scratch1(this);
+ GPRTemporary scratch2(this);
</ins><span class="cx"> GPRTemporary result(this, Reuse, value);
</span><span class="cx">
</span><span class="cx"> GPRReg valueGPR = value.gpr();
</span><ins>+ GPRReg scratchGPR1 = scratch1.gpr();
+ GPRReg scratchGPR2 = scratch2.gpr();
</ins><span class="cx"> GPRReg resultGPR = result.gpr();
</span><span class="cx">
</span><span class="cx"> m_jit.move(valueGPR, resultGPR);
</span><span class="cx">
</span><del>- JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR);
-
</del><span class="cx"> if (node->origin.semantic.inlineCallFrame) {
</span><ins>+ JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR);
</ins><span class="cx"> addSlowPathGenerator(
</span><span class="cx"> slowPathCall(
</span><span class="cx"> notCreated, this, operationCreateInlinedArguments, resultGPR,
</span><span class="cx"> node->origin.semantic.inlineCallFrame));
</span><del>- } else {
</del><ins>+ cellResult(resultGPR, node);
+ break;
+ }
+
+ FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_jit.graph().executableFor(node->origin.semantic));
+ if (m_jit.codeBlock()->hasSlowArguments()
+ || executable->isStrictMode()
+ || !executable->parameterCount()) {
+ JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR);
</ins><span class="cx"> addSlowPathGenerator(
</span><span class="cx"> slowPathCall(notCreated, this, operationCreateArguments, resultGPR));
</span><ins>+ cellResult(resultGPR, node);
+ break;
</ins><span class="cx"> }
</span><del>-
</del><ins>+
+ JITCompiler::Jump alreadyCreated = m_jit.branchTest64(JITCompiler::NonZero, resultGPR);
+
+ MacroAssembler::JumpList slowPaths;
+ emitAllocateArguments(resultGPR, scratchGPR1, scratchGPR2, slowPaths);
+ addSlowPathGenerator(
+ slowPathCall(slowPaths, this, operationCreateArguments, resultGPR));
+
+ alreadyCreated.link(&m_jit);
</ins><span class="cx"> cellResult(resultGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.h (167590 => 167591)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.h        2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.h        2014-04-21 15:11:33 UTC (rev 167591)
</span><span class="lines">@@ -89,10 +89,20 @@
</span><span class="cx"> return Structure::create(vm, globalObject, prototype, TypeInfo(ArgumentsType, StructureFlags), info());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ static ptrdiff_t offsetOfActivation() { return OBJECT_OFFSETOF(Arguments, m_activation); }
</ins><span class="cx"> static ptrdiff_t offsetOfNumArguments() { return OBJECT_OFFSETOF(Arguments, m_numArguments); }
</span><ins>+ static ptrdiff_t offsetOfOverrodeLength() { return OBJECT_OFFSETOF(Arguments, m_overrodeLength); }
+ static ptrdiff_t offsetOfIsStrictMode() { return OBJECT_OFFSETOF(Arguments, m_isStrictMode); }
</ins><span class="cx"> static ptrdiff_t offsetOfRegisters() { return OBJECT_OFFSETOF(Arguments, m_registers); }
</span><ins>+ static ptrdiff_t offsetOfRegisterArray() { return OBJECT_OFFSETOF(Arguments, m_registerArray); }
</ins><span class="cx"> static ptrdiff_t offsetOfSlowArgumentData() { return OBJECT_OFFSETOF(Arguments, m_slowArgumentData); }
</span><del>- static ptrdiff_t offsetOfOverrodeLength() { return OBJECT_OFFSETOF(Arguments, m_overrodeLength); }
</del><ins>+ static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(Arguments, m_callee); }
+
+ static size_t allocationSize(size_t inlineCapacity)
+ {
+ ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
+ return sizeof(Arguments);
+ }
</ins><span class="cx">
</span><span class="cx"> protected:
</span><span class="cx"> static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
</span></span></pre>
</div>
</div>
</body>
</html>