<!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>[225072] 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/225072">225072</a></dd>
<dt>Author</dt> <dd>utatane.tea@gmail.com</dd>
<dt>Date</dt> <dd>2017-11-21 02:40:34 -0800 (Tue, 21 Nov 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[DFG][FTL] Support MapSet / SetAdd intrinsics
https://bugs.webkit.org/show_bug.cgi?id=179858

Reviewed by Saam Barati.

JSTests:

* microbenchmarks/map-has-and-set.js: Added.
(test):
* stress/map-set-check-failure.js: Added.
(shouldBe):
(shouldThrow):
(target):
* stress/map-set-cse.js: Added.
(shouldBe):
(test):
* stress/set-add-check-failure.js: Added.
(shouldBe):
(shouldThrow):
(set shouldThrow):
* stress/set-add-cse.js: Added.
(shouldBe):

Source/JavaScriptCore:

Map.prototype.set and Set.prototype.add uses MapHash value anyway.
By handling them as MapSet and SetAdd DFG nodes and decoupling
MapSet and SetAdd nodes from MapHash DFG node, we have a chance to
remove duplicate MapHash calculation for the same key.

One story is *set-if-not-exists*.

    if (!map.has(key))
        map.set(key, value);

In the above code, both `has` and `set` require hash value for `key`.
If we can change `set` to the series of DFG nodes:

    1: MapHash(key)
    2: MapSet(MapObjectUse:map, Untyped:key, Untyped:value, Int32Use:@1)

we can remove duplicate @1 produced by `has` operation.

This patch improves SixSpeed map-set.es6 and map-set-object.es6 by 20.5% and 20.4% respectively,

                                 baseline                  patched

    map-set.es6             246.2413+-15.2084    ^    204.3679+-11.2408       ^ definitely 1.2049x faster
    map-set-object.es6      266.5075+-17.2289    ^    221.2792+-12.2948       ^ definitely 1.2044x faster

Microbenchmarks

    map-has-and-set         148.1522+-7.6665     ^    131.4552+-7.8846        ^ definitely 1.1270x faster

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileSetAdd):
(JSC::DFG::SpeculativeJIT::compileMapSet):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileSetAdd):
(JSC::FTL::DFG::LowerDFGToB3::compileMapSet):
* jit/JITOperations.h:
* runtime/HashMapImpl.h:
(JSC::HashMapImpl::addNormalized):
(JSC::HashMapImpl::addNormalizedInternal):
* runtime/Intrinsic.cpp:
(JSC::intrinsicName):
* runtime/Intrinsic.h:
* runtime/MapPrototype.cpp:
(JSC::MapPrototype::finishCreation):
* runtime/SetPrototype.cpp:
(JSC::SetPrototype::finishCreation):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeHashMapImplh">trunk/Source/JavaScriptCore/runtime/HashMapImpl.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntrinsiccpp">trunk/Source/JavaScriptCore/runtime/Intrinsic.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntrinsich">trunk/Source/JavaScriptCore/runtime/Intrinsic.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeMapPrototypecpp">trunk/Source/JavaScriptCore/runtime/MapPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSetPrototypecpp">trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsmicrobenchmarksmaphasandsetjs">trunk/JSTests/microbenchmarks/map-has-and-set.js</a></li>
<li><a href="#trunkJSTestsstressmapsetcheckfailurejs">trunk/JSTests/stress/map-set-check-failure.js</a></li>
<li><a href="#trunkJSTestsstressmapsetcsejs">trunk/JSTests/stress/map-set-cse.js</a></li>
<li><a href="#trunkJSTestsstresssetaddcheckfailurejs">trunk/JSTests/stress/set-add-check-failure.js</a></li>
<li><a href="#trunkJSTestsstresssetaddcsejs">trunk/JSTests/stress/set-add-cse.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog  2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/JSTests/ChangeLog     2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -1,5 +1,28 @@
</span><span class="cx"> 2017-11-21  Yusuke Suzuki  <utatane.tea@gmail.com>
</span><span class="cx"> 
</span><ins>+        [DFG][FTL] Support MapSet / SetAdd intrinsics
+        https://bugs.webkit.org/show_bug.cgi?id=179858
+
+        Reviewed by Saam Barati.
+
+        * microbenchmarks/map-has-and-set.js: Added.
+        (test):
+        * stress/map-set-check-failure.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (target):
+        * stress/map-set-cse.js: Added.
+        (shouldBe):
+        (test):
+        * stress/set-add-check-failure.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (set shouldThrow):
+        * stress/set-add-cse.js: Added.
+        (shouldBe):
+
+2017-11-21  Yusuke Suzuki  <utatane.tea@gmail.com>
+
</ins><span class="cx">         [JSC] Allow poly proto for intrinsic getters
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=179550
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarksmaphasandsetjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/map-has-and-set.js (0 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/map-has-and-set.js                         (rev 0)
+++ trunk/JSTests/microbenchmarks/map-has-and-set.js    2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+function test()
+{
+    let map = new Map();
+    for (let i = 0; i < 1e6; ++i) {
+        if (!map.has(i))
+            map.set(i, i);
+    }
+    return map
+}
+noInline(test);
+
+test();
</ins></span></pre></div>
<a id="trunkJSTestsstressmapsetcheckfailurejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/map-set-check-failure.js (0 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/map-set-check-failure.js                            (rev 0)
+++ trunk/JSTests/stress/map-set-check-failure.js       2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+var func = Map.prototype.set;
+function target(map)
+{
+    return func.call(map, 42, 42);
+}
+noInline(target);
+
+for (var i = 0; i < 1e6; ++i) {
+    var map = new Map();
+    shouldBe(target(map), map);
+    shouldBe(map.get(42), 42);
+}
+shouldThrow(() => {
+    target(new Set());
+}, `TypeError: Map operation called on non-Map object`);
</ins></span></pre></div>
<a id="trunkJSTestsstressmapsetcsejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/map-set-cse.js (0 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/map-set-cse.js                              (rev 0)
+++ trunk/JSTests/stress/map-set-cse.js 2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+    var map = new Map();
+    var r1 = map.get(42);
+    map.set(42, 42);
+    var r2 = map.get(42);
+    return [r1, r2];
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i) {
+    let [r1, r2] = test();
+    shouldBe(r1, undefined);
+    shouldBe(r2, 42);
+}
</ins></span></pre></div>
<a id="trunkJSTestsstresssetaddcheckfailurejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/set-add-check-failure.js (0 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/set-add-check-failure.js                            (rev 0)
+++ trunk/JSTests/stress/set-add-check-failure.js       2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+var func = Set.prototype.add;
+function target(set)
+{
+    return func.call(set, 42);
+}
+noInline(target);
+
+for (var i = 0; i < 1e6; ++i) {
+    var set = new Set();
+    shouldBe(target(set), set);
+    shouldBe(set.has(42), true);
+}
+shouldThrow(() => {
+    target(new Map());
+}, `TypeError: Set operation called on non-Set object`);
</ins></span></pre></div>
<a id="trunkJSTestsstresssetaddcsejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/set-add-cse.js (0 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/set-add-cse.js                              (rev 0)
+++ trunk/JSTests/stress/set-add-cse.js 2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+    var set = new Set();
+    var r1 = set.has(42);
+    set.add(42);
+    var r2 = set.has(42);
+    return [r1, r2];
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i) {
+    let [r1, r2] = test();
+    shouldBe(r1, false);
+    shouldBe(r2, true);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/ChangeLog       2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -1,5 +1,84 @@
</span><span class="cx"> 2017-11-21  Yusuke Suzuki  <utatane.tea@gmail.com>
</span><span class="cx"> 
</span><ins>+        [DFG][FTL] Support MapSet / SetAdd intrinsics
+        https://bugs.webkit.org/show_bug.cgi?id=179858
+
+        Reviewed by Saam Barati.
+
+        Map.prototype.set and Set.prototype.add uses MapHash value anyway.
+        By handling them as MapSet and SetAdd DFG nodes and decoupling
+        MapSet and SetAdd nodes from MapHash DFG node, we have a chance to
+        remove duplicate MapHash calculation for the same key.
+
+        One story is *set-if-not-exists*.
+
+            if (!map.has(key))
+                map.set(key, value);
+
+        In the above code, both `has` and `set` require hash value for `key`.
+        If we can change `set` to the series of DFG nodes:
+
+            1: MapHash(key)
+            2: MapSet(MapObjectUse:map, Untyped:key, Untyped:value, Int32Use:@1)
+
+        we can remove duplicate @1 produced by `has` operation.
+
+        This patch improves SixSpeed map-set.es6 and map-set-object.es6 by 20.5% and 20.4% respectively,
+
+                                         baseline                  patched
+
+            map-set.es6             246.2413+-15.2084    ^    204.3679+-11.2408       ^ definitely 1.2049x faster
+            map-set-object.es6      266.5075+-17.2289    ^    221.2792+-12.2948       ^ definitely 1.2044x faster
+
+        Microbenchmarks
+
+            map-has-and-set         148.1522+-7.6665     ^    131.4552+-7.8846        ^ definitely 1.1270x faster
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileSetAdd):
+        (JSC::DFG::SpeculativeJIT::compileMapSet):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileSetAdd):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMapSet):
+        * jit/JITOperations.h:
+        * runtime/HashMapImpl.h:
+        (JSC::HashMapImpl::addNormalized):
+        (JSC::HashMapImpl::addNormalizedInternal):
+        * runtime/Intrinsic.cpp:
+        (JSC::intrinsicName):
+        * runtime/Intrinsic.h:
+        * runtime/MapPrototype.cpp:
+        (JSC::MapPrototype::finishCreation):
+        * runtime/SetPrototype.cpp:
+        (JSC::SetPrototype::finishCreation):
+
+2017-11-21  Yusuke Suzuki  <utatane.tea@gmail.com>
+
</ins><span class="cx">         [JSC] Allow poly proto for intrinsic getters
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=179550
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h  2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h     2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -1141,6 +1141,10 @@
</span><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case SetAdd:
+    case MapSet:
+        break;
+
</ins><span class="cx">     case WeakMapGet:
</span><span class="cx">         forNode(node).makeHeapTop();
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp    2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp       2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -2904,6 +2904,38 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case JSSetAddIntrinsic: {
+        if (argumentCountIncludingThis != 2)
+            return false;
+
+        insertChecks();
+        Node* base = get(virtualRegisterForArgument(0, registerOffset));
+        Node* key = get(virtualRegisterForArgument(1, registerOffset));
+        Node* hash = addToGraph(MapHash, key);
+        addToGraph(SetAdd, base, key, hash);
+        set(VirtualRegister(resultOperand), base);
+        return true;
+    }
+
+    case JSMapSetIntrinsic: {
+        if (argumentCountIncludingThis != 3)
+            return false;
+
+        insertChecks();
+        Node* base = get(virtualRegisterForArgument(0, registerOffset));
+        Node* key = get(virtualRegisterForArgument(1, registerOffset));
+        Node* value = get(virtualRegisterForArgument(2, registerOffset));
+        Node* hash = addToGraph(MapHash, key);
+
+        addVarArgChild(base);
+        addVarArgChild(key);
+        addVarArgChild(value);
+        addVarArgChild(hash);
+        addToGraph(Node::VarArg, MapSet, OpInfo(0), OpInfo(0));
+        set(VirtualRegister(resultOperand), base);
+        return true;
+    }
+
</ins><span class="cx">     case JSSetBucketHeadIntrinsic:
</span><span class="cx">     case JSMapBucketHeadIntrinsic: {
</span><span class="cx">         ASSERT(argumentCountIncludingThis == 2);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h  2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h     2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -1643,6 +1643,14 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case SetAdd:
+    case MapSet: {
+        // FIXME: Define defs for them to participate in CSE.
+        // https://bugs.webkit.org/show_bug.cgi?id=179911
+        write(MiscFields);
+        return;
+    }
+
</ins><span class="cx">     case StringSlice:
</span><span class="cx">         def(PureValue(node));
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp    2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp       2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -344,6 +344,8 @@
</span><span class="cx">     case ArraySlice:
</span><span class="cx">     case ArrayIndexOf:
</span><span class="cx">     case ParseInt: // We might resolve a rope even though we don't clobber anything.
</span><ins>+    case SetAdd:
+    case MapSet:
</ins><span class="cx">         return true;
</span><span class="cx">         
</span><span class="cx">     case MultiPutByOffset:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp   2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -1947,6 +1947,18 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case SetAdd: {
+            fixEdge<SetObjectUse>(node->child1());
+            fixEdge<Int32Use>(node->child3());
+            break;
+        }
+
+        case MapSet: {
+            fixEdge<MapObjectUse>(m_graph.varArgChild(node, 0));
+            fixEdge<Int32Use>(m_graph.varArgChild(node, 3));
+            break;
+        }
+
</ins><span class="cx">         case DefineDataProperty: {
</span><span class="cx">             fixEdge<CellUse>(m_graph.varArgChild(node, 0));
</span><span class="cx">             Edge& propertyEdge = m_graph.varArgChild(node, 1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h    2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h       2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -445,6 +445,8 @@
</span><span class="cx">     macro(GetMapBucketNext, NodeResultJS) \
</span><span class="cx">     macro(LoadKeyFromMapBucket, NodeResultJS) \
</span><span class="cx">     macro(LoadValueFromMapBucket, NodeResultJS) \
</span><ins>+    macro(SetAdd, NodeMustGenerate) \
+    macro(MapSet, NodeMustGenerate | NodeHasVarArgs) \
</ins><span class="cx">     /* Nodes for JSWeakMap and JSWeakSet */ \
</span><span class="cx">     macro(WeakMapGet, NodeResultJS) \
</span><span class="cx">     \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp   2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -2556,6 +2556,22 @@
</span><span class="cx">     return *bucket;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// FIXME: Add NormalizeMapKey DFG node.
+// https://bugs.webkit.org/show_bug.cgi?id=179912
+void JIT_OPERATION operationSetAdd(ExecState* exec, JSCell* set, EncodedJSValue key, int32_t hash)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+    jsCast<JSSet*>(set)->addNormalized(exec, normalizeMapKey(JSValue::decode(key)), JSValue(), hash);
+}
+
+void JIT_OPERATION operationMapSet(ExecState* exec, JSCell* map, EncodedJSValue key, EncodedJSValue value, int32_t hash)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+    jsCast<JSMap*>(map)->addNormalized(exec, normalizeMapKey(JSValue::decode(key)), JSValue::decode(value), hash);
+}
+
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(ExecState* exec, JSObject* thisObject)
</span><span class="cx"> {
</span><span class="cx">     VM& vm = exec->vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h  2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h     2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -138,6 +138,8 @@
</span><span class="cx"> void JIT_OPERATION operationDefineAccessorPropertyString(ExecState*, JSObject*, JSString*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
</span><span class="cx"> void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState*, JSObject*, UniquedStringImpl*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
</span><span class="cx"> void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState*, JSObject*, Symbol*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
</span><ins>+void JIT_OPERATION operationSetAdd(ExecState*, JSCell*, EncodedJSValue, int32_t) WTF_INTERNAL;
+void JIT_OPERATION operationMapSet(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue, int32_t) WTF_INTERNAL;
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationArrayPushMultiple(ExecState*, JSArray*, void* buffer, int32_t elementCount) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState*, double value, JSArray*) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp   2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -1173,6 +1173,8 @@
</span><span class="cx">         case PutDynamicVar:
</span><span class="cx">         case NukeStructureAndSetButterfly:
</span><span class="cx">         case InitializeEntrypointArguments:
</span><ins>+        case SetAdd:
+        case MapSet:
</ins><span class="cx">             break;
</span><span class="cx">             
</span><span class="cx">         // This gets ignored because it only pretends to produce a value.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h       2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h  2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -535,6 +535,10 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case SetAdd:
+    case MapSet:
+        return false;
+
</ins><span class="cx">     case LastNodeType:
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         return false;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp    2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp       2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -10836,6 +10836,44 @@
</span><span class="cx">     noResult(node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileSetAdd(Node* node)
+{
+    SpeculateCellOperand set(this, node->child1());
+    JSValueOperand key(this, node->child2());
+    SpeculateInt32Operand hash(this, node->child3());
+
+    GPRReg setGPR = set.gpr();
+    JSValueRegs keyRegs = key.jsValueRegs();
+    GPRReg hashGPR = hash.gpr();
+
+    speculateSetObject(node->child1(), setGPR);
+
+    flushRegisters();
+    callOperation(operationSetAdd, setGPR, keyRegs, hashGPR);
+    m_jit.exceptionCheck();
+    noResult(node);
+}
+
+void SpeculativeJIT::compileMapSet(Node* node)
+{
+    SpeculateCellOperand map(this, m_jit.graph().varArgChild(node, 0));
+    JSValueOperand key(this, m_jit.graph().varArgChild(node, 1));
+    JSValueOperand value(this, m_jit.graph().varArgChild(node, 2));
+    SpeculateInt32Operand hash(this, m_jit.graph().varArgChild(node, 3));
+
+    GPRReg mapGPR = map.gpr();
+    JSValueRegs keyRegs = key.jsValueRegs();
+    JSValueRegs valueRegs = value.jsValueRegs();
+    GPRReg hashGPR = hash.gpr();
+
+    speculateMapObject(m_jit.graph().varArgChild(node, 0), mapGPR);
+
+    flushRegisters();
+    callOperation(operationMapSet, mapGPR, keyRegs, valueRegs, hashGPR);
+    m_jit.exceptionCheck();
+    noResult(node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileWeakMapGet(Node* node)
</span><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand weakMap(this, node->child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h      2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h 2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -1932,11 +1932,21 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR());
</span><span class="cx">         return appendCall(operation);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(V_JITOperation_ECJZ operation, GPRReg arg1, JSValueRegs arg2, GPRReg arg3)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg3);
+        return appendCall(operation);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(V_JITOperation_ECJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
</span><span class="cx">         return appendCall(operation);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(V_JITOperation_ECJJZ operation, GPRReg arg1, JSValueRegs arg2, JSValueRegs arg3, GPRReg arg4)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg3.payloadGPR(), arg4);
+        return appendCall(operation);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(V_JITOperation_ECCJ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.payloadGPR());
</span><span class="lines">@@ -2502,6 +2512,16 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3.payloadGPR(), arg3.tagGPR());
</span><span class="cx">         return appendCall(operation);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(V_JITOperation_ECJZ operation, GPRReg arg1, JSValueRegs arg2, GPRReg arg3)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3);
+        return appendCall(operation);
+    }
+    JITCompiler::Call callOperation(V_JITOperation_ECJJZ operation, GPRReg arg1, JSValueRegs arg2, JSValueRegs arg3, GPRReg arg4)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3.payloadGPR(), arg3.tagGPR(), arg4);
+        return appendCall(operation);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(V_JITOperation_ECCJ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3.payloadGPR(), arg3.tagGPR());
</span><span class="lines">@@ -2876,6 +2896,8 @@
</span><span class="cx">     void compileCheckSubClass(Node*);
</span><span class="cx">     void compileGetMapBucketHead(Node*);
</span><span class="cx">     void compileGetMapBucketNext(Node*);
</span><ins>+    void compileSetAdd(Node*);
+    void compileMapSet(Node*);
</ins><span class="cx">     void compileWeakMapGet(Node*);
</span><span class="cx">     void compileLoadKeyFromMapBucket(Node*);
</span><span class="cx">     void compileLoadValueFromMapBucket(Node*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp       2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp  2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -4875,6 +4875,14 @@
</span><span class="cx">         compileLoadValueFromMapBucket(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case SetAdd:
+        compileSetAdd(node);
+        break;
+
+    case MapSet:
+        compileMapSet(node);
+        break;
+
</ins><span class="cx">     case WeakMapGet:
</span><span class="cx">         compileWeakMapGet(node);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp  2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp     2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -5261,6 +5261,14 @@
</span><span class="cx">         compileLoadValueFromMapBucket(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case SetAdd:
+        compileSetAdd(node);
+        break;
+
+    case MapSet:
+        compileMapSet(node);
+        break;
+
</ins><span class="cx">     case WeakMapGet:
</span><span class="cx">         compileWeakMapGet(node);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp      2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp 2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -207,6 +207,8 @@
</span><span class="cx">     case GetMapBucketNext:
</span><span class="cx">     case LoadKeyFromMapBucket:
</span><span class="cx">     case LoadValueFromMapBucket:
</span><ins>+    case SetAdd:
+    case MapSet:
</ins><span class="cx">     case WeakMapGet:
</span><span class="cx">     case IsEmpty:
</span><span class="cx">     case IsUndefined:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp      2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp 2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -1052,6 +1052,12 @@
</span><span class="cx">         case LoadValueFromMapBucket:
</span><span class="cx">             compileLoadValueFromMapBucket();
</span><span class="cx">             break;
</span><ins>+        case SetAdd:
+            compileSetAdd();
+            break;
+        case MapSet:
+            compileMapSet();
+            break;
</ins><span class="cx">         case WeakMapGet:
</span><span class="cx">             compileWeakMapGet();
</span><span class="cx">             break;
</span><span class="lines">@@ -8786,6 +8792,25 @@
</span><span class="cx">         setJSValue(m_out.load64(mapBucket, m_heaps.HashMapBucket_key));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void compileSetAdd()
+    {
+        LValue set = lowSetObject(m_node->child1());
+        LValue key = lowJSValue(m_node->child2());
+        LValue hash = lowInt32(m_node->child3());
+
+        vmCall(Void, m_out.operation(operationSetAdd), m_callFrame, set, key, hash);
+    }
+
+    void compileMapSet()
+    {
+        LValue map = lowMapObject(m_graph.varArgChild(m_node, 0));
+        LValue key = lowJSValue(m_graph.varArgChild(m_node, 1));
+        LValue value = lowJSValue(m_graph.varArgChild(m_node, 2));
+        LValue hash = lowInt32(m_graph.varArgChild(m_node, 3));
+
+        vmCall(Void, m_out.operation(operationMapSet), m_callFrame, map, key, value, hash);
+    }
+
</ins><span class="cx">     void compileWeakMapGet()
</span><span class="cx">     {
</span><span class="cx">         LValue weakMap = lowWeakMapObject(m_node->child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h  2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h     2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -265,7 +265,9 @@
</span><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_ECJZC)(ExecState*, JSCell*, EncodedJSValue, int32_t, JSCell*);
</span><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_ECCIcf)(ExecState*, JSCell*, JSCell*, InlineCallFrame*);
</span><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
</span><ins>+typedef void (JIT_OPERATION *V_JITOperation_ECJZ)(ExecState*, JSCell*, EncodedJSValue, int32_t);
</ins><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_ECJJ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue);
</span><ins>+typedef void (JIT_OPERATION *V_JITOperation_ECJJZ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue, int32_t);
</ins><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_ECPSPS)(ExecState*, JSCell*, void*, size_t, void*, size_t);
</span><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_ECZ)(ExecState*, JSCell*, int32_t);
</span><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeHashMapImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/HashMapImpl.h (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/HashMapImpl.h        2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/runtime/HashMapImpl.h   2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -441,6 +441,18 @@
</span><span class="cx">             rehash(exec);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void addNormalized(ExecState* exec, JSValue key, JSValue value, uint32_t hash)
+    {
+        ASSERT_WITH_MESSAGE(normalizeMapKey(key) == key, "We expect normalized values flowing into this function.");
+        ASSERT_WITH_MESSAGE(jsMapHash(exec, exec->vm(), key) == hash, "We expect hash value is what we expect.");
+
+        addNormalizedInternal(exec->vm(), key, value, hash, [&] (HashMapBucketType* bucket) {
+            return !isDeleted(bucket) && areKeysEqual(exec, key, bucket->key());
+        });
+        if (shouldRehashAfterAdd())
+            rehash(exec);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE bool remove(ExecState* exec, JSValue key)
</span><span class="cx">     {
</span><span class="cx">         HashMapBucketType** bucket = findBucket(exec, key);
</span><span class="lines">@@ -556,14 +568,22 @@
</span><span class="cx">     template<typename CanUseBucket>
</span><span class="cx">     ALWAYS_INLINE void addNormalizedInternal(ExecState* exec, JSValue key, JSValue value, const CanUseBucket& canUseBucket)
</span><span class="cx">     {
</span><del>-        ASSERT_WITH_MESSAGE(normalizeMapKey(key) == key, "We expect normalized values flowing into this function.");
-
</del><span class="cx">         VM& vm = exec->vm();
</span><span class="cx">         auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><ins>+        uint32_t hash = jsMapHash(exec, vm, key);
+        RETURN_IF_EXCEPTION(scope, void());
+        scope.release();
+        addNormalizedInternal(vm, key, value, hash, canUseBucket);
+    }
+
+    template<typename CanUseBucket>
+    ALWAYS_INLINE void addNormalizedInternal(VM& vm, JSValue key, JSValue value, uint32_t hash, const CanUseBucket& canUseBucket)
+    {
+        ASSERT_WITH_MESSAGE(normalizeMapKey(key) == key, "We expect normalized values flowing into this function.");
+
</ins><span class="cx">         const uint32_t mask = m_capacity - 1;
</span><del>-        uint32_t index = jsMapHash(exec, vm, key) & mask;
-        RETURN_IF_EXCEPTION(scope, void());
</del><ins>+        uint32_t index = hash & mask;
</ins><span class="cx">         HashMapBucketType** buffer = this->buffer();
</span><span class="cx">         HashMapBucketType* bucket = buffer[index];
</span><span class="cx">         while (!isEmpty(bucket)) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntrinsiccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Intrinsic.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Intrinsic.cpp        2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/runtime/Intrinsic.cpp   2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -143,6 +143,8 @@
</span><span class="cx">         return "JSMapGetIntrinsic";
</span><span class="cx">     case JSMapHasIntrinsic:
</span><span class="cx">         return "JSMapHasIntrinsic";
</span><ins>+    case JSMapSetIntrinsic:
+        return "JSMapSetIntrinsic";
</ins><span class="cx">     case JSMapBucketHeadIntrinsic:
</span><span class="cx">         return "JSMapBucketHeadIntrinsic";
</span><span class="cx">     case JSMapBucketNextIntrinsic:
</span><span class="lines">@@ -153,6 +155,8 @@
</span><span class="cx">         return "JSMapBucketValueIntrinsic";
</span><span class="cx">     case JSSetHasIntrinsic:
</span><span class="cx">         return "JSSetHasIntrinsic";
</span><ins>+    case JSSetAddIntrinsic:
+        return "JSSetAddIntrinsic";
</ins><span class="cx">     case JSSetBucketHeadIntrinsic:
</span><span class="cx">         return "JSSetBucketHeadIntrinsic";
</span><span class="cx">     case JSSetBucketNextIntrinsic:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntrinsich"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Intrinsic.h (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Intrinsic.h  2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/runtime/Intrinsic.h     2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -84,11 +84,13 @@
</span><span class="cx">     BoundThisNoArgsFunctionCallIntrinsic,
</span><span class="cx">     JSMapGetIntrinsic,
</span><span class="cx">     JSMapHasIntrinsic,
</span><ins>+    JSMapSetIntrinsic,
</ins><span class="cx">     JSMapBucketHeadIntrinsic,
</span><span class="cx">     JSMapBucketNextIntrinsic,
</span><span class="cx">     JSMapBucketKeyIntrinsic,
</span><span class="cx">     JSMapBucketValueIntrinsic,
</span><span class="cx">     JSSetHasIntrinsic,
</span><ins>+    JSSetAddIntrinsic,
</ins><span class="cx">     JSSetBucketHeadIntrinsic,
</span><span class="cx">     JSSetBucketNextIntrinsic,
</span><span class="cx">     JSSetBucketKeyIntrinsic,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeMapPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/MapPrototype.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/MapPrototype.cpp     2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/runtime/MapPrototype.cpp        2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -66,10 +66,10 @@
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, mapProtoFuncDelete, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->get, mapProtoFuncGet, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSMapGetIntrinsic);
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, mapProtoFuncHas, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSMapHasIntrinsic);
</span><del>-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->set, mapProtoFuncSet, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
</del><ins>+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->set, mapProtoFuncSet, static_cast<unsigned>(PropertyAttribute::DontEnum), 2, JSMapSetIntrinsic);
</ins><span class="cx"> 
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrivateName(), mapProtoFuncGet, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSMapGetIntrinsic);
</span><del>-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().setPrivateName(), mapProtoFuncSet, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
</del><ins>+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().setPrivateName(), mapProtoFuncSet, static_cast<unsigned>(PropertyAttribute::DontEnum), 2, JSMapSetIntrinsic);
</ins><span class="cx"> 
</span><span class="cx">     JSFunction* entries = JSFunction::create(vm, mapPrototypeEntriesCodeGenerator(vm), globalObject);
</span><span class="cx">     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().entriesPublicName(), entries, static_cast<unsigned>(PropertyAttribute::DontEnum));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSetPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp (225071 => 225072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp     2017-11-21 10:07:50 UTC (rev 225071)
+++ trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp        2017-11-21 10:40:34 UTC (rev 225072)
</span><span class="lines">@@ -61,12 +61,12 @@
</span><span class="cx">     ASSERT(inherits(vm, info()));
</span><span class="cx">     didBecomePrototype();
</span><span class="cx"> 
</span><del>-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->add, setProtoFuncAdd, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
</del><ins>+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->add, setProtoFuncAdd, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetAddIntrinsic);
</ins><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, setProtoFuncClear, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, setProtoFuncDelete, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, setProtoFuncHas, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetHasIntrinsic);
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().hasPrivateName(), setProtoFuncHas, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetHasIntrinsic);
</span><del>-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().addPrivateName(), setProtoFuncAdd, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
</del><ins>+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().addPrivateName(), setProtoFuncAdd, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetAddIntrinsic);
</ins><span class="cx"> 
</span><span class="cx">     JSFunction* values = JSFunction::create(vm, setPrototypeValuesCodeGenerator(vm), globalObject);
</span><span class="cx">     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPublicName(), values, static_cast<unsigned>(PropertyAttribute::DontEnum));
</span></span></pre>
</div>
</div>

</body>
</html>