<!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>[210146] 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/210146">210146</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-12-24 13:26:22 -0800 (Sat, 24 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[test262] Fixing mapped arguments object property test case
https://bugs.webkit.org/show_bug.cgi?id=159398

Patch by Caio Lima &lt;ticaiolima@gmail.com&gt; on 2016-12-24
Reviewed by Saam Barati.

JSTests:

* stress/arguments-bizarre-behaviour-disable-enumerability.js:
* stress/arguments-define-property.js: Added.
(assert):
(testProperties):
* stress/arguments-non-configurable.js: Added.
(assert):
(tryChangeNonConfigurableDescriptor):
(set tryChangeNonConfigurableDescriptor):
(tryChangeWritableOfNonConfigurableDescriptor):
* test262.yaml:

Source/JavaScriptCore:

This patch changes GenericArguments' override mechanism to
implement corret behavior on ECMAScript test262 suite test cases of
mapped arguments object with non-configurable and non-writable
property. Also it is ensuring that arguments[i]
cannot be deleted when argument &quot;i&quot; is {configurable: false}.

The previous implementation is against to the specification for 2 reasons:

1. Every argument in arguments object are {writable: true} by default
   (http://www.ecma-international.org/ecma-262/7.0/index.html#sec-createunmappedargumentsobject).
   It means that we have to stop mapping a defined property index
   if the new property descriptor contains writable (i.e writable is
   present) and its value is false (also check
   https://tc39.github.io/ecma262/#sec-arguments-exotic-objects-defineownproperty-p-desc).
   Previous implementation considers {writable: false} if writable is
   not present.

2. When a property is overriden, &quot;delete&quot; operation is always returning true. However
   delete operations should follow the specification.

We created an auxilary boolean array named m_modifiedArgumentsDescriptor
to store which arguments[i] descriptor was changed from its default
property descriptor. This modification was necessary because m_overrides
was responsible to keep this information at the same time
of keeping information about arguments mapping. The problem of this apporach was
that we needed to call overridesArgument(i) as soon as the ith argument's property
descriptor was changed and it stops the argument's mapping as sideffect, producing
wrong behavior.
To keep tracking arguments mapping status, we renamed DirectArguments::m_overrides to
DirectArguments::m_mappedArguments and now we it is responsible to manage if an
argument[i] is mapped or not.
With these 2 structures, now it is possible to an argument[i] have its property
descriptor modified and don't stop the mapping as soon as it happens. One example
of that wrong behavior can be found on arguments-bizarre-behaviour-disable-enumerability
test case, that now is fixed by this new mechanism.

* bytecode/PolymorphicAccess.cpp:
(JSC::AccessCase::generateWithGuard):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments):
(JSC::DFG::SpeculativeJIT::compileGetArrayLength):
(JSC::DFG::SpeculativeJIT::compileCreateDirectArguments):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength):
(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateDirectArguments):
* jit/JITOperations.cpp:
(JSC::canAccessArgumentIndexQuickly):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emitDirectArgumentsGetByVal):
* runtime/DirectArguments.cpp:
(JSC::DirectArguments::estimatedSize):
(JSC::DirectArguments::visitChildren):
(JSC::DirectArguments::overrideThings):
(JSC::DirectArguments::overrideThingsIfNecessary):
(JSC::DirectArguments::unmapArgument):
(JSC::DirectArguments::copyToArguments):
(JSC::DirectArguments::overridesSize):
(JSC::DirectArguments::overrideArgument): Deleted.
* runtime/DirectArguments.h:
(JSC::DirectArguments::length):
(JSC::DirectArguments::isMappedArgument):
(JSC::DirectArguments::isMappedArgumentInDFG):
(JSC::DirectArguments::getIndexQuickly):
(JSC::DirectArguments::setIndexQuickly):
(JSC::DirectArguments::overrodeThings):
(JSC::DirectArguments::initModifiedArgumentsDescriptorIfNecessary):
(JSC::DirectArguments::setModifiedArgumentDescriptor):
(JSC::DirectArguments::isModifiedArgumentDescriptor):
(JSC::DirectArguments::offsetOfMappedArguments):
(JSC::DirectArguments::offsetOfModifiedArgumentsDescriptor):
(JSC::DirectArguments::canAccessIndexQuickly): Deleted.
(JSC::DirectArguments::canAccessArgumentIndexQuicklyInDFG): Deleted.
(JSC::DirectArguments::offsetOfOverrides): Deleted.
* runtime/GenericArguments.h:
* runtime/GenericArgumentsInlines.h:
(JSC::GenericArguments&lt;Type&gt;::visitChildren):
(JSC::GenericArguments&lt;Type&gt;::getOwnPropertySlot):
(JSC::GenericArguments&lt;Type&gt;::getOwnPropertySlotByIndex):
(JSC::GenericArguments&lt;Type&gt;::getOwnPropertyNames):
(JSC::GenericArguments&lt;Type&gt;::put):
(JSC::GenericArguments&lt;Type&gt;::putByIndex):
(JSC::GenericArguments&lt;Type&gt;::deleteProperty):
(JSC::GenericArguments&lt;Type&gt;::deletePropertyByIndex):
(JSC::GenericArguments&lt;Type&gt;::defineOwnProperty):
(JSC::GenericArguments&lt;Type&gt;::initModifiedArgumentsDescriptor):
(JSC::GenericArguments&lt;Type&gt;::initModifiedArgumentsDescriptorIfNecessary):
(JSC::GenericArguments&lt;Type&gt;::setModifiedArgumentDescriptor):
(JSC::GenericArguments&lt;Type&gt;::isModifiedArgumentDescriptor):
(JSC::GenericArguments&lt;Type&gt;::copyToArguments):
* runtime/ScopedArguments.cpp:
(JSC::ScopedArguments::visitChildren):
(JSC::ScopedArguments::unmapArgument):
(JSC::ScopedArguments::overrideArgument): Deleted.
* runtime/ScopedArguments.h:
(JSC::ScopedArguments::isMappedArgument):
(JSC::ScopedArguments::isMappedArgumentInDFG):
(JSC::ScopedArguments::getIndexQuickly):
(JSC::ScopedArguments::setIndexQuickly):
(JSC::ScopedArguments::initModifiedArgumentsDescriptorIfNecessary):
(JSC::ScopedArguments::setModifiedArgumentDescriptor):
(JSC::ScopedArguments::isModifiedArgumentDescriptor):
(JSC::ScopedArguments::canAccessIndexQuickly): Deleted.
(JSC::ScopedArguments::canAccessArgumentIndexQuicklyInDFG): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestsstressargumentsbizarrebehaviourdisableenumerabilityjs">trunk/JSTests/stress/arguments-bizarre-behaviour-disable-enumerability.js</a></li>
<li><a href="#trunkJSTeststest262yaml">trunk/JSTests/test262.yaml</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccesscpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeDirectArgumentscpp">trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeDirectArgumentsh">trunk/Source/JavaScriptCore/runtime/DirectArguments.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeGenericArgumentsh">trunk/Source/JavaScriptCore/runtime/GenericArguments.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeGenericArgumentsInlinesh">trunk/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeScopedArgumentscpp">trunk/Source/JavaScriptCore/runtime/ScopedArguments.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeScopedArgumentsh">trunk/Source/JavaScriptCore/runtime/ScopedArguments.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressargumentsdefinepropertyjs">trunk/JSTests/stress/arguments-define-property.js</a></li>
<li><a href="#trunkJSTestsstressargumentsnonconfigurablejs">trunk/JSTests/stress/arguments-non-configurable.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/JSTests/ChangeLog        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -1,3 +1,39 @@
</span><ins>+2016-12-24  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [test262] Fixing mapped arguments object property test case
+        https://bugs.webkit.org/show_bug.cgi?id=159398
+
+        Reviewed by Saam Barati.
+
+        * stress/arguments-bizarre-behaviour-disable-enumerability.js:
+        * stress/arguments-define-property.js: Added.
+        (assert):
+        (testProperties):
+        * stress/arguments-non-configurable.js: Added.
+        (assert):
+        (tryChangeNonConfigurableDescriptor):
+        (set tryChangeNonConfigurableDescriptor):
+        (tryChangeWritableOfNonConfigurableDescriptor):
+        * test262.yaml:
+
+016-12-20  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [test262] Fixing mapped arguments object property test case
+        https://bugs.webkit.org/show_bug.cgi?id=159398
+
+        Reviewed by .
+
+        * stress/arguments-bizarre-behaviour-disable-enumerability.js:
+        * stress/arguments-define-property.js: Added.
+        (assert):
+        (testProperties):
+        * stress/arguments-non-configurable.js: Added.
+        (assert):
+        (tryChangeNonConfigurableDescriptor):
+        (set tryChangeNonConfigurableDescriptor):
+        (tryChangeWritableOfNonConfigurableDescriptor):
+        * test262.yaml:
+
</ins><span class="cx"> 2016-12-23  Keith Miller  &lt;keith_miller@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: trap on bad division.
</span></span></pre></div>
<a id="trunkJSTestsstressargumentsbizarrebehaviourdisableenumerabilityjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/arguments-bizarre-behaviour-disable-enumerability.js (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arguments-bizarre-behaviour-disable-enumerability.js        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/JSTests/stress/arguments-bizarre-behaviour-disable-enumerability.js        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -24,7 +24,5 @@
</span><span class="cx"> if (Object.keys(result[2]).join(&quot;,&quot;) != &quot;0&quot;)
</span><span class="cx">     throw new Error();
</span><span class="cx"> 
</span><del>-// FIXME: This is totally weird!
-// https://bugs.webkit.org/show_bug.cgi?id=141952
-if (Object.getOwnPropertyDescriptor(result[2], 0).enumerable !== true)
</del><ins>+if (Object.getOwnPropertyDescriptor(result[2], 0).enumerable === true)
</ins><span class="cx">     throw new Error();
</span></span></pre></div>
<a id="trunkJSTestsstressargumentsdefinepropertyjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/arguments-define-property.js (0 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arguments-define-property.js                                (rev 0)
+++ trunk/JSTests/stress/arguments-define-property.js        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+function assert(a) {
+    if (!a)
+        throw Error(&quot;Bad assertion!&quot;);
+}
+
+function testProperties(o, initProperty, testProperty, shouldThrow) {
+    Object.defineProperty(arguments, 0, initProperty);
+
+    if (shouldThrow) {
+        try {
+            Object.defineProperty(arguments, 0, testProperty);
+            assert(false);
+        } catch(e) {
+            assert(e instanceof TypeError);
+        }
+    } else {
+        assert(Object.defineProperty(arguments, 0, testProperty));
+    }
+}
+
+testProperties(&quot;foo&quot;, {configurable: false}, {writable: true}, false);
+testProperties(&quot;foo&quot;, {configurable: false}, {configurable: true}, true);
+testProperties(&quot;foo&quot;, {configurable: false, enumareble: true}, {enumerable: false}, true);
+testProperties(&quot;foo&quot;, {configurable: false, writable: false}, {writable: false}, false);
+testProperties(&quot;foo&quot;, {configurable: false, writable: false}, {writable: true}, true);
+testProperties(&quot;foo&quot;, {configurable: false, writable: false, value: 50}, {value: 30}, true);
+testProperties(&quot;foo&quot;, {configurable: false, writable: false, value: 30}, {value: 30}, false);
+testProperties(&quot;foo&quot;, {configurable: false, get: () =&gt; {return 0}}, {get: () =&gt; {return 10}}, true);
+let getterFoo = () =&gt; {return 0};
+testProperties(&quot;foo&quot;, {configurable: false, get: getterFoo}, {get: getterFoo}, false);
+testProperties(&quot;foo&quot;, {configurable: false, set: (x) =&gt; {return 0}}, {get: (x) =&gt; {return 10}}, true);
+let setterFoo = (x) =&gt; {return 0};
+testProperties(&quot;foo&quot;, {configurable: false, set: setterFoo}, {set: setterFoo}, false);
+
</ins></span></pre></div>
<a id="trunkJSTestsstressargumentsnonconfigurablejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/arguments-non-configurable.js (0 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arguments-non-configurable.js                                (rev 0)
+++ trunk/JSTests/stress/arguments-non-configurable.js        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+function assert(a) {
+    if (!a)
+        throw Error(&quot;Bad assertion!&quot;);
+}
+
+function tryChangeNonConfigurableDescriptor(x) {
+    Object.defineProperty(arguments, 0, {configurable: false});
+    try {
+        Object.defineProperty(arguments, 0, x);
+        assert(false);
+    } catch(e) {
+        assert(e instanceof TypeError);
+    }
+}
+
+tryChangeNonConfigurableDescriptor({get: () =&gt; {return 50;} });
+tryChangeNonConfigurableDescriptor({set: (x) =&gt; {}});
+tryChangeNonConfigurableDescriptor({writable: true, enumerable: false});
+
+function tryChangeWritableOfNonConfigurableDescriptor(x) {
+    Object.defineProperty(arguments, 0, {configurable: false});
+    Object.defineProperty(arguments, 0, {writable: true});
+    assert(Object.defineProperty(arguments, 0, {writable: false}));
+}
+
+tryChangeWritableOfNonConfigurableDescriptor(&quot;foo&quot;);
+
</ins></span></pre></div>
<a id="trunkJSTeststest262yaml"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/test262.yaml (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/test262.yaml        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/JSTests/test262.yaml        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -51364,37 +51364,37 @@
</span><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-1.js
</span><span class="cx">   cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</span><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-2.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-3.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-4.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-1.js
</span><span class="cx">   cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</span><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-2.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-3.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-4.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-1.js
</span><span class="cx">   cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</span><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-2.js
</span><span class="cx">   cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</span><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-3.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-4.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-5.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-1.js
</span><span class="cx">   cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</span><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-2.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-3.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-4.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonwritable-nonconfigurable-1.js
</span><span class="cx">   cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../harness/assert.js&quot;, &quot;../../../../harness/sta.js&quot;], []
</span><span class="cx"> - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonwritable-nonconfigurable-2.js
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -1,3 +1,116 @@
</span><ins>+2016-12-24  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [test262] Fixing mapped arguments object property test case
+        https://bugs.webkit.org/show_bug.cgi?id=159398
+
+        Reviewed by Saam Barati.
+
+        This patch changes GenericArguments' override mechanism to
+        implement corret behavior on ECMAScript test262 suite test cases of
+        mapped arguments object with non-configurable and non-writable
+        property. Also it is ensuring that arguments[i]
+        cannot be deleted when argument &quot;i&quot; is {configurable: false}.
+        
+        The previous implementation is against to the specification for 2 reasons:
+
+        1. Every argument in arguments object are {writable: true} by default
+           (http://www.ecma-international.org/ecma-262/7.0/index.html#sec-createunmappedargumentsobject).
+           It means that we have to stop mapping a defined property index
+           if the new property descriptor contains writable (i.e writable is
+           present) and its value is false (also check
+           https://tc39.github.io/ecma262/#sec-arguments-exotic-objects-defineownproperty-p-desc).
+           Previous implementation considers {writable: false} if writable is
+           not present.
+
+        2. When a property is overriden, &quot;delete&quot; operation is always returning true. However
+           delete operations should follow the specification.
+
+        We created an auxilary boolean array named m_modifiedArgumentsDescriptor
+        to store which arguments[i] descriptor was changed from its default
+        property descriptor. This modification was necessary because m_overrides
+        was responsible to keep this information at the same time
+        of keeping information about arguments mapping. The problem of this apporach was
+        that we needed to call overridesArgument(i) as soon as the ith argument's property
+        descriptor was changed and it stops the argument's mapping as sideffect, producing
+        wrong behavior.
+        To keep tracking arguments mapping status, we renamed DirectArguments::m_overrides to
+        DirectArguments::m_mappedArguments and now we it is responsible to manage if an
+        argument[i] is mapped or not.
+        With these 2 structures, now it is possible to an argument[i] have its property 
+        descriptor modified and don't stop the mapping as soon as it happens. One example
+        of that wrong behavior can be found on arguments-bizarre-behaviour-disable-enumerability
+        test case, that now is fixed by this new mechanism.
+
+        * bytecode/PolymorphicAccess.cpp:
+        (JSC::AccessCase::generateWithGuard):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments):
+        (JSC::DFG::SpeculativeJIT::compileGetArrayLength):
+        (JSC::DFG::SpeculativeJIT::compileCreateDirectArguments):
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength):
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateDirectArguments):
+        * jit/JITOperations.cpp:
+        (JSC::canAccessArgumentIndexQuickly):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emitDirectArgumentsGetByVal):
+        * runtime/DirectArguments.cpp:
+        (JSC::DirectArguments::estimatedSize):
+        (JSC::DirectArguments::visitChildren):
+        (JSC::DirectArguments::overrideThings):
+        (JSC::DirectArguments::overrideThingsIfNecessary):
+        (JSC::DirectArguments::unmapArgument):
+        (JSC::DirectArguments::copyToArguments):
+        (JSC::DirectArguments::overridesSize):
+        (JSC::DirectArguments::overrideArgument): Deleted.
+        * runtime/DirectArguments.h:
+        (JSC::DirectArguments::length):
+        (JSC::DirectArguments::isMappedArgument):
+        (JSC::DirectArguments::isMappedArgumentInDFG):
+        (JSC::DirectArguments::getIndexQuickly):
+        (JSC::DirectArguments::setIndexQuickly):
+        (JSC::DirectArguments::overrodeThings):
+        (JSC::DirectArguments::initModifiedArgumentsDescriptorIfNecessary):
+        (JSC::DirectArguments::setModifiedArgumentDescriptor):
+        (JSC::DirectArguments::isModifiedArgumentDescriptor):
+        (JSC::DirectArguments::offsetOfMappedArguments):
+        (JSC::DirectArguments::offsetOfModifiedArgumentsDescriptor):
+        (JSC::DirectArguments::canAccessIndexQuickly): Deleted.
+        (JSC::DirectArguments::canAccessArgumentIndexQuicklyInDFG): Deleted.
+        (JSC::DirectArguments::offsetOfOverrides): Deleted.
+        * runtime/GenericArguments.h:
+        * runtime/GenericArgumentsInlines.h:
+        (JSC::GenericArguments&lt;Type&gt;::visitChildren):
+        (JSC::GenericArguments&lt;Type&gt;::getOwnPropertySlot):
+        (JSC::GenericArguments&lt;Type&gt;::getOwnPropertySlotByIndex):
+        (JSC::GenericArguments&lt;Type&gt;::getOwnPropertyNames):
+        (JSC::GenericArguments&lt;Type&gt;::put):
+        (JSC::GenericArguments&lt;Type&gt;::putByIndex):
+        (JSC::GenericArguments&lt;Type&gt;::deleteProperty):
+        (JSC::GenericArguments&lt;Type&gt;::deletePropertyByIndex):
+        (JSC::GenericArguments&lt;Type&gt;::defineOwnProperty):
+        (JSC::GenericArguments&lt;Type&gt;::initModifiedArgumentsDescriptor):
+        (JSC::GenericArguments&lt;Type&gt;::initModifiedArgumentsDescriptorIfNecessary):
+        (JSC::GenericArguments&lt;Type&gt;::setModifiedArgumentDescriptor):
+        (JSC::GenericArguments&lt;Type&gt;::isModifiedArgumentDescriptor):
+        (JSC::GenericArguments&lt;Type&gt;::copyToArguments):
+        * runtime/ScopedArguments.cpp:
+        (JSC::ScopedArguments::visitChildren):
+        (JSC::ScopedArguments::unmapArgument):
+        (JSC::ScopedArguments::overrideArgument): Deleted.
+        * runtime/ScopedArguments.h:
+        (JSC::ScopedArguments::isMappedArgument):
+        (JSC::ScopedArguments::isMappedArgumentInDFG):
+        (JSC::ScopedArguments::getIndexQuickly):
+        (JSC::ScopedArguments::setIndexQuickly):
+        (JSC::ScopedArguments::initModifiedArgumentsDescriptorIfNecessary):
+        (JSC::ScopedArguments::setModifiedArgumentDescriptor):
+        (JSC::ScopedArguments::isModifiedArgumentDescriptor):
+        (JSC::ScopedArguments::canAccessIndexQuickly): Deleted.
+        (JSC::ScopedArguments::canAccessArgumentIndexQuicklyInDFG): Deleted.
+
</ins><span class="cx"> 2016-12-23  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Using Option::breakOnThrow() shouldn't crash while printing a null CodeBlock.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -638,7 +638,7 @@
</span><span class="cx">         fallThrough.append(
</span><span class="cx">             jit.branchTestPtr(
</span><span class="cx">                 CCallHelpers::NonZero,
</span><del>-                CCallHelpers::Address(baseGPR, DirectArguments::offsetOfOverrides())));
</del><ins>+                CCallHelpers::Address(baseGPR, DirectArguments::offsetOfMappedArguments())));
</ins><span class="cx">         jit.load32(
</span><span class="cx">             CCallHelpers::Address(baseGPR, DirectArguments::offsetOfLength()),
</span><span class="cx">             valueRegs.payloadGPR());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -6118,7 +6118,7 @@
</span><span class="cx">         ExoticObjectMode, JSValueSource(), 0,
</span><span class="cx">         m_jit.branchTestPtr(
</span><span class="cx">             MacroAssembler::NonZero,
</span><del>-            MacroAssembler::Address(baseReg, DirectArguments::offsetOfOverrides())));
</del><ins>+            MacroAssembler::Address(baseReg, DirectArguments::offsetOfMappedArguments())));
</ins><span class="cx">     speculationCheck(
</span><span class="cx">         ExoticObjectMode, JSValueSource(), 0,
</span><span class="cx">         m_jit.branch32(
</span><span class="lines">@@ -6292,7 +6292,7 @@
</span><span class="cx">             ExoticObjectMode, JSValueSource(), 0,
</span><span class="cx">             m_jit.branchTestPtr(
</span><span class="cx">                 MacroAssembler::NonZero,
</span><del>-                MacroAssembler::Address(baseReg, DirectArguments::offsetOfOverrides())));
</del><ins>+                MacroAssembler::Address(baseReg, DirectArguments::offsetOfMappedArguments())));
</ins><span class="cx">         
</span><span class="cx">         m_jit.load32(
</span><span class="cx">             MacroAssembler::Address(baseReg, DirectArguments::offsetOfLength()), resultReg);
</span><span class="lines">@@ -6658,7 +6658,10 @@
</span><span class="cx">         JITCompiler::Address(resultGPR, DirectArguments::offsetOfMinCapacity()));
</span><span class="cx">         
</span><span class="cx">     m_jit.storePtr(
</span><del>-        TrustedImmPtr(0), JITCompiler::Address(resultGPR, DirectArguments::offsetOfOverrides()));
</del><ins>+        TrustedImmPtr(0), JITCompiler::Address(resultGPR, DirectArguments::offsetOfMappedArguments()));
+
+    m_jit.storePtr(
+        TrustedImmPtr(0), JITCompiler::Address(resultGPR, DirectArguments::offsetOfModifiedArgumentsDescriptor()));
</ins><span class="cx">     
</span><span class="cx">     if (lengthIsKnown) {
</span><span class="cx">         addSlowPathGenerator(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -51,7 +51,8 @@
</span><span class="cx">     macro(DirectArguments_callee, DirectArguments::offsetOfCallee()) \
</span><span class="cx">     macro(DirectArguments_length, DirectArguments::offsetOfLength()) \
</span><span class="cx">     macro(DirectArguments_minCapacity, DirectArguments::offsetOfMinCapacity()) \
</span><del>-    macro(DirectArguments_overrides, DirectArguments::offsetOfOverrides()) \
</del><ins>+    macro(DirectArguments_mappedArguments, DirectArguments::offsetOfMappedArguments()) \
+    macro(DirectArguments_modifiedArgumentsDescriptor, DirectArguments::offsetOfModifiedArgumentsDescriptor()) \
</ins><span class="cx">     macro(GetterSetter_getter, GetterSetter::offsetOfGetter()) \
</span><span class="cx">     macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \
</span><span class="cx">     macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -3140,7 +3140,7 @@
</span><span class="cx">             LValue arguments = lowCell(m_node-&gt;child1());
</span><span class="cx">             speculate(
</span><span class="cx">                 ExoticObjectMode, noValue(), nullptr,
</span><del>-                m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_overrides)));
</del><ins>+                m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_mappedArguments)));
</ins><span class="cx">             setInt32(m_out.load32NonNegative(arguments, m_heaps.DirectArguments_length));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -3292,7 +3292,7 @@
</span><span class="cx">             
</span><span class="cx">             speculate(
</span><span class="cx">                 ExoticObjectMode, noValue(), nullptr,
</span><del>-                m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_overrides)));
</del><ins>+                m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_mappedArguments)));
</ins><span class="cx">             speculate(
</span><span class="cx">                 ExoticObjectMode, noValue(), nullptr,
</span><span class="cx">                 m_out.aboveOrEqual(
</span><span class="lines">@@ -4088,7 +4088,8 @@
</span><span class="cx">         
</span><span class="cx">         m_out.store32(length.value, fastObject, m_heaps.DirectArguments_length);
</span><span class="cx">         m_out.store32(m_out.constInt32(minCapacity), fastObject, m_heaps.DirectArguments_minCapacity);
</span><del>-        m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_overrides);
</del><ins>+        m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_mappedArguments);
+        m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_modifiedArgumentsDescriptor);
</ins><span class="cx">         
</span><span class="cx">         ValueFromBlock fastResult = m_out.anchor(fastObject);
</span><span class="cx">         m_out.jump(continuation);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -1620,13 +1620,13 @@
</span><span class="cx">     switch (object.structure()-&gt;typeInfo().type()) {
</span><span class="cx">     case DirectArgumentsType: {
</span><span class="cx">         DirectArguments* directArguments = jsCast&lt;DirectArguments*&gt;(&amp;object);
</span><del>-        if (directArguments-&gt;canAccessArgumentIndexQuicklyInDFG(index))
</del><ins>+        if (directArguments-&gt;isMappedArgumentInDFG(index))
</ins><span class="cx">             return true;
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     case ScopedArgumentsType: {
</span><span class="cx">         ScopedArguments* scopedArguments = jsCast&lt;ScopedArguments*&gt;(&amp;object);
</span><del>-        if (scopedArguments-&gt;canAccessArgumentIndexQuicklyInDFG(index))
</del><ins>+        if (scopedArguments-&gt;isMappedArgumentInDFG(index))
</ins><span class="cx">             return true;
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -1458,7 +1458,7 @@
</span><span class="cx">     badType = patchableBranch32(NotEqual, scratch, TrustedImm32(DirectArgumentsType));
</span><span class="cx">     
</span><span class="cx">     slowCases.append(branch32(AboveOrEqual, property, Address(base, DirectArguments::offsetOfLength())));
</span><del>-    slowCases.append(branchTestPtr(NonZero, Address(base, DirectArguments::offsetOfOverrides())));
</del><ins>+    slowCases.append(branchTestPtr(NonZero, Address(base, DirectArguments::offsetOfMappedArguments())));
</ins><span class="cx">     
</span><span class="cx">     zeroExtend32ToPtr(property, scratch);
</span><span class="cx">     loadValue(BaseIndex(base, scratch, TimesEight, DirectArguments::storageOffset()), result);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeDirectArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -86,8 +86,9 @@
</span><span class="cx"> size_t DirectArguments::estimatedSize(JSCell* cell)
</span><span class="cx"> {
</span><span class="cx">     DirectArguments* thisObject = jsCast&lt;DirectArguments*&gt;(cell);
</span><del>-    size_t overridesSize = thisObject-&gt;m_overrides ? thisObject-&gt;overridesSize() : 0;
-    return Base::estimatedSize(cell) + overridesSize;
</del><ins>+    size_t mappedArgumentsSize = thisObject-&gt;m_mappedArguments ? thisObject-&gt;mappedArgumentsSize() * sizeof(bool) : 0;
+    size_t modifiedArgumentsSize = thisObject-&gt;m_modifiedArgumentsDescriptor ? thisObject-&gt;m_length * sizeof(bool) : 0;
+    return Base::estimatedSize(cell) + mappedArgumentsSize + modifiedArgumentsSize;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void DirectArguments::visitChildren(JSCell* thisCell, SlotVisitor&amp; visitor)
</span><span class="lines">@@ -95,12 +96,13 @@
</span><span class="cx">     DirectArguments* thisObject = static_cast&lt;DirectArguments*&gt;(thisCell);
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><del>-    
</del><ins>+
</ins><span class="cx">     visitor.appendValues(thisObject-&gt;storage(), std::max(thisObject-&gt;m_length, thisObject-&gt;m_minCapacity));
</span><span class="cx">     visitor.append(thisObject-&gt;m_callee);
</span><span class="cx"> 
</span><del>-    if (bool* override = thisObject-&gt;m_overrides.get())
-        visitor.markAuxiliary(override);
</del><ins>+    if (thisObject-&gt;m_mappedArguments)
+        visitor.markAuxiliary(thisObject-&gt;m_mappedArguments.get());
+    GenericArguments&lt;DirectArguments&gt;::visitChildren(thisCell, visitor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Structure* DirectArguments::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span><span class="lines">@@ -110,16 +112,16 @@
</span><span class="cx"> 
</span><span class="cx"> void DirectArguments::overrideThings(VM&amp; vm)
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(!m_overrides);
</del><ins>+    RELEASE_ASSERT(!m_mappedArguments);
</ins><span class="cx">     
</span><span class="cx">     putDirect(vm, vm.propertyNames-&gt;length, jsNumber(m_length), DontEnum);
</span><span class="cx">     putDirect(vm, vm.propertyNames-&gt;callee, m_callee.get(), DontEnum);
</span><span class="cx">     putDirect(vm, vm.propertyNames-&gt;iteratorSymbol, globalObject()-&gt;arrayProtoValuesFunction(), DontEnum);
</span><span class="cx">     
</span><del>-    void* backingStore = vm.heap.tryAllocateAuxiliary(this, overridesSize());
</del><ins>+    void* backingStore = vm.heap.tryAllocateAuxiliary(this, mappedArgumentsSize());
</ins><span class="cx">     RELEASE_ASSERT(backingStore);
</span><span class="cx">     bool* overrides = static_cast&lt;bool*&gt;(backingStore);
</span><del>-    m_overrides.set(vm, this, overrides);
</del><ins>+    m_mappedArguments.set(vm, this, overrides);
</ins><span class="cx">     for (unsigned i = m_length; i--;)
</span><span class="cx">         overrides[i] = false;
</span><span class="cx"> }
</span><span class="lines">@@ -126,19 +128,19 @@
</span><span class="cx"> 
</span><span class="cx"> void DirectArguments::overrideThingsIfNecessary(VM&amp; vm)
</span><span class="cx"> {
</span><del>-    if (!m_overrides)
</del><ins>+    if (!m_mappedArguments)
</ins><span class="cx">         overrideThings(vm);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void DirectArguments::overrideArgument(VM&amp; vm, unsigned index)
</del><ins>+void DirectArguments::unmapArgument(VM&amp; vm, unsigned index)
</ins><span class="cx"> {
</span><span class="cx">     overrideThingsIfNecessary(vm);
</span><del>-    m_overrides.get()[index] = true;
</del><ins>+    m_mappedArguments.get()[index] = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void DirectArguments::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length)
</span><span class="cx"> {
</span><del>-    if (!m_overrides) {
</del><ins>+    if (!m_mappedArguments) {
</ins><span class="cx">         unsigned limit = std::min(length + offset, m_length);
</span><span class="cx">         unsigned i;
</span><span class="cx">         VirtualRegister start = firstElementDest - offset;
</span><span class="lines">@@ -152,10 +154,10 @@
</span><span class="cx">     GenericArguments::copyToArguments(exec, firstElementDest, offset, length);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-unsigned DirectArguments::overridesSize()
</del><ins>+unsigned DirectArguments::mappedArgumentsSize()
</ins><span class="cx"> {
</span><span class="cx">     // We always allocate something; in the relatively uncommon case of overriding an empty argument we
</span><del>-    // still allocate so that m_overrides is non-null. We use that to indicate that the other properties
</del><ins>+    // still allocate so that m_mappedArguments is non-null. We use that to indicate that the other properties
</ins><span class="cx">     // (length, etc) are overridden.
</span><span class="cx">     return WTF::roundUpToMultipleOf&lt;8&gt;(m_length ? m_length : 1);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeDirectArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/DirectArguments.h (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/DirectArguments.h        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/runtime/DirectArguments.h        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -66,17 +66,17 @@
</span><span class="cx">     
</span><span class="cx">     uint32_t length(ExecState* exec) const
</span><span class="cx">     {
</span><del>-        if (UNLIKELY(m_overrides))
</del><ins>+        if (UNLIKELY(m_mappedArguments))
</ins><span class="cx">             return get(exec, exec-&gt;propertyNames().length).toUInt32(exec);
</span><span class="cx">         return m_length;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool canAccessIndexQuickly(uint32_t i) const
</del><ins>+    bool isMappedArgument(uint32_t i) const
</ins><span class="cx">     {
</span><del>-        return i &lt; m_length &amp;&amp; (!m_overrides || !m_overrides.get()[i]);
</del><ins>+        return i &lt; m_length &amp;&amp; (!m_mappedArguments || !m_mappedArguments.get()[i]);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool canAccessArgumentIndexQuicklyInDFG(uint32_t i) const
</del><ins>+    bool isMappedArgumentInDFG(uint32_t i) const
</ins><span class="cx">     {
</span><span class="cx">         return i &lt; m_length &amp;&amp; !overrodeThings();
</span><span class="cx">     }
</span><span class="lines">@@ -83,13 +83,13 @@
</span><span class="cx"> 
</span><span class="cx">     JSValue getIndexQuickly(uint32_t i) const
</span><span class="cx">     {
</span><del>-        ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
</del><ins>+        ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
</ins><span class="cx">         return const_cast&lt;DirectArguments*&gt;(this)-&gt;storage()[i].get();
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void setIndexQuickly(VM&amp; vm, uint32_t i, JSValue value)
</span><span class="cx">     {
</span><del>-        ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
</del><ins>+        ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
</ins><span class="cx">         storage()[i].set(vm, this, value);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -106,11 +106,26 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Methods intended for use by the GenericArguments mixin.
</span><del>-    bool overrodeThings() const { return !!m_overrides; }
</del><ins>+    bool overrodeThings() const { return !!m_mappedArguments; }
</ins><span class="cx">     void overrideThings(VM&amp;);
</span><span class="cx">     void overrideThingsIfNecessary(VM&amp;);
</span><del>-    void overrideArgument(VM&amp;, unsigned index);
-    
</del><ins>+    void unmapArgument(VM&amp;, unsigned index);
+
+    void initModifiedArgumentsDescriptorIfNecessary(VM&amp; vm)
+    {
+        GenericArguments&lt;DirectArguments&gt;::initModifiedArgumentsDescriptorIfNecessary(vm, m_length);
+    }
+
+    void setModifiedArgumentDescriptor(VM&amp; vm, unsigned index)
+    {
+        GenericArguments&lt;DirectArguments&gt;::setModifiedArgumentDescriptor(vm, index, m_length);
+    }
+
+    bool isModifiedArgumentDescriptor(unsigned index)
+    {
+        return GenericArguments&lt;DirectArguments&gt;::isModifiedArgumentDescriptor(index, m_length);
+    }
+
</ins><span class="cx">     void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="lines">@@ -120,7 +135,8 @@
</span><span class="cx">     static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(DirectArguments, m_callee); }
</span><span class="cx">     static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(DirectArguments, m_length); }
</span><span class="cx">     static ptrdiff_t offsetOfMinCapacity() { return OBJECT_OFFSETOF(DirectArguments, m_minCapacity); }
</span><del>-    static ptrdiff_t offsetOfOverrides() { return OBJECT_OFFSETOF(DirectArguments, m_overrides); }
</del><ins>+    static ptrdiff_t offsetOfMappedArguments() { return OBJECT_OFFSETOF(DirectArguments, m_mappedArguments); }
+    static ptrdiff_t offsetOfModifiedArgumentsDescriptor() { return OBJECT_OFFSETOF(DirectArguments, m_modifiedArgumentsDescriptor); }
</ins><span class="cx">     
</span><span class="cx">     static size_t storageOffset()
</span><span class="cx">     {
</span><span class="lines">@@ -143,12 +159,12 @@
</span><span class="cx">         return bitwise_cast&lt;WriteBarrier&lt;Unknown&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + storageOffset());
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    unsigned overridesSize();
</del><ins>+    unsigned mappedArgumentsSize();
</ins><span class="cx">     
</span><span class="cx">     WriteBarrier&lt;JSFunction&gt; m_callee;
</span><span class="cx">     uint32_t m_length; // Always the actual length of captured arguments and never what was stored into the length property.
</span><span class="cx">     uint32_t m_minCapacity; // The max of this and length determines the capacity of this object. It may be the actual capacity, or maybe something smaller. We arrange it this way to be kind to the JITs.
</span><del>-    AuxiliaryBarrier&lt;bool*&gt; m_overrides; // If non-null, it means that length, callee, and caller are fully materialized properties.
</del><ins>+    AuxiliaryBarrier&lt;bool*&gt; m_mappedArguments; // If non-null, it means that length, callee, and caller are fully materialized properties.
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeGenericArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/GenericArguments.h (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/GenericArguments.h        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/runtime/GenericArguments.h        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static void visitChildren(JSCell*, SlotVisitor&amp;);
</ins><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">@@ -52,7 +53,14 @@
</span><span class="cx">     static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
</span><span class="cx">     static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&amp;, bool shouldThrow);
</span><span class="cx">     
</span><ins>+    void initModifiedArgumentsDescriptor(VM&amp;, unsigned length);
+    void initModifiedArgumentsDescriptorIfNecessary(VM&amp;, unsigned length);
+    void setModifiedArgumentDescriptor(VM&amp;, unsigned index, unsigned length);
+    bool isModifiedArgumentDescriptor(unsigned index, unsigned length);
+
</ins><span class="cx">     void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
</span><ins>+    
+    AuxiliaryBarrier&lt;bool*&gt; m_modifiedArgumentsDescriptor;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeGenericArgumentsInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -31,6 +31,16 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Type&gt;
</span><ins>+void GenericArguments&lt;Type&gt;::visitChildren(JSCell* thisCell, SlotVisitor&amp; visitor)
+{
+    Type* thisObject = static_cast&lt;Type*&gt;(thisCell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    
+    if (thisObject-&gt;m_modifiedArgumentsDescriptor)
+        visitor.markAuxiliary(thisObject-&gt;m_modifiedArgumentsDescriptor.get());
+}
+
+template&lt;typename Type&gt;
</ins><span class="cx"> bool GenericArguments&lt;Type&gt;::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot&amp; slot)
</span><span class="cx"> {
</span><span class="cx">     Type* thisObject = jsCast&lt;Type*&gt;(object);
</span><span class="lines">@@ -52,12 +62,17 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     std::optional&lt;uint32_t&gt; index = parseIndex(ident);
</span><del>-    if (index &amp;&amp; thisObject-&gt;canAccessIndexQuickly(index.value())) {
</del><ins>+    if (index &amp;&amp; !thisObject-&gt;isModifiedArgumentDescriptor(index.value()) &amp;&amp; thisObject-&gt;isMappedArgument(index.value())) {
</ins><span class="cx">         slot.setValue(thisObject, None, thisObject-&gt;getIndexQuickly(index.value()));
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    return Base::getOwnPropertySlot(thisObject, exec, ident, slot);
</del><ins>+    bool result = Base::getOwnPropertySlot(thisObject, exec, ident, slot);
+    
+    if (index &amp;&amp; thisObject-&gt;isMappedArgument(index.value()))
+        slot.setValue(thisObject, slot.attributes(), thisObject-&gt;getIndexQuickly(index.value()));
+    
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Type&gt;
</span><span class="lines">@@ -65,13 +80,16 @@
</span><span class="cx"> {
</span><span class="cx">     Type* thisObject = jsCast&lt;Type*&gt;(object);
</span><span class="cx">     
</span><del>-    if (thisObject-&gt;canAccessIndexQuickly(index)) {
-        JSValue result = thisObject-&gt;getIndexQuickly(index);
-        slot.setValue(thisObject, None, result);
</del><ins>+    if (!thisObject-&gt;isModifiedArgumentDescriptor(index) &amp;&amp; thisObject-&gt;isMappedArgument(index)) {
+        slot.setValue(thisObject, None, thisObject-&gt;getIndexQuickly(index));
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     bool result = Base::getOwnPropertySlotByIndex(object, exec, index, slot);
</span><ins>+    
+    if (thisObject-&gt;isMappedArgument(index))
+        slot.setValue(thisObject, slot.attributes(), thisObject-&gt;getIndexQuickly(index));
+    
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -82,7 +100,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (array.includeStringProperties()) {
</span><span class="cx">         for (unsigned i = 0; i &lt; thisObject-&gt;internalLength(); ++i) {
</span><del>-            if (!thisObject-&gt;canAccessIndexQuickly(i))
</del><ins>+            if (!thisObject-&gt;isMappedArgument(i))
</ins><span class="cx">                 continue;
</span><span class="cx">             array.add(Identifier::from(exec, i));
</span><span class="cx">         }
</span><span class="lines">@@ -118,7 +136,7 @@
</span><span class="cx">         return ordinarySetSlow(exec, thisObject, ident, value, slot.thisValue(), slot.isStrictMode());
</span><span class="cx">     
</span><span class="cx">     std::optional&lt;uint32_t&gt; index = parseIndex(ident);
</span><del>-    if (index &amp;&amp; thisObject-&gt;canAccessIndexQuickly(index.value())) {
</del><ins>+    if (index &amp;&amp; thisObject-&gt;isMappedArgument(index.value())) {
</ins><span class="cx">         thisObject-&gt;setIndexQuickly(vm, index.value(), value);
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="lines">@@ -131,8 +149,8 @@
</span><span class="cx"> {
</span><span class="cx">     Type* thisObject = jsCast&lt;Type*&gt;(cell);
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><del>-    
-    if (thisObject-&gt;canAccessIndexQuickly(index)) {
</del><ins>+
+    if (thisObject-&gt;isMappedArgument(index)) {
</ins><span class="cx">         thisObject-&gt;setIndexQuickly(vm, index, value);
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="lines">@@ -153,8 +171,9 @@
</span><span class="cx">         thisObject-&gt;overrideThings(vm);
</span><span class="cx">     
</span><span class="cx">     std::optional&lt;uint32_t&gt; index = parseIndex(ident);
</span><del>-    if (index &amp;&amp; thisObject-&gt;canAccessIndexQuickly(index.value())) {
-        thisObject-&gt;overrideArgument(vm, index.value());
</del><ins>+    if (index &amp;&amp; !thisObject-&gt;isModifiedArgumentDescriptor(index.value()) &amp;&amp; thisObject-&gt;isMappedArgument(index.value())) {
+        thisObject-&gt;unmapArgument(vm, index.value());
+        thisObject-&gt;setModifiedArgumentDescriptor(vm, index.value());
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -166,12 +185,13 @@
</span><span class="cx"> {
</span><span class="cx">     Type* thisObject = jsCast&lt;Type*&gt;(cell);
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><del>-    
-    if (thisObject-&gt;canAccessIndexQuickly(index)) {
-        thisObject-&gt;overrideArgument(vm, index);
</del><ins>+
+    if (!thisObject-&gt;isModifiedArgumentDescriptor(index) &amp;&amp; thisObject-&gt;isMappedArgument(index)) {
+        thisObject-&gt;unmapArgument(vm, index);
+        thisObject-&gt;setModifiedArgumentDescriptor(vm, index);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     return Base::deletePropertyByIndex(cell, exec, index);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -187,37 +207,93 @@
</span><span class="cx">         thisObject-&gt;overrideThingsIfNecessary(vm);
</span><span class="cx">     else {
</span><span class="cx">         std::optional&lt;uint32_t&gt; optionalIndex = parseIndex(ident);
</span><del>-        if (optionalIndex &amp;&amp; thisObject-&gt;canAccessIndexQuickly(optionalIndex.value())) {
</del><ins>+        if (optionalIndex) {
</ins><span class="cx">             uint32_t index = optionalIndex.value();
</span><del>-            if (!descriptor.isAccessorDescriptor()) {
</del><ins>+            if (!descriptor.isAccessorDescriptor() &amp;&amp; thisObject-&gt;isMappedArgument(optionalIndex.value())) {
</ins><span class="cx">                 // If the property is not deleted and we are using a non-accessor descriptor, then
</span><span class="cx">                 // make sure that the aliased argument sees the value.
</span><span class="cx">                 if (descriptor.value())
</span><span class="cx">                     thisObject-&gt;setIndexQuickly(vm, index, descriptor.value());
</span><span class="cx">             
</span><del>-                // If the property is not deleted and we are using a non-accessor, writable
-                // descriptor, then we are done. The argument continues to be aliased. Note that we
-                // ignore the request to change enumerability. We appear to have always done so, in
-                // cases where the argument was still aliased.
-                // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141952
-                if (descriptor.writable())
</del><ins>+                // If the property is not deleted and we are using a non-accessor, writable,
+                // configurable and enumerable descriptor and isn't modified, then we are done.
+                // The argument continues to be aliased.
+                if (descriptor.writable() &amp;&amp; descriptor.configurable() &amp;&amp; descriptor.enumerable() &amp;&amp; !thisObject-&gt;isModifiedArgumentDescriptor(index))
</ins><span class="cx">                     return true;
</span><ins>+                
+                if (!thisObject-&gt;isModifiedArgumentDescriptor(index)) {
+                    // If it is a new entry, we need to put direct to initialize argument[i] descriptor properly
+                    JSValue value = thisObject-&gt;getIndexQuickly(index);
+                    ASSERT(value);
+                    object-&gt;putDirectMayBeIndex(exec, ident, value);
+                    
+                    thisObject-&gt;setModifiedArgumentDescriptor(vm, index);
+                }
</ins><span class="cx">             }
</span><del>-        
-            // If the property is a non-deleted argument, then move it into the base object and
-            // then delete it.
-            JSValue value = thisObject-&gt;getIndexQuickly(index);
-            ASSERT(value);
-            object-&gt;putDirectMayBeIndex(exec, ident, value);
-            thisObject-&gt;overrideArgument(vm, index);
</del><ins>+            
+            if (thisObject-&gt;isMappedArgument(index)) {
+                // Just unmap arguments if its descriptor contains {writable: false}.
+                // Check https://tc39.github.io/ecma262/#sec-createunmappedargumentsobject
+                // and https://tc39.github.io/ecma262/#sec-createmappedargumentsobject to verify that all data
+                // property from arguments object are {writable: true, configurable: true, enumerable: true} by default
+                if ((descriptor.writablePresent() &amp;&amp; !descriptor.writable()) || descriptor.isAccessorDescriptor()) {
+                    if (!descriptor.isAccessorDescriptor()) {
+                        JSValue value = thisObject-&gt;getIndexQuickly(index);
+                        ASSERT(value);
+                        object-&gt;putDirectMayBeIndex(exec, ident, value);
+                    }
+                    thisObject-&gt;unmapArgument(vm, index);
+                    thisObject-&gt;setModifiedArgumentDescriptor(vm, index);
+                }
+            }
</ins><span class="cx">         }
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     // Now just let the normal object machinery do its thing.
</span><span class="cx">     return Base::defineOwnProperty(object, exec, ident, descriptor, shouldThrow);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Type&gt;
</span><ins>+void GenericArguments&lt;Type&gt;::initModifiedArgumentsDescriptor(VM&amp; vm, unsigned argsLength)
+{
+    RELEASE_ASSERT(!m_modifiedArgumentsDescriptor);
+
+    if (argsLength) {
+        void* backingStore = vm.heap.tryAllocateAuxiliary(this, WTF::roundUpToMultipleOf&lt;8&gt;(argsLength));
+        RELEASE_ASSERT(backingStore);
+        bool* modifiedArguments = static_cast&lt;bool*&gt;(backingStore);
+        m_modifiedArgumentsDescriptor.set(vm, this, modifiedArguments);
+        for (unsigned i = argsLength; i--;)
+            modifiedArguments[i] = false;
+    }
+}
+
+template&lt;typename Type&gt;
+void GenericArguments&lt;Type&gt;::initModifiedArgumentsDescriptorIfNecessary(VM&amp; vm, unsigned argsLength)
+{
+    if (!m_modifiedArgumentsDescriptor)
+        initModifiedArgumentsDescriptor(vm, argsLength);
+}
+
+template&lt;typename Type&gt;
+void GenericArguments&lt;Type&gt;::setModifiedArgumentDescriptor(VM&amp; vm, unsigned index, unsigned length)
+{
+    initModifiedArgumentsDescriptorIfNecessary(vm, length);
+    if (index &lt; length)
+        m_modifiedArgumentsDescriptor.get()[index] = true;
+}
+
+template&lt;typename Type&gt;
+bool GenericArguments&lt;Type&gt;::isModifiedArgumentDescriptor(unsigned index, unsigned length)
+{
+    if (!m_modifiedArgumentsDescriptor)
+        return false;
+    if (index &lt; length)
+        return m_modifiedArgumentsDescriptor.get()[index];
+    return false;
+}
+
+template&lt;typename Type&gt;
</ins><span class="cx"> void GenericArguments&lt;Type&gt;::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="lines">@@ -225,7 +301,7 @@
</span><span class="cx"> 
</span><span class="cx">     Type* thisObject = static_cast&lt;Type*&gt;(this);
</span><span class="cx">     for (unsigned i = 0; i &lt; length; ++i) {
</span><del>-        if (thisObject-&gt;canAccessIndexQuickly(i + offset))
</del><ins>+        if (thisObject-&gt;isMappedArgument(i + offset))
</ins><span class="cx">             exec-&gt;r(firstElementDest + i) = thisObject-&gt;getIndexQuickly(i + offset);
</span><span class="cx">         else {
</span><span class="cx">             exec-&gt;r(firstElementDest + i) = get(exec, i + offset);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeScopedArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ScopedArguments.cpp (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ScopedArguments.cpp        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/runtime/ScopedArguments.cpp        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -111,6 +111,8 @@
</span><span class="cx">         visitor.appendValues(
</span><span class="cx">             thisObject-&gt;overflowStorage(), thisObject-&gt;m_totalLength - thisObject-&gt;m_table-&gt;length());
</span><span class="cx">     }
</span><ins>+
+    GenericArguments&lt;ScopedArguments&gt;::visitChildren(cell, visitor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Structure* ScopedArguments::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span><span class="lines">@@ -135,7 +137,7 @@
</span><span class="cx">         overrideThings(vm);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ScopedArguments::overrideArgument(VM&amp; vm, uint32_t i)
</del><ins>+void ScopedArguments::unmapArgument(VM&amp; vm, uint32_t i)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT_WITH_SECURITY_IMPLICATION(i &lt; m_totalLength);
</span><span class="cx">     unsigned namedLength = m_table-&gt;length();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeScopedArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ScopedArguments.h (210145 => 210146)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ScopedArguments.h        2016-12-24 18:00:00 UTC (rev 210145)
+++ trunk/Source/JavaScriptCore/runtime/ScopedArguments.h        2016-12-24 21:26:22 UTC (rev 210146)
</span><span class="lines">@@ -70,7 +70,7 @@
</span><span class="cx">         return internalLength();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool canAccessIndexQuickly(uint32_t i) const
</del><ins>+    bool isMappedArgument(uint32_t i) const
</ins><span class="cx">     {
</span><span class="cx">         if (i &gt;= m_totalLength)
</span><span class="cx">             return false;
</span><span class="lines">@@ -80,14 +80,14 @@
</span><span class="cx">         return !!overflowStorage()[i - namedLength].get();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool canAccessArgumentIndexQuicklyInDFG(uint32_t i) const
</del><ins>+    bool isMappedArgumentInDFG(uint32_t i) const
</ins><span class="cx">     {
</span><del>-        return canAccessIndexQuickly(i);
</del><ins>+        return isMappedArgument(i);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     JSValue getIndexQuickly(uint32_t i) const
</span><span class="cx">     {
</span><del>-        ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
</del><ins>+        ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
</ins><span class="cx">         unsigned namedLength = m_table-&gt;length();
</span><span class="cx">         if (i &lt; namedLength)
</span><span class="cx">             return m_scope-&gt;variableAt(m_table-&gt;get(i)).get();
</span><span class="lines">@@ -96,7 +96,7 @@
</span><span class="cx"> 
</span><span class="cx">     void setIndexQuickly(VM&amp; vm, uint32_t i, JSValue value)
</span><span class="cx">     {
</span><del>-        ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
</del><ins>+        ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
</ins><span class="cx">         unsigned namedLength = m_table-&gt;length();
</span><span class="cx">         if (i &lt; namedLength)
</span><span class="cx">             m_scope-&gt;variableAt(m_table-&gt;get(i)).set(vm, m_scope.get(), value);
</span><span class="lines">@@ -108,12 +108,27 @@
</span><span class="cx">     {
</span><span class="cx">         return m_callee;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     bool overrodeThings() const { return m_overrodeThings; }
</span><span class="cx">     void overrideThings(VM&amp;);
</span><span class="cx">     void overrideThingsIfNecessary(VM&amp;);
</span><del>-    void overrideArgument(VM&amp;, uint32_t index);
</del><ins>+    void unmapArgument(VM&amp;, uint32_t index);
</ins><span class="cx">     
</span><ins>+    void initModifiedArgumentsDescriptorIfNecessary(VM&amp; vm)
+    {
+        GenericArguments&lt;ScopedArguments&gt;::initModifiedArgumentsDescriptorIfNecessary(vm, m_table-&gt;length());
+    }
+
+    void setModifiedArgumentDescriptor(VM&amp; vm, unsigned index)
+    {
+        GenericArguments&lt;ScopedArguments&gt;::setModifiedArgumentDescriptor(vm, index, m_table-&gt;length());
+    }
+
+    bool isModifiedArgumentDescriptor(unsigned index)
+    {
+        return GenericArguments&lt;ScopedArguments&gt;::isModifiedArgumentDescriptor(index, m_table-&gt;length());
+    }
+
</ins><span class="cx">     void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span></span></pre>
</div>
</div>

</body>
</html>