<!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>[174795] 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/174795">174795</a></dd>
<dt>Author</dt> <dd>oliver@apple.com</dd>
<dt>Date</dt> <dd>2014-10-16 15:02:16 -0700 (Thu, 16 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Use a single allocation for the Arguments object
https://bugs.webkit.org/show_bug.cgi?id=137751

Reviewed by Filip Pizlo.

This patch removes the secondary allocation for parameters in the Arguments
object.  This is faily simple, but we needed to make it possible for the JIT
to allocate a variable GC object.  To do this i've added a new
emitAllocateVariableSizedJSObject function to the JIT that does the work to
find the correct heap for a variable sized allocation and then bump that
allocator.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::emitAllocateArguments):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::emitAllocateVariableSizedJSObject):
* heap/CopyToken.h:
* heap/Heap.h:
(JSC::Heap::subspaceForObjectWithoutDestructor):
(JSC::Heap::subspaceForObjectNormalDestructor):
(JSC::Heap::subspaceForObjectsWithImmortalStructure):
* heap/MarkedSpace.h:
(JSC::MarkedSpace::subspaceForObjectsWithNormalDestructor):
(JSC::MarkedSpace::subspaceForObjectsWithImmortalStructure):
(JSC::MarkedSpace::subspaceForObjectsWithoutDestructor):
* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::Frame::createArguments):
* runtime/Arguments.cpp:
(JSC::Arguments::visitChildren):
(JSC::Arguments::copyBackingStore):
(JSC::Arguments::tearOff):
(JSC::Arguments::allocateRegisterArray): Deleted.
* runtime/Arguments.h:
(JSC::Arguments::create):
(JSC::Arguments::isTornOff):
(JSC::Arguments::offsetOfRegisterArray):
(JSC::Arguments::registerArraySizeInBytes):
(JSC::Arguments::registerArray):
(JSC::Arguments::allocationSize): Deleted.</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="#trunkSourceJavaScriptCoreheapCopyTokenh">trunk/Source/JavaScriptCore/heap/CopyToken.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedSpaceh">trunk/Source/JavaScriptCore/heap/MarkedSpace.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterStackVisitorcpp">trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArgumentscpp">trunk/Source/JavaScriptCore/runtime/Arguments.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 (174794 => 174795)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-10-16 21:58:06 UTC (rev 174794)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-10-16 22:02:16 UTC (rev 174795)
</span><span class="lines">@@ -1,3 +1,45 @@
</span><ins>+2014-10-15  Oliver Hunt  &lt;oliver@apple.com&gt;
+
+        Use a single allocation for the Arguments object
+        https://bugs.webkit.org/show_bug.cgi?id=137751
+
+        Reviewed by Filip Pizlo.
+
+        This patch removes the secondary allocation for parameters in the Arguments
+        object.  This is faily simple, but we needed to make it possible for the JIT
+        to allocate a variable GC object.  To do this i've added a new 
+        emitAllocateVariableSizedJSObject function to the JIT that does the work to
+        find the correct heap for a variable sized allocation and then bump that
+        allocator.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::emitAllocateArguments):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::emitAllocateVariableSizedJSObject):
+        * heap/CopyToken.h:
+        * heap/Heap.h:
+        (JSC::Heap::subspaceForObjectWithoutDestructor):
+        (JSC::Heap::subspaceForObjectNormalDestructor):
+        (JSC::Heap::subspaceForObjectsWithImmortalStructure):
+        * heap/MarkedSpace.h:
+        (JSC::MarkedSpace::subspaceForObjectsWithNormalDestructor):
+        (JSC::MarkedSpace::subspaceForObjectsWithImmortalStructure):
+        (JSC::MarkedSpace::subspaceForObjectsWithoutDestructor):
+        * interpreter/StackVisitor.cpp:
+        (JSC::StackVisitor::Frame::createArguments):
+        * runtime/Arguments.cpp:
+        (JSC::Arguments::visitChildren):
+        (JSC::Arguments::copyBackingStore):
+        (JSC::Arguments::tearOff):
+        (JSC::Arguments::allocateRegisterArray): Deleted.
+        * runtime/Arguments.h:
+        (JSC::Arguments::create):
+        (JSC::Arguments::isTornOff):
+        (JSC::Arguments::offsetOfRegisterArray):
+        (JSC::Arguments::registerArraySizeInBytes):
+        (JSC::Arguments::registerArray):
+        (JSC::Arguments::allocationSize): Deleted.
+
</ins><span class="cx"> 2014-10-15  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Apparently we've had a hole in arguments capture all along
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (174794 => 174795)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-10-16 21:58:06 UTC (rev 174794)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-10-16 22:02:16 UTC (rev 174795)
</span><span class="lines">@@ -111,8 +111,12 @@
</span><span class="cx"> void SpeculativeJIT::emitAllocateArguments(GPRReg resultGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList&amp; slowPath)
</span><span class="cx"> {
</span><span class="cx">     Structure* structure = m_jit.graph().globalObjectFor(m_currentNode-&gt;origin.semantic)-&gt;argumentsStructure();
</span><del>-    emitAllocateDestructibleObject&lt;Arguments&gt;(resultGPR, structure, scratchGPR1, scratchGPR2, slowPath);
</del><span class="cx"> 
</span><ins>+    m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), scratchGPR1);
+    m_jit.mul32(TrustedImm32(sizeof(JSValue)), scratchGPR1, scratchGPR1);
+    m_jit.add32(TrustedImm32(Arguments::offsetOfInlineRegisterArray()), scratchGPR1);
+    emitAllocateVariableSizedJSObject&lt;Arguments&gt;(resultGPR, structure, scratchGPR1, scratchGPR1, scratchGPR2, slowPath);
+
</ins><span class="cx">     m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfActivation()));
</span><span class="cx"> 
</span><span class="cx">     m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), scratchGPR1);
</span><span class="lines">@@ -124,11 +128,11 @@
</span><span class="cx">         m_jit.store8(TrustedImm32(1), MacroAssembler::Address(resultGPR, Arguments::offsetOfIsStrictMode()));
</span><span class="cx"> 
</span><span class="cx">     m_jit.storePtr(GPRInfo::callFrameRegister, MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisters()));
</span><del>-    m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisterArray()));
</del><span class="cx">     m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfSlowArgumentData()));
</span><span class="cx"> 
</span><span class="cx">     m_jit.loadPtr(JITCompiler::addressFor(JSStack::Callee), scratchGPR1);
</span><span class="cx">     m_jit.storePtr(scratchGPR1, MacroAssembler::Address(resultGPR, Arguments::offsetOfCallee()));
</span><ins>+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (174794 => 174795)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-10-16 21:58:06 UTC (rev 174794)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-10-16 22:02:16 UTC (rev 174795)
</span><span class="lines">@@ -2252,6 +2252,38 @@
</span><span class="cx">         emitAllocateJSObject(resultGPR, scratchGPR1, structure, storage, scratchGPR2, slowPath);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    template &lt;typename ClassType, typename StructureType&gt; // StructureType and StorageType can be GPR or ImmPtr.
+    void emitAllocateVariableSizedJSObject(GPRReg resultGPR, StructureType structure, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList&amp; slowPath)
+    {
+        static_assert(!(MarkedSpace::preciseStep &amp; (MarkedSpace::preciseStep - 1)), &quot;MarkedSpace::preciseStep must be a power of two.&quot;);
+        static_assert(!(MarkedSpace::impreciseStep &amp; (MarkedSpace::impreciseStep - 1)), &quot;MarkedSpace::impreciseStep must be a power of two.&quot;);
+
+        MarkedSpace::Subspace* subspace;
+        if (ClassType::needsDestruction &amp;&amp; ClassType::hasImmortalStructure)
+            subspace = &amp;m_jit.vm()-&gt;heap.subspaceForObjectsWithImmortalStructure();
+        else if (ClassType::needsDestruction)
+            subspace = &amp;m_jit.vm()-&gt;heap.subspaceForObjectNormalDestructor();
+        else
+            subspace = &amp;m_jit.vm()-&gt;heap.subspaceForObjectWithoutDestructor();
+        m_jit.add32(TrustedImm32(MarkedSpace::preciseStep - 1), allocationSize);
+        MacroAssembler::Jump notSmall = m_jit.branch32(MacroAssembler::AboveOrEqual, allocationSize, TrustedImm32(MarkedSpace::preciseCutoff));
+        m_jit.rshift32(allocationSize, TrustedImm32(getLSBSet(MarkedSpace::preciseStep)), scratchGPR1);
+        m_jit.mul32(TrustedImm32(sizeof(MarkedAllocator)), scratchGPR1, scratchGPR1);
+        m_jit.addPtr(MacroAssembler::TrustedImmPtr(&amp;subspace-&gt;preciseAllocators[0]), scratchGPR1);
+
+        MacroAssembler::Jump selectedSmallSpace = m_jit.jump();
+        notSmall.link(&amp;m_jit);
+        slowPath.append(m_jit.branch32(MacroAssembler::AboveOrEqual, allocationSize, TrustedImm32(MarkedSpace::impreciseCutoff)));
+        m_jit.rshift32(allocationSize, TrustedImm32(getLSBSet(MarkedSpace::impreciseStep)), scratchGPR1);
+        m_jit.mul32(TrustedImm32(sizeof(MarkedAllocator)), scratchGPR1, scratchGPR1);
+        m_jit.addPtr(MacroAssembler::TrustedImmPtr(&amp;subspace-&gt;impreciseAllocators[0]), scratchGPR1);
+
+        selectedSmallSpace.link(&amp;m_jit);
+
+        emitAllocateJSObject(resultGPR, scratchGPR1, TrustedImmPtr(structure), TrustedImmPtr(0), scratchGPR2, slowPath);
+        m_jit.storePtr(TrustedImmPtr(structure-&gt;classInfo()), MacroAssembler::Address(resultGPR, JSDestructibleObject::classInfoOffset()));
+    }
+
</ins><span class="cx">     template &lt;typename T&gt;
</span><span class="cx">     void emitAllocateDestructibleObject(GPRReg resultGPR, Structure* structure, 
</span><span class="cx">         GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList&amp; slowPath)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCopyTokenh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CopyToken.h (174794 => 174795)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CopyToken.h        2014-10-16 21:58:06 UTC (rev 174794)
+++ trunk/Source/JavaScriptCore/heap/CopyToken.h        2014-10-16 22:02:16 UTC (rev 174795)
</span><span class="lines">@@ -32,7 +32,6 @@
</span><span class="cx">     ButterflyCopyToken,
</span><span class="cx">     TypedArrayVectorCopyToken,
</span><span class="cx">     MapBackingStoreCopyToken,
</span><del>-    ArgumentsRegisterArrayCopyToken,
</del><span class="cx">     ArgumentsSlowArgumentDataCopyToken
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (174794 => 174795)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2014-10-16 21:58:06 UTC (rev 174794)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2014-10-16 22:02:16 UTC (rev 174795)
</span><span class="lines">@@ -135,7 +135,9 @@
</span><span class="cx">     HeapOperation operationInProgress() { return m_operationInProgress; }
</span><span class="cx">     // true if an allocation or collection is in progress
</span><span class="cx">     bool isBusy();
</span><del>-    
</del><ins>+    MarkedSpace::Subspace&amp; subspaceForObjectWithoutDestructor() { return m_objectSpace.subspaceForObjectsWithoutDestructor(); }
+    MarkedSpace::Subspace&amp; subspaceForObjectNormalDestructor() { return m_objectSpace.subspaceForObjectsWithNormalDestructor(); }
+    MarkedSpace::Subspace&amp; subspaceForObjectsWithImmortalStructure() { return m_objectSpace.subspaceForObjectsWithImmortalStructure(); }
</ins><span class="cx">     MarkedAllocator&amp; allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
</span><span class="cx">     MarkedAllocator&amp; allocatorForObjectWithNormalDestructor(size_t bytes) { return m_objectSpace.normalDestructorAllocatorFor(bytes); }
</span><span class="cx">     MarkedAllocator&amp; allocatorForObjectWithImmortalStructureDestructor(size_t bytes) { return m_objectSpace.immortalStructureDestructorAllocatorFor(bytes); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedSpaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedSpace.h (174794 => 174795)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2014-10-16 21:58:06 UTC (rev 174794)
+++ trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2014-10-16 22:02:16 UTC (rev 174795)
</span><span class="lines">@@ -82,6 +82,22 @@
</span><span class="cx"> class MarkedSpace {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(MarkedSpace);
</span><span class="cx"> public:
</span><ins>+    // [ 32... 128 ]
+    static const size_t preciseStep = MarkedBlock::atomSize;
+    static const size_t preciseCutoff = 128;
+    static const size_t preciseCount = preciseCutoff / preciseStep;
+
+    // [ 1024... blockSize ]
+    static const size_t impreciseStep = 2 * preciseCutoff;
+    static const size_t impreciseCutoff = MarkedBlock::blockSize / 2;
+    static const size_t impreciseCount = impreciseCutoff / impreciseStep;
+
+    struct Subspace {
+        std::array&lt;MarkedAllocator, preciseCount&gt; preciseAllocators;
+        std::array&lt;MarkedAllocator, impreciseCount&gt; impreciseAllocators;
+        MarkedAllocator largeAllocator;
+    };
+
</ins><span class="cx">     MarkedSpace(Heap*);
</span><span class="cx">     ~MarkedSpace();
</span><span class="cx">     void lastChanceToFinalize();
</span><span class="lines">@@ -93,7 +109,11 @@
</span><span class="cx">     void* allocateWithNormalDestructor(size_t);
</span><span class="cx">     void* allocateWithImmortalStructureDestructor(size_t);
</span><span class="cx">     void* allocateWithoutDestructor(size_t);
</span><del>- 
</del><ins>+
+    Subspace&amp; subspaceForObjectsWithNormalDestructor() { return m_normalDestructorSpace; }
+    Subspace&amp; subspaceForObjectsWithImmortalStructure() { return m_immortalStructureDestructorSpace; }
+    Subspace&amp; subspaceForObjectsWithoutDestructor() { return m_normalSpace; }
+
</ins><span class="cx">     void resetAllocators();
</span><span class="cx"> 
</span><span class="cx">     void visitWeakSets(HeapRootVisitor&amp;);
</span><span class="lines">@@ -143,26 +163,11 @@
</span><span class="cx"> private:
</span><span class="cx">     friend class DelayedReleaseScope;
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span><ins>+    friend class JIT;
</ins><span class="cx"> 
</span><span class="cx">     template&lt;typename Functor&gt; void forEachAllocator(Functor&amp;);
</span><span class="cx">     template&lt;typename Functor&gt; void forEachAllocator();
</span><span class="cx"> 
</span><del>-    // [ 32... 128 ]
-    static const size_t preciseStep = MarkedBlock::atomSize;
-    static const size_t preciseCutoff = 128;
-    static const size_t preciseCount = preciseCutoff / preciseStep;
-
-    // [ 1024... blockSize ]
-    static const size_t impreciseStep = 2 * preciseCutoff;
-    static const size_t impreciseCutoff = MarkedBlock::blockSize / 2;
-    static const size_t impreciseCount = impreciseCutoff / impreciseStep;
-
-    struct Subspace {
-        std::array&lt;MarkedAllocator, preciseCount&gt; preciseAllocators;
-        std::array&lt;MarkedAllocator, impreciseCount&gt; impreciseAllocators;
-        MarkedAllocator largeAllocator;
-    };
-
</del><span class="cx">     Subspace m_normalDestructorSpace;
</span><span class="cx">     Subspace m_immortalStructureDestructorSpace;
</span><span class="cx">     Subspace m_normalSpace;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterStackVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp (174794 => 174795)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2014-10-16 21:58:06 UTC (rev 174794)
+++ trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2014-10-16 22:02:16 UTC (rev 174795)
</span><span class="lines">@@ -271,6 +271,7 @@
</span><span class="cx">         ASSERT(m_inlineCallFrame);
</span><span class="cx">         arguments = Arguments::create(vm, physicalFrame, m_inlineCallFrame, mode);
</span><span class="cx">         arguments-&gt;tearOff(physicalFrame, m_inlineCallFrame);
</span><ins>+        jsCast&lt;Arguments*&gt;((JSCell*)arguments);
</ins><span class="cx">     } else 
</span><span class="cx"> #endif
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.cpp (174794 => 174795)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.cpp        2014-10-16 21:58:06 UTC (rev 174794)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.cpp        2014-10-16 22:02:16 UTC (rev 174795)
</span><span class="lines">@@ -43,14 +43,13 @@
</span><span class="cx"> void Arguments::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><span class="cx">     Arguments* thisObject = jsCast&lt;Arguments*&gt;(cell);
</span><ins>+
</ins><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx">     JSObject::visitChildren(thisObject, visitor);
</span><span class="cx"> 
</span><del>-    if (thisObject-&gt;m_registerArray) {
-        visitor.copyLater(thisObject, ArgumentsRegisterArrayCopyToken, 
-            thisObject-&gt;m_registerArray.get(), thisObject-&gt;registerArraySizeInBytes());
-        visitor.appendValues(thisObject-&gt;m_registerArray.get(), thisObject-&gt;m_numArguments);
-    }
</del><ins>+    if (thisObject-&gt;isTornOff())
+        visitor.appendValues(&amp;thisObject-&gt;registerArray(), thisObject-&gt;m_numArguments);
+
</ins><span class="cx">     if (thisObject-&gt;m_slowArgumentData) {
</span><span class="cx">         visitor.copyLater(thisObject, ArgumentsSlowArgumentDataCopyToken,
</span><span class="cx">             thisObject-&gt;m_slowArgumentData.get(), SlowArgumentData::sizeForNumArguments(thisObject-&gt;m_numArguments));
</span><span class="lines">@@ -66,22 +65,6 @@
</span><span class="cx">     
</span><span class="cx"> 
</span><span class="cx">     switch (token) {
</span><del>-    case ArgumentsRegisterArrayCopyToken: {
-        WriteBarrier&lt;Unknown&gt;* registerArray = thisObject-&gt;m_registerArray.get();
-        if (!registerArray)
-            return;
-
-        if (visitor.checkIfShouldCopy(registerArray)) {
-            size_t bytes = thisObject-&gt;registerArraySizeInBytes();
-            WriteBarrier&lt;Unknown&gt;* newRegisterArray = static_cast&lt;WriteBarrier&lt;Unknown&gt;*&gt;(visitor.allocateNewSpace(bytes));
-            memcpy(newRegisterArray, registerArray, bytes);
-            thisObject-&gt;m_registerArray.setWithoutWriteBarrier(newRegisterArray);
-            thisObject-&gt;m_registers = newRegisterArray - CallFrame::offsetFor(1) - 1;
-            visitor.didCopy(registerArray, bytes);
-        }
-        return;
-    }
-
</del><span class="cx">     case ArgumentsSlowArgumentDataCopyToken: {
</span><span class="cx">         SlowArgumentData* slowArgumentData = thisObject-&gt;m_slowArgumentData.get();
</span><span class="cx">         if (!slowArgumentData)
</span><span class="lines">@@ -361,15 +344,6 @@
</span><span class="cx">     return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Arguments::allocateRegisterArray(VM&amp; vm)
-{
-    ASSERT(!m_registerArray);
-    void* backingStore;
-    if (!vm.heap.tryAllocateStorage(this, registerArraySizeInBytes(), &amp;backingStore))
-        RELEASE_ASSERT_NOT_REACHED();
-    m_registerArray.set(vm, this, static_cast&lt;WriteBarrier&lt;Unknown&gt;*&gt;(backingStore));
-}
-
</del><span class="cx"> void Arguments::tearOff(CallFrame* callFrame)
</span><span class="cx"> {
</span><span class="cx">     if (isTornOff())
</span><span class="lines">@@ -380,13 +354,14 @@
</span><span class="cx"> 
</span><span class="cx">     // Must be called for the same call frame from which it was created.
</span><span class="cx">     ASSERT(bitwise_cast&lt;WriteBarrier&lt;Unknown&gt;*&gt;(callFrame) == m_registers);
</span><del>-    
-    allocateRegisterArray(callFrame-&gt;vm());
-    m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1;
</del><span class="cx"> 
</span><ins>+    m_registers = &amp;registerArray() - CallFrame::offsetFor(1) - 1;
+
</ins><span class="cx">     for (size_t i = 0; i &lt; m_numArguments; ++i) {
</span><del>-        if (m_slowArgumentData &amp;&amp; m_slowArgumentData-&gt;slowArguments()[i].status == SlowArgument::Captured)
</del><ins>+        if (m_slowArgumentData &amp;&amp; m_slowArgumentData-&gt;slowArguments()[i].status == SlowArgument::Captured) {
+            m_registers[CallFrame::argumentOffset(i)].setUndefined();
</ins><span class="cx">             continue;
</span><ins>+        }
</ins><span class="cx">         trySetArgument(callFrame-&gt;vm(), i, callFrame-&gt;argumentAfterCapture(i));
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -399,10 +374,9 @@
</span><span class="cx">     
</span><span class="cx">     if (!m_numArguments)
</span><span class="cx">         return;
</span><del>-    
-    allocateRegisterArray(callFrame-&gt;vm());
-    m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1;
</del><span class="cx"> 
</span><ins>+    m_registers = &amp;registerArray() - CallFrame::offsetFor(1) - 1;
+
</ins><span class="cx">     for (size_t i = 0; i &lt; m_numArguments; ++i) {
</span><span class="cx">         ValueRecovery&amp; recovery = inlineCallFrame-&gt;arguments[i + 1];
</span><span class="cx">         trySetArgument(callFrame-&gt;vm(), i, recovery.recover(callFrame));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.h (174794 => 174795)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.h        2014-10-16 21:58:06 UTC (rev 174794)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.h        2014-10-16 22:02:16 UTC (rev 174795)
</span><span class="lines">@@ -48,14 +48,14 @@
</span><span class="cx"> 
</span><span class="cx">     static Arguments* create(VM&amp; vm, CallFrame* callFrame, ArgumentsMode mode = NormalArgumentsCreationMode)
</span><span class="cx">     {
</span><del>-        Arguments* arguments = new (NotNull, allocateCell&lt;Arguments&gt;(vm.heap)) Arguments(callFrame);
</del><ins>+        Arguments* arguments = new (NotNull, allocateCell&lt;Arguments&gt;(vm.heap, offsetOfInlineRegisterArray() + registerArraySizeInBytes(callFrame))) Arguments(callFrame);
</ins><span class="cx">         arguments-&gt;finishCreation(callFrame, mode);
</span><span class="cx">         return arguments;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     static Arguments* create(VM&amp; vm, CallFrame* callFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode = NormalArgumentsCreationMode)
</span><span class="cx">     {
</span><del>-        Arguments* arguments = new (NotNull, allocateCell&lt;Arguments&gt;(vm.heap)) Arguments(callFrame);
</del><ins>+        Arguments* arguments = new (NotNull, allocateCell&lt;Arguments&gt;(vm.heap, offsetOfInlineRegisterArray() + registerArraySizeInBytes(inlineCallFrame))) Arguments(callFrame);
</ins><span class="cx">         arguments-&gt;finishCreation(callFrame, inlineCallFrame, mode);
</span><span class="cx">         return arguments;
</span><span class="cx">     }
</span><span class="lines">@@ -86,7 +86,7 @@
</span><span class="cx">     void copyToArguments(ExecState*, CallFrame*, uint32_t copyLength, int32_t firstArgumentOffset);
</span><span class="cx">     void tearOff(CallFrame*);
</span><span class="cx">     void tearOff(CallFrame*, InlineCallFrame*);
</span><del>-    bool isTornOff() const { return m_registerArray.get(); }
</del><ins>+    bool isTornOff() const { return m_registers == (&amp;registerArray() - CallFrame::offsetFor(1) - 1); }
</ins><span class="cx"> 
</span><span class="cx">     static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype) 
</span><span class="cx">     { 
</span><span class="lines">@@ -98,15 +98,9 @@
</span><span class="cx">     static ptrdiff_t offsetOfOverrodeLength() { return OBJECT_OFFSETOF(Arguments, m_overrodeLength); }
</span><span class="cx">     static ptrdiff_t offsetOfIsStrictMode() { return OBJECT_OFFSETOF(Arguments, m_isStrictMode); }
</span><span class="cx">     static ptrdiff_t offsetOfRegisters() { return OBJECT_OFFSETOF(Arguments, m_registers); }
</span><del>-    static ptrdiff_t offsetOfRegisterArray() { return OBJECT_OFFSETOF(Arguments, m_registerArray); }
</del><ins>+    static ptrdiff_t offsetOfInlineRegisterArray() { return WTF::roundUpToMultipleOf&lt;8&gt;(sizeof(Arguments)); }
</ins><span class="cx">     static ptrdiff_t offsetOfSlowArgumentData() { return OBJECT_OFFSETOF(Arguments, m_slowArgumentData); }
</span><span class="cx">     static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(Arguments, m_callee); }
</span><del>-
-    static size_t allocationSize(size_t inlineCapacity)
-    {
-        ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
-        return sizeof(Arguments);
-    }
</del><span class="cx">     
</span><span class="cx"> protected:
</span><span class="cx">     static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | JSObject::StructureFlags;
</span><span class="lines">@@ -126,8 +120,8 @@
</span><span class="cx">     void createStrictModeCallerIfNecessary(ExecState*);
</span><span class="cx">     void createStrictModeCalleeIfNecessary(ExecState*);
</span><span class="cx"> 
</span><del>-    size_t registerArraySizeInBytes() const { return sizeof(WriteBarrier&lt;Unknown&gt;) * m_numArguments; }
-    void allocateRegisterArray(VM&amp;);
</del><ins>+    static size_t registerArraySizeInBytes(CallFrame* callFrame) { return sizeof(WriteBarrier&lt;Unknown&gt;) * callFrame-&gt;argumentCount(); }
+    static size_t registerArraySizeInBytes(InlineCallFrame* inlineCallFrame) { return sizeof(WriteBarrier&lt;Unknown&gt;) * (inlineCallFrame-&gt;arguments.size() - 1); }
</ins><span class="cx">     bool isArgument(size_t);
</span><span class="cx">     bool trySetArgument(VM&amp;, size_t argument, JSValue);
</span><span class="cx">     JSValue tryGetArgument(size_t argument);
</span><span class="lines">@@ -151,7 +145,8 @@
</span><span class="cx">     bool m_isStrictMode;
</span><span class="cx"> 
</span><span class="cx">     WriteBarrierBase&lt;Unknown&gt;* m_registers;
</span><del>-    CopyWriteBarrier&lt;WriteBarrier&lt;Unknown&gt;&gt; m_registerArray;
</del><ins>+    WriteBarrier&lt;Unknown&gt;&amp; registerArray() { return *reinterpret_cast&lt;WriteBarrier&lt;Unknown&gt;*&gt;(reinterpret_cast&lt;char*&gt;(this) + offsetOfInlineRegisterArray()); }
+    const WriteBarrier&lt;Unknown&gt;&amp; registerArray() const { return *reinterpret_cast&lt;const WriteBarrier&lt;Unknown&gt;*&gt;(reinterpret_cast&lt;const char*&gt;(this) + offsetOfInlineRegisterArray()); }
</ins><span class="cx"> 
</span><span class="cx"> public:
</span><span class="cx">     struct SlowArgumentData {
</span></span></pre>
</div>
</div>

</body>
</html>