<!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>[167641] 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/167641">167641</a></dd>
<dt>Author</dt> <dd>mhahnenberg@apple.com</dd>
<dt>Date</dt> <dd>2014-04-21 18:37:34 -0700 (Mon, 21 Apr 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Arguments objects shouldn't need a destructor
https://bugs.webkit.org/show_bug.cgi?id=131899

Reviewed by Oliver Hunt.

This patch rids Arguments objects of their destructors. It does this by
switching their backing stores to use CopiedSpace rather than malloc memory.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::emitAllocateArguments): Fix the code emitted for inline
Arguments allocation so that it only emits an extra write for strict mode code rather
than unconditionally.
* heap/CopyToken.h: New CopyTokens for the two different types of Arguments backing stores.
* runtime/Arguments.cpp:
(JSC::Arguments::visitChildren): We need to tell the collector to copy the back stores now.
(JSC::Arguments::copyBackingStore): Do the actual copying of the backing stores.
(JSC::Arguments::deletePropertyByIndex): Update all the accesses to SlowArgumentData and m_registerArray.
(JSC::Arguments::deleteProperty):
(JSC::Arguments::defineOwnProperty):
(JSC::Arguments::allocateRegisterArray):
(JSC::Arguments::tearOff):
(JSC::Arguments::destroy): Deleted. We don't need the destructor any more.
* runtime/Arguments.h:
(JSC::Arguments::registerArraySizeInBytes):
(JSC::Arguments::SlowArgumentData::SlowArgumentData): Switch SlowArgumentData to being allocated
in CopiedSpace. Now the SlowArgumentData and its backing store are a single contiguous CopiedSpace
allocation.
(JSC::Arguments::SlowArgumentData::slowArguments):
(JSC::Arguments::SlowArgumentData::bytecodeToMachineCaptureOffset):
(JSC::Arguments::SlowArgumentData::setBytecodeToMachineCaptureOffset):
(JSC::Arguments::SlowArgumentData::sizeForNumArguments):
(JSC::Arguments::Arguments):
(JSC::Arguments::allocateSlowArguments):
(JSC::Arguments::tryDeleteArgument):
(JSC::Arguments::isDeletedArgument):
(JSC::Arguments::isArgument):
(JSC::Arguments::argument):
(JSC::Arguments::finishCreation):
* runtime/SymbolTable.h:</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="#trunkSourceJavaScriptCoreheapCopyTokenh">trunk/Source/JavaScriptCore/heap/CopyToken.h</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>
<li><a href="#trunkSourceJavaScriptCoreruntimeSymbolTableh">trunk/Source/JavaScriptCore/runtime/SymbolTable.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (167640 => 167641)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-04-22 01:34:46 UTC (rev 167640)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-04-22 01:37:34 UTC (rev 167641)
</span><span class="lines">@@ -1,3 +1,45 @@
</span><ins>+2014-04-21  Mark Hahnenberg  &lt;mhahnenberg@apple.com&gt;
+
+        Arguments objects shouldn't need a destructor
+        https://bugs.webkit.org/show_bug.cgi?id=131899
+
+        Reviewed by Oliver Hunt.
+
+        This patch rids Arguments objects of their destructors. It does this by 
+        switching their backing stores to use CopiedSpace rather than malloc memory.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::emitAllocateArguments): Fix the code emitted for inline
+        Arguments allocation so that it only emits an extra write for strict mode code rather
+        than unconditionally.
+        * heap/CopyToken.h: New CopyTokens for the two different types of Arguments backing stores.
+        * runtime/Arguments.cpp:
+        (JSC::Arguments::visitChildren): We need to tell the collector to copy the back stores now.
+        (JSC::Arguments::copyBackingStore): Do the actual copying of the backing stores.
+        (JSC::Arguments::deletePropertyByIndex): Update all the accesses to SlowArgumentData and m_registerArray.
+        (JSC::Arguments::deleteProperty):
+        (JSC::Arguments::defineOwnProperty):
+        (JSC::Arguments::allocateRegisterArray):
+        (JSC::Arguments::tearOff):
+        (JSC::Arguments::destroy): Deleted. We don't need the destructor any more.
+        * runtime/Arguments.h:
+        (JSC::Arguments::registerArraySizeInBytes):
+        (JSC::Arguments::SlowArgumentData::SlowArgumentData): Switch SlowArgumentData to being allocated
+        in CopiedSpace. Now the SlowArgumentData and its backing store are a single contiguous CopiedSpace
+        allocation.
+        (JSC::Arguments::SlowArgumentData::slowArguments):
+        (JSC::Arguments::SlowArgumentData::bytecodeToMachineCaptureOffset):
+        (JSC::Arguments::SlowArgumentData::setBytecodeToMachineCaptureOffset):
+        (JSC::Arguments::SlowArgumentData::sizeForNumArguments):
+        (JSC::Arguments::Arguments):
+        (JSC::Arguments::allocateSlowArguments):
+        (JSC::Arguments::tryDeleteArgument):
+        (JSC::Arguments::isDeletedArgument):
+        (JSC::Arguments::isArgument):
+        (JSC::Arguments::argument):
+        (JSC::Arguments::finishCreation):
+        * runtime/SymbolTable.h:
+
</ins><span class="cx"> 2014-04-21  Eric Carlson  &lt;eric.carlson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Mac] implement WebKitDataCue
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (167640 => 167641)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-04-22 01:34:46 UTC (rev 167640)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-04-22 01:37:34 UTC (rev 167641)
</span><span class="lines">@@ -118,8 +118,8 @@
</span><span class="cx">     m_jit.store32(scratchGPR1, MacroAssembler::Address(resultGPR, Arguments::offsetOfNumArguments()));
</span><span class="cx"> 
</span><span class="cx">     m_jit.store32(TrustedImm32(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfOverrodeLength()));
</span><del>-    m_jit.store8(TrustedImm32(m_jit.isStrictModeFor(m_currentNode-&gt;origin.semantic)), 
-        MacroAssembler::Address(resultGPR, Arguments::offsetOfIsStrictMode()));
</del><ins>+    if (m_jit.isStrictModeFor(m_currentNode-&gt;origin.semantic))
+        m_jit.store8(TrustedImm32(1), MacroAssembler::Address(resultGPR, Arguments::offsetOfIsStrictMode()));
</ins><span class="cx"> 
</span><span class="cx">     m_jit.storePtr(GPRInfo::callFrameRegister, MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisters()));
</span><span class="cx">     m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisterArray()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCopyTokenh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CopyToken.h (167640 => 167641)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CopyToken.h        2014-04-22 01:34:46 UTC (rev 167640)
+++ trunk/Source/JavaScriptCore/heap/CopyToken.h        2014-04-22 01:37:34 UTC (rev 167641)
</span><span class="lines">@@ -31,7 +31,9 @@
</span><span class="cx"> enum CopyToken {
</span><span class="cx">     ButterflyCopyToken,
</span><span class="cx">     TypedArrayVectorCopyToken,
</span><del>-    MapBackingStoreCopyToken
</del><ins>+    MapBackingStoreCopyToken,
+    ArgumentsRegisterArrayCopyToken,
+    ArgumentsSlowArgumentDataCopyToken
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.cpp (167640 => 167641)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.cpp        2014-04-22 01:34:46 UTC (rev 167640)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.cpp        2014-04-22 01:37:34 UTC (rev 167641)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;Arguments.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CopyVisitorInlines.h&quot;
</ins><span class="cx"> #include &quot;JSActivation.h&quot;
</span><span class="cx"> #include &quot;JSArgumentsIterator.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="lines">@@ -35,6 +36,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(Arguments);
+
</ins><span class="cx"> const ClassInfo Arguments::s_info = { &quot;Arguments&quot;, &amp;Base::s_info, 0, 0, CREATE_METHOD_TABLE(Arguments) };
</span><span class="cx"> 
</span><span class="cx"> void Arguments::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="lines">@@ -45,18 +48,62 @@
</span><span class="cx">     ASSERT(thisObject-&gt;structure()-&gt;typeInfo().overridesVisitChildren());
</span><span class="cx">     JSObject::visitChildren(thisObject, visitor);
</span><span class="cx"> 
</span><del>-    if (thisObject-&gt;m_registerArray)
</del><ins>+    if (thisObject-&gt;m_registerArray) {
+        visitor.copyLater(thisObject, ArgumentsRegisterArrayCopyToken, 
+            thisObject-&gt;m_registerArray.get(), thisObject-&gt;registerArraySizeInBytes());
</ins><span class="cx">         visitor.appendValues(thisObject-&gt;m_registerArray.get(), thisObject-&gt;m_numArguments);
</span><ins>+    }
+    if (thisObject-&gt;m_slowArgumentData) {
+        visitor.copyLater(thisObject, ArgumentsSlowArgumentDataCopyToken,
+            thisObject-&gt;m_slowArgumentData.get(), SlowArgumentData::sizeForNumArguments(thisObject-&gt;m_numArguments));
+    }
</ins><span class="cx">     visitor.append(&amp;thisObject-&gt;m_callee);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_activation);
</span><span class="cx"> }
</span><ins>+
+void Arguments::copyBackingStore(JSCell* cell, CopyVisitor&amp; visitor, CopyToken token)
+{
+    Arguments* thisObject = jsCast&lt;Arguments*&gt;(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</ins><span class="cx">     
</span><del>-static EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState*);
</del><span class="cx"> 
</span><del>-void Arguments::destroy(JSCell* cell)
-{
-    static_cast&lt;Arguments*&gt;(cell)-&gt;Arguments::~Arguments();
</del><ins>+    switch (token) {
+    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);
+            visitor.didCopy(registerArray, bytes);
+        }
+        return;
+    }
+
+    case ArgumentsSlowArgumentDataCopyToken: {
+        SlowArgumentData* slowArgumentData = thisObject-&gt;m_slowArgumentData.get();
+        if (!slowArgumentData)
+            return;
+
+        if (visitor.checkIfShouldCopy(slowArgumentData)) {
+            size_t bytes = SlowArgumentData::sizeForNumArguments(thisObject-&gt;m_numArguments);
+            SlowArgumentData* newSlowArgumentData = static_cast&lt;SlowArgumentData*&gt;(visitor.allocateNewSpace(bytes));
+            memcpy(newSlowArgumentData, slowArgumentData, bytes);
+            thisObject-&gt;m_slowArgumentData.setWithoutWriteBarrier(newSlowArgumentData);
+            visitor.didCopy(slowArgumentData, bytes);
+        }
+        return;
+    }
+
+    default:
+        return;
+    }
</ins><span class="cx"> }
</span><ins>+    
+static EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState*);
</ins><span class="cx"> 
</span><span class="cx"> void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t copyLength, int32_t firstVarArgOffset)
</span><span class="cx"> {
</span><span class="lines">@@ -226,7 +273,7 @@
</span><span class="cx">     if (i &lt; thisObject-&gt;m_numArguments) {
</span><span class="cx">         if (!Base::deletePropertyByIndex(cell, exec, i))
</span><span class="cx">             return false;
</span><del>-        if (thisObject-&gt;tryDeleteArgument(i))
</del><ins>+        if (thisObject-&gt;tryDeleteArgument(exec-&gt;vm(), i))
</ins><span class="cx">             return true;
</span><span class="cx">     }
</span><span class="cx">     return JSObject::deletePropertyByIndex(thisObject, exec, i);
</span><span class="lines">@@ -243,7 +290,7 @@
</span><span class="cx">         RELEASE_ASSERT(i &lt; PropertyName::NotAnIndex);
</span><span class="cx">         if (!Base::deleteProperty(cell, exec, propertyName))
</span><span class="cx">             return false;
</span><del>-        if (thisObject-&gt;tryDeleteArgument(i))
</del><ins>+        if (thisObject-&gt;tryDeleteArgument(exec-&gt;vm(), i))
</ins><span class="cx">             return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -288,7 +335,7 @@
</span><span class="cx">             // a. If IsAccessorDescriptor(Desc) is true, then
</span><span class="cx">             if (descriptor.isAccessorDescriptor()) {
</span><span class="cx">                 // i. Call the [[Delete]] internal method of map passing P, and false as the arguments.
</span><del>-                thisObject-&gt;tryDeleteArgument(i);
</del><ins>+                thisObject-&gt;tryDeleteArgument(exec-&gt;vm(), i);
</ins><span class="cx">             } else { // b. Else
</span><span class="cx">                 // i. If Desc.[[Value]] is present, then
</span><span class="cx">                 // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments.
</span><span class="lines">@@ -297,7 +344,7 @@
</span><span class="cx">                 // ii. If Desc.[[Writable]] is present and its value is false, then
</span><span class="cx">                 // 1. Call the [[Delete]] internal method of map passing P and false as arguments.
</span><span class="cx">                 if (descriptor.writablePresent() &amp;&amp; !descriptor.writable())
</span><del>-                    thisObject-&gt;tryDeleteArgument(i);
</del><ins>+                    thisObject-&gt;tryDeleteArgument(exec-&gt;vm(), i);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         return true;
</span><span class="lines">@@ -315,6 +362,15 @@
</span><span class="cx">     return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+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));
+}
+
</ins><span class="cx"> void Arguments::tearOff(CallFrame* callFrame)
</span><span class="cx"> {
</span><span class="cx">     if (isTornOff())
</span><span class="lines">@@ -326,7 +382,7 @@
</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><span class="cx">     
</span><del>-    m_registerArray = std::make_unique&lt;WriteBarrier&lt;Unknown&gt;[]&gt;(m_numArguments);
</del><ins>+    allocateRegisterArray(callFrame-&gt;vm());
</ins><span class="cx">     m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1;
</span><span class="cx"> 
</span><span class="cx">     // If we have a captured argument that logically aliases activation storage,
</span><span class="lines">@@ -334,10 +390,10 @@
</span><span class="cx">     // our storage. The simplest way to do this is to revert it to Normal status.
</span><span class="cx">     if (m_slowArgumentData &amp;&amp; !m_activation) {
</span><span class="cx">         for (size_t i = 0; i &lt; m_numArguments; ++i) {
</span><del>-            if (m_slowArgumentData-&gt;slowArguments[i].status != SlowArgument::Captured)
</del><ins>+            if (m_slowArgumentData-&gt;slowArguments()[i].status != SlowArgument::Captured)
</ins><span class="cx">                 continue;
</span><del>-            m_slowArgumentData-&gt;slowArguments[i].status = SlowArgument::Normal;
-            m_slowArgumentData-&gt;slowArguments[i].index = CallFrame::argumentOffset(i);
</del><ins>+            m_slowArgumentData-&gt;slowArguments()[i].status = SlowArgument::Normal;
+            m_slowArgumentData-&gt;slowArguments()[i].index = CallFrame::argumentOffset(i);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -366,7 +422,7 @@
</span><span class="cx">     if (!m_numArguments)
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    m_registerArray = std::make_unique&lt;WriteBarrier&lt;Unknown&gt;[]&gt;(m_numArguments);
</del><ins>+    allocateRegisterArray(callFrame-&gt;vm());
</ins><span class="cx">     m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1;
</span><span class="cx"> 
</span><span class="cx">     for (size_t i = 0; i &lt; m_numArguments; ++i) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.h (167640 => 167641)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.h        2014-04-22 01:34:46 UTC (rev 167640)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.h        2014-04-22 01:37:34 UTC (rev 167641)
</span><span class="lines">@@ -26,7 +26,6 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeOrigin.h&quot;
</span><span class="cx"> #include &quot;JSActivation.h&quot;
</span><del>-#include &quot;JSDestructibleObject.h&quot;
</del><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;JSGlobalObject.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="lines">@@ -36,11 +35,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-class Arguments : public JSDestructibleObject {
</del><ins>+class Arguments : public JSNonFinalObject {
</ins><span class="cx">     friend class JIT;
</span><span class="cx">     friend class JSArgumentsIterator;
</span><span class="cx"> public:
</span><del>-    typedef JSDestructibleObject Base;
</del><ins>+    typedef JSNonFinalObject Base;
</ins><span class="cx"> 
</span><span class="cx">     static Arguments* create(VM&amp; vm, CallFrame* callFrame)
</span><span class="cx">     {
</span><span class="lines">@@ -68,6 +67,7 @@
</span><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><ins>+    static void copyBackingStore(JSCell*, CopyVisitor&amp;, CopyToken);
</ins><span class="cx"> 
</span><span class="cx">     void fillArgList(ExecState*, MarkedArgumentBuffer&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -111,7 +111,6 @@
</span><span class="cx">     void finishCreation(CallFrame*, InlineCallFrame*);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    static void destroy(JSCell*);
</del><span class="cx">     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&amp;);
</span><span class="cx">     static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&amp;);
</span><span class="cx">     static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><span class="lines">@@ -123,13 +122,15 @@
</span><span class="cx">     void createStrictModeCallerIfNecessary(ExecState*);
</span><span class="cx">     void createStrictModeCalleeIfNecessary(ExecState*);
</span><span class="cx"> 
</span><ins>+    size_t registerArraySizeInBytes() const { return sizeof(WriteBarrier&lt;Unknown&gt;) * m_numArguments; }
+    void allocateRegisterArray(VM&amp;);
</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="cx">     bool isDeletedArgument(size_t);
</span><del>-    bool tryDeleteArgument(size_t);
</del><ins>+    bool tryDeleteArgument(VM&amp;, size_t);
</ins><span class="cx">     WriteBarrierBase&lt;Unknown&gt;&amp; argument(size_t);
</span><del>-    void allocateSlowArguments();
</del><ins>+    void allocateSlowArguments(VM&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void init(CallFrame*);
</span><span class="cx"> 
</span><span class="lines">@@ -146,19 +147,35 @@
</span><span class="cx">     bool m_isStrictMode;
</span><span class="cx"> 
</span><span class="cx">     WriteBarrierBase&lt;Unknown&gt;* m_registers;
</span><del>-    std::unique_ptr&lt;WriteBarrier&lt;Unknown&gt;[]&gt; m_registerArray;
</del><ins>+    CopyWriteBarrier&lt;WriteBarrier&lt;Unknown&gt;&gt; m_registerArray;
</ins><span class="cx"> 
</span><span class="cx"> public:
</span><span class="cx">     struct SlowArgumentData {
</span><del>-        WTF_MAKE_FAST_ALLOCATED;
</del><span class="cx">     public:
</span><ins>+        SlowArgumentData()
+            : m_bytecodeToMachineCaptureOffset(0)
+        {
+        }
</ins><span class="cx"> 
</span><del>-        std::unique_ptr&lt;SlowArgument[]&gt; slowArguments;
-        int bytecodeToMachineCaptureOffset; // Add this if you have a bytecode offset into captured registers and you want the machine offset instead. Subtract if you want to do the opposite.
</del><ins>+        SlowArgument* slowArguments()
+        {
+            return reinterpret_cast&lt;SlowArgument*&gt;(WTF::roundUpToMultipleOf&lt;8&gt;(reinterpret_cast&lt;size_t&gt;(this + 1)));
+        }
+
+        int bytecodeToMachineCaptureOffset() const { return m_bytecodeToMachineCaptureOffset; }
+        void setBytecodeToMachineCaptureOffset(int newOffset) { m_bytecodeToMachineCaptureOffset = newOffset; }
+
+        static size_t sizeForNumArguments(unsigned numArguments)
+        {
+            return WTF::roundUpToMultipleOf&lt;8&gt;(sizeof(SlowArgumentData)) + sizeof(SlowArgument) * numArguments;
+        }
+
+    private:
+        int m_bytecodeToMachineCaptureOffset; // Add this if you have a bytecode offset into captured registers and you want the machine offset instead. Subtract if you want to do the opposite. 
</ins><span class="cx">     };
</span><span class="cx">     
</span><span class="cx"> private:
</span><del>-    std::unique_ptr&lt;SlowArgumentData&gt; m_slowArgumentData;
</del><ins>+    CopyWriteBarrier&lt;SlowArgumentData&gt; m_slowArgumentData;
</ins><span class="cx"> 
</span><span class="cx">     WriteBarrier&lt;JSFunction&gt; m_callee;
</span><span class="cx"> };
</span><span class="lines">@@ -172,34 +189,37 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline Arguments::Arguments(CallFrame* callFrame)
</span><del>-    : JSDestructibleObject(callFrame-&gt;vm(), callFrame-&gt;lexicalGlobalObject()-&gt;argumentsStructure())
</del><ins>+    : Base(callFrame-&gt;vm(), callFrame-&gt;lexicalGlobalObject()-&gt;argumentsStructure())
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
</span><del>-    : JSDestructibleObject(callFrame-&gt;vm(), callFrame-&gt;lexicalGlobalObject()-&gt;argumentsStructure())
</del><ins>+    : Base(callFrame-&gt;vm(), callFrame-&gt;lexicalGlobalObject()-&gt;argumentsStructure())
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void Arguments::allocateSlowArguments()
</del><ins>+inline void Arguments::allocateSlowArguments(VM&amp; vm)
</ins><span class="cx"> {
</span><del>-    if (m_slowArgumentData)
</del><ins>+    if (!!m_slowArgumentData)
</ins><span class="cx">         return;
</span><del>-    m_slowArgumentData = std::make_unique&lt;SlowArgumentData&gt;();
-    m_slowArgumentData-&gt;bytecodeToMachineCaptureOffset = 0;
-    m_slowArgumentData-&gt;slowArguments = std::make_unique&lt;SlowArgument[]&gt;(m_numArguments);
</del><ins>+
+    void* backingStore;
+    if (!vm.heap.tryAllocateStorage(this, SlowArgumentData::sizeForNumArguments(m_numArguments), &amp;backingStore))
+        RELEASE_ASSERT_NOT_REACHED();
+    m_slowArgumentData.set(vm, this, static_cast&lt;SlowArgumentData*&gt;(backingStore));
+
</ins><span class="cx">     for (size_t i = 0; i &lt; m_numArguments; ++i) {
</span><del>-        ASSERT(m_slowArgumentData-&gt;slowArguments[i].status == SlowArgument::Normal);
-        m_slowArgumentData-&gt;slowArguments[i].index = CallFrame::argumentOffset(i);
</del><ins>+        ASSERT(m_slowArgumentData-&gt;slowArguments()[i].status == SlowArgument::Normal);
+        m_slowArgumentData-&gt;slowArguments()[i].index = CallFrame::argumentOffset(i);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool Arguments::tryDeleteArgument(size_t argument)
</del><ins>+inline bool Arguments::tryDeleteArgument(VM&amp; vm, size_t argument)
</ins><span class="cx"> {
</span><span class="cx">     if (!isArgument(argument))
</span><span class="cx">         return false;
</span><del>-    allocateSlowArguments();
-    m_slowArgumentData-&gt;slowArguments[argument].status = SlowArgument::Deleted;
</del><ins>+    allocateSlowArguments(vm);
+    m_slowArgumentData-&gt;slowArguments()[argument].status = SlowArgument::Deleted;
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -224,7 +244,7 @@
</span><span class="cx">         return false;
</span><span class="cx">     if (!m_slowArgumentData)
</span><span class="cx">         return false;
</span><del>-    if (m_slowArgumentData-&gt;slowArguments[argument].status != SlowArgument::Deleted)
</del><ins>+    if (m_slowArgumentData-&gt;slowArguments()[argument].status != SlowArgument::Deleted)
</ins><span class="cx">         return false;
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="lines">@@ -233,7 +253,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (argument &gt;= m_numArguments)
</span><span class="cx">         return false;
</span><del>-    if (m_slowArgumentData &amp;&amp; m_slowArgumentData-&gt;slowArguments[argument].status == SlowArgument::Deleted)
</del><ins>+    if (m_slowArgumentData &amp;&amp; m_slowArgumentData-&gt;slowArguments()[argument].status == SlowArgument::Deleted)
</ins><span class="cx">         return false;
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="lines">@@ -244,11 +264,11 @@
</span><span class="cx">     if (!m_slowArgumentData)
</span><span class="cx">         return m_registers[CallFrame::argumentOffset(argument)];
</span><span class="cx"> 
</span><del>-    int index = m_slowArgumentData-&gt;slowArguments[argument].index;
-    if (!m_activation || m_slowArgumentData-&gt;slowArguments[argument].status != SlowArgument::Captured)
</del><ins>+    int index = m_slowArgumentData-&gt;slowArguments()[argument].index;
+    if (!m_activation || m_slowArgumentData-&gt;slowArguments()[argument].status != SlowArgument::Captured)
</ins><span class="cx">         return m_registers[index];
</span><span class="cx"> 
</span><del>-    return m_activation-&gt;registerAt(index - m_slowArgumentData-&gt;bytecodeToMachineCaptureOffset);
</del><ins>+    return m_activation-&gt;registerAt(index - m_slowArgumentData-&gt;bytecodeToMachineCaptureOffset());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void Arguments::finishCreation(CallFrame* callFrame)
</span><span class="lines">@@ -269,12 +289,12 @@
</span><span class="cx">     if (codeBlock-&gt;hasSlowArguments()) {
</span><span class="cx">         SymbolTable* symbolTable = codeBlock-&gt;symbolTable();
</span><span class="cx">         const SlowArgument* slowArguments = codeBlock-&gt;machineSlowArguments();
</span><del>-        allocateSlowArguments();
</del><ins>+        allocateSlowArguments(callFrame-&gt;vm());
</ins><span class="cx">         size_t count = std::min&lt;unsigned&gt;(m_numArguments, symbolTable-&gt;parameterCount());
</span><span class="cx">         for (size_t i = 0; i &lt; count; ++i)
</span><del>-            m_slowArgumentData-&gt;slowArguments[i] = slowArguments[i];
-        m_slowArgumentData-&gt;bytecodeToMachineCaptureOffset =
-            codeBlock-&gt;framePointerOffsetToGetActivationRegisters();
</del><ins>+            m_slowArgumentData-&gt;slowArguments()[i] = slowArguments[i];
+        m_slowArgumentData-&gt;setBytecodeToMachineCaptureOffset(
+            codeBlock-&gt;framePointerOffsetToGetActivationRegisters());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // The bytecode generator omits op_tear_off_activation in cases of no
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSymbolTableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SymbolTable.h (167640 => 167641)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SymbolTable.h        2014-04-22 01:34:46 UTC (rev 167640)
+++ trunk/Source/JavaScriptCore/runtime/SymbolTable.h        2014-04-22 01:37:34 UTC (rev 167641)
</span><span class="lines">@@ -39,9 +39,7 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> struct SlowArgument {
</span><del>-    WTF_MAKE_FAST_ALLOCATED;
</del><span class="cx"> public:
</span><del>-
</del><span class="cx">     enum Status {
</span><span class="cx">         Normal = 0,
</span><span class="cx">         Captured = 1,
</span></span></pre>
</div>
</div>

</body>
</html>