<!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>[208117] 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/208117">208117</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-10-29 18:38:22 -0700 (Sat, 29 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>We should have a way of profiling when a get_by_id is pure and to emit a PureGetById in the DFG/FTL
https://bugs.webkit.org/show_bug.cgi?id=163305

Reviewed by Keith Miller.

JSTests:

* microbenchmarks/pure-get-by-id-cse-2.js: Added.
(foo):
* microbenchmarks/pure-get-by-id-cse.js: Added.
(foo):
* stress/pure-get-by-id-cse-correctness.js: Added.
(assert):
(foo):
* stress/pure-get-by-id-on-non-object.js: Added.
(assert):
(foo):

Source/JavaScriptCore:

This creates a new GetById node in the DFG called PureGetById. We emit a
PureGetById when we profile that a get_by_id in the baseline never does
side effects. PureGetById speculates on the fact that it won't do side
effects. If it realizes that it must perform side effects, it will perform
the side effect, but also invalidate the CodeBlock that compiled it,
which will cause us to exit once we return back to the compiled code.
This allows us to have stricter clobberize rules for PureGetById which
model how getOwnPropertySlot(VMInquiry) behaves. This means that PureGetByIds
can be CSEd with each other, and that other things are more likely to
be CSEd around a PureGetById. To profile if a get_by_id does side
effects, I've added an extra bit into StructureStubInfo that we write
to when performing a get_by_id slow path call. If we notice that we
never do effects, inside the ByteCodeParser, we will emit a PureGetById
instead of a GetById.

To justify the performance benefit of this patch, I ran the suite of
benchmarks with useAccessInlining=false. This meant that we don't compile
any (Multi)GetByOffset/(Multi)PutByOffset. This was just to try to see if
this patch is worth anything at all in a world where we emit many
PureGetByIds. Running the benchmarks under this mode showed a 3.5% octane
improvement and a 15% kraken improvement. However, when running benchmarks
with useAccessInlining=true (the default JSC state), this patch is neutral.
I think the main reason for this is that the DFG is good at knowing when to
emit (Multi)GetByOffset, and most benchmarks that would benefit from
PureGetById are already emitting (Multi)GetByOffset. However, PureGetById can be
profitable when we encounter code that is too polymorphic for (Multi)GetByOffset.
It's reasonable to expect that JS code in the wild will fall into this use
case even though it might not be represented in some of the major JS benchmarks.
I wrote some microbenchmarks to demonstrate the benefits of PureGetById CSE,
and they were 30% (eliminating a few PureGetById from an add expression)
to 10x faster (eliminating a PureGetById in a loop).

* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::StructureStubInfo):
(JSC::StructureStubInfo::reset):
* bytecode/StructureStubInfo.h:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGArrayMode.cpp:
(JSC::DFG::canBecomeGetArrayLength):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToGetByOffset):
(JSC::DFG::Node::convertToMultiGetByOffset):
(JSC::DFG::Node::hasIdentifier):
(JSC::DFG::Node::hasHeapPrediction):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileTryGetById):
(JSC::DFG::SpeculativeJIT::compilePureGetById):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileGetById):
(JSC::FTL::DFG::LowerDFGToB3::getById):
* jit/JITOperations.cpp:
(JSC::pureGetByIdCommon):
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_try_get_by_id):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_try_get_by_id):
* jit/Repatch.cpp:
(JSC::appropriateOptimizingGetByIdFunction):
(JSC::appropriateGenericGetByIdFunction):
(JSC::tryCacheGetByID):
* jit/Repatch.h:
* profiler/ProfilerJettisonReason.cpp:
(WTF::printInternal):
* profiler/ProfilerJettisonReason.h:</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="#trunkSourceJavaScriptCorebytecodeStructureStubInfocpp">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubInfoh">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArrayModecpp">trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp</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="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</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="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.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="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccesscpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchh">trunk/Source/JavaScriptCore/jit/Repatch.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfilerJettisonReasoncpp">trunk/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfilerJettisonReasonh">trunk/Source/JavaScriptCore/profiler/ProfilerJettisonReason.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsmicrobenchmarkspuregetbyidcse2js">trunk/JSTests/microbenchmarks/pure-get-by-id-cse-2.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkspuregetbyidcsejs">trunk/JSTests/microbenchmarks/pure-get-by-id-cse.js</a></li>
<li><a href="#trunkJSTestsstresspuregetbyidcsecorrectnessjs">trunk/JSTests/stress/pure-get-by-id-cse-correctness.js</a></li>
<li><a href="#trunkJSTestsstresspuregetbyidonnonobjectjs">trunk/JSTests/stress/pure-get-by-id-on-non-object.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/JSTests/ChangeLog        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2016-10-29  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        We should have a way of profiling when a get_by_id is pure and to emit a PureGetById in the DFG/FTL
+        https://bugs.webkit.org/show_bug.cgi?id=163305
+
+        Reviewed by Keith Miller.
+
+        * microbenchmarks/pure-get-by-id-cse-2.js: Added.
+        (foo):
+        * microbenchmarks/pure-get-by-id-cse.js: Added.
+        (foo):
+        * stress/pure-get-by-id-cse-correctness.js: Added.
+        (assert):
+        (foo):
+        * stress/pure-get-by-id-on-non-object.js: Added.
+        (assert):
+        (foo):
+
</ins><span class="cx"> 2016-10-28  Csaba Osztrogonác  &lt;ossy@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Skip JSTests/microbenchmarks/dense-set.js on memory limited devices
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkspuregetbyidcse2js"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/pure-get-by-id-cse-2.js (0 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/pure-get-by-id-cse-2.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/pure-get-by-id-cse-2.js        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+function foo(o, c) {
+    if (o.f) {
+        let sum = 0;
+        for (let i = 0; i &lt; c; i++)
+            sum += o.f;
+        return sum;
+    }
+}
+noInline(foo);
+
+let start = Date.now();
+let objects = [];
+const objectCount = 20;
+for (let i = 0; i &lt; objectCount; i++) {
+    let obj = {};
+    for (let j = 0; j &lt; i * 2; j++) {
+        obj[&quot;j&quot; + j] = j;
+    }
+    obj.f = 20;
+    objects.push(obj);
+}
+
+for (let i = 0; i &lt; 1000000; i++) {
+    let obj = objects[i % objects.length];
+    foo(obj, 150);
+}
+
+const verbose = false;
+if (verbose)
+    print(Date.now() - start);
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkspuregetbyidcsejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/pure-get-by-id-cse.js (0 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/pure-get-by-id-cse.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/pure-get-by-id-cse.js        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+function foo(o) {
+    if (o.f)
+        return o.f + o.f + o.f + o.f; 
+}
+noInline(foo);
+
+let start = Date.now();
+let objects = [];
+const objectCount = 20;
+for (let i = 0; i &lt; objectCount; i++) {
+    let obj = {};
+    for (let j = 0; j &lt; i * 2; j++) {
+        obj[&quot;j&quot; + j] = j;
+    }
+    obj.f = 20;
+    objects.push(obj);
+}
+
+for (let i = 0; i &lt; 10000000; i++) {
+    let obj = objects[i % objects.length];
+    foo(obj);
+}
+
+const verbose = false;
+if (verbose)
+    print(Date.now() - start);
</ins></span></pre></div>
<a id="trunkJSTestsstresspuregetbyidcsecorrectnessjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/pure-get-by-id-cse-correctness.js (0 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/pure-get-by-id-cse-correctness.js                                (rev 0)
+++ trunk/JSTests/stress/pure-get-by-id-cse-correctness.js        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;)
+}
+noInline(assert);
+
+function foo(o1, o2) {
+    let a = o1.f1;
+    let b = o2.f2;
+    return a + o1.f1 + b;
+}
+noInline(foo);
+
+let objs = [];
+const count = 80;
+for (let i = 0; i &lt; count; i++) {
+    let o = {};
+    for (let j = 0; j &lt; i; ++j) {
+        o[j + &quot;J&quot;] = j;
+    }
+    o.f1 = 20;
+    o.f2 = 40;
+    objs.push(o);
+}
+
+for (let i = 0; i &lt; 1000; i++) {
+    let o1 = objs[i % objs.length];
+    let o2 = objs[(i + 1) % objs.length];
+    assert(foo(o1, o2) === 80);
+}
+
+let o = objs[count - 1];
+let numCalls = 0;
+Object.defineProperty(o, &quot;f1&quot;, {
+    get() { ++numCalls; return 25; }
+});
+
+assert(foo(o, objs[count - 2]) === 90);
+assert(numCalls === 2);
</ins></span></pre></div>
<a id="trunkJSTestsstresspuregetbyidonnonobjectjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/pure-get-by-id-on-non-object.js (0 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/pure-get-by-id-on-non-object.js                                (rev 0)
+++ trunk/JSTests/stress/pure-get-by-id-on-non-object.js        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion.&quot;)
+}
+
+function foo(o) {
+    assert(o.length === o.length);
+    return o.length;
+}
+noInline(foo);
+
+let items = [];
+const numItems = 30;
+for (let i = 0; i &lt; numItems; i++) {
+    let o = {};
+    for (let j = 0; j &lt; i; j++) {
+        o[j + &quot;j&quot;] = j;
+    }
+    o.length = 2;
+    items.push(o);
+} 
+
+items.push(&quot;st&quot;);
+
+for (let i = 0; i &lt; 10000; i++)
+    assert(foo(items[i % items.length]) === 2);
+
+Number.prototype.length = 2;
+items.push(42);
+
+for (let i = 0; i &lt; 100000; i++)
+    assert(foo(items[i % items.length]) === 2);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -1,3 +1,102 @@
</span><ins>+2016-10-29  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        We should have a way of profiling when a get_by_id is pure and to emit a PureGetById in the DFG/FTL
+        https://bugs.webkit.org/show_bug.cgi?id=163305
+
+        Reviewed by Keith Miller.
+
+        This creates a new GetById node in the DFG called PureGetById. We emit a
+        PureGetById when we profile that a get_by_id in the baseline never does
+        side effects. PureGetById speculates on the fact that it won't do side
+        effects. If it realizes that it must perform side effects, it will perform
+        the side effect, but also invalidate the CodeBlock that compiled it,
+        which will cause us to exit once we return back to the compiled code.
+        This allows us to have stricter clobberize rules for PureGetById which
+        model how getOwnPropertySlot(VMInquiry) behaves. This means that PureGetByIds
+        can be CSEd with each other, and that other things are more likely to
+        be CSEd around a PureGetById. To profile if a get_by_id does side
+        effects, I've added an extra bit into StructureStubInfo that we write
+        to when performing a get_by_id slow path call. If we notice that we
+        never do effects, inside the ByteCodeParser, we will emit a PureGetById
+        instead of a GetById.
+
+        To justify the performance benefit of this patch, I ran the suite of
+        benchmarks with useAccessInlining=false. This meant that we don't compile
+        any (Multi)GetByOffset/(Multi)PutByOffset. This was just to try to see if
+        this patch is worth anything at all in a world where we emit many
+        PureGetByIds. Running the benchmarks under this mode showed a 3.5% octane
+        improvement and a 15% kraken improvement. However, when running benchmarks
+        with useAccessInlining=true (the default JSC state), this patch is neutral.
+        I think the main reason for this is that the DFG is good at knowing when to
+        emit (Multi)GetByOffset, and most benchmarks that would benefit from
+        PureGetById are already emitting (Multi)GetByOffset. However, PureGetById can be
+        profitable when we encounter code that is too polymorphic for (Multi)GetByOffset.
+        It's reasonable to expect that JS code in the wild will fall into this use
+        case even though it might not be represented in some of the major JS benchmarks.
+        I wrote some microbenchmarks to demonstrate the benefits of PureGetById CSE,
+        and they were 30% (eliminating a few PureGetById from an add expression)
+        to 10x faster (eliminating a PureGetById in a loop).
+
+        * bytecode/StructureStubInfo.cpp:
+        (JSC::StructureStubInfo::StructureStubInfo):
+        (JSC::StructureStubInfo::reset):
+        * bytecode/StructureStubInfo.h:
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::canBecomeGetArrayLength):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleGetById):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToGetByOffset):
+        (JSC::DFG::Node::convertToMultiGetByOffset):
+        (JSC::DFG::Node::hasIdentifier):
+        (JSC::DFG::Node::hasHeapPrediction):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileTryGetById):
+        (JSC::DFG::SpeculativeJIT::compilePureGetById):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::cachedGetById):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::cachedGetById):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetById):
+        (JSC::FTL::DFG::LowerDFGToB3::getById):
+        * jit/JITOperations.cpp:
+        (JSC::pureGetByIdCommon):
+        * jit/JITOperations.h:
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_try_get_by_id):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emit_op_try_get_by_id):
+        * jit/Repatch.cpp:
+        (JSC::appropriateOptimizingGetByIdFunction):
+        (JSC::appropriateGenericGetByIdFunction):
+        (JSC::tryCacheGetByID):
+        * jit/Repatch.h:
+        * profiler/ProfilerJettisonReason.cpp:
+        (WTF::printInternal):
+        * profiler/ProfilerJettisonReason.h:
+
</ins><span class="cx"> 2016-10-28  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Breakpoints not working in scripts with unicode characters
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx">     , resetByGC(false)
</span><span class="cx">     , tookSlowPath(false)
</span><span class="cx">     , everConsidered(false)
</span><ins>+    , didSideEffects(false)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -216,7 +217,10 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     switch (accessType) {
</span><del>-    case AccessType::GetPure:
</del><ins>+    case AccessType::TryGet:
+        resetGetByID(codeBlock, *this, GetByIDKind::Try);
+        break;
+    case AccessType::PureGet:
</ins><span class="cx">         resetGetByID(codeBlock, *this, GetByIDKind::Pure);
</span><span class="cx">         break;
</span><span class="cx">     case AccessType::Get:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -46,7 +46,8 @@
</span><span class="cx"> 
</span><span class="cx"> enum class AccessType : int8_t {
</span><span class="cx">     Get,
</span><del>-    GetPure,
</del><ins>+    TryGet,
+    PureGet,
</ins><span class="cx">     Put,
</span><span class="cx">     In
</span><span class="cx"> };
</span><span class="lines">@@ -205,6 +206,7 @@
</span><span class="cx">     bool resetByGC : 1;
</span><span class="cx">     bool tookSlowPath : 1;
</span><span class="cx">     bool everConsidered : 1;
</span><ins>+    bool didSideEffects : 1;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline CodeOrigin getStructureStubInfoCodeOrigin(StructureStubInfo&amp; structureStubInfo)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -2119,6 +2119,7 @@
</span><span class="cx">         forNode(node).makeHeapTop();
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case PureGetById:
</ins><span class="cx">     case GetById:
</span><span class="cx">     case GetByIdFlush: {
</span><span class="cx">         if (!node-&gt;prediction()) {
</span><span class="lines">@@ -2150,7 +2151,10 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        clobberWorld(node-&gt;origin.semantic, clobberLimit);
</del><ins>+        if (node-&gt;op() == PureGetById)
+            clobberStructures(clobberLimit);
+        else
+            clobberWorld(node-&gt;origin.semantic, clobberLimit);
</ins><span class="cx">         forNode(node).makeHeapTop();
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArrayModecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -152,10 +152,11 @@
</span><span class="cx"> 
</span><span class="cx"> static bool canBecomeGetArrayLength(Graph&amp; graph, Node* node)
</span><span class="cx"> {
</span><del>-    if (node-&gt;op() != GetById)
-        return false;
-    auto uid = graph.identifiers()[node-&gt;identifierNumber()];
-    return uid == graph.m_vm.propertyNames-&gt;length.impl();
</del><ins>+    if (node-&gt;op() == GetById || node-&gt;op() == PureGetById) {
+        auto uid = graph.identifiers()[node-&gt;identifierNumber()];
+        return uid == graph.m_vm.propertyNames-&gt;length.impl();
+    }
+    return false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ArrayMode ArrayMode::refine(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -3307,10 +3307,19 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     NodeType getById;
</span><del>-    if (type == AccessType::Get)
</del><ins>+    switch (type) {
+    case AccessType::Get:
</ins><span class="cx">         getById = getByIdStatus.makesCalls() ? GetByIdFlush : GetById;
</span><del>-    else
</del><ins>+        break;
+    case AccessType::TryGet:
</ins><span class="cx">         getById = TryGetById;
</span><ins>+        break;
+    case AccessType::PureGet:
+        getById = PureGetById;
+        break;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
</ins><span class="cx"> 
</span><span class="cx">     // Special path for custom accessors since custom's offset does not have any meanings.
</span><span class="cx">     // So, this is completely different from Simple one. But we have a chance to optimize it when we use DOMJIT.
</span><span class="lines">@@ -4198,7 +4207,8 @@
</span><span class="cx"> 
</span><span class="cx">             Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             Node* property = get(VirtualRegister(currentInstruction[3].u.operand));
</span><del>-            bool compiledAsGetById = false;
</del><ins>+            bool compileAsGetById = false;
+            bool compileAsPureGetById = false;
</ins><span class="cx">             GetByIdStatus getByIdStatus;
</span><span class="cx">             unsigned identifierNumber = 0;
</span><span class="cx">             {
</span><span class="lines">@@ -4207,7 +4217,8 @@
</span><span class="cx">                 // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
</span><span class="cx">                 // At that time, there is no information.
</span><span class="cx">                 if (byValInfo &amp;&amp; byValInfo-&gt;stubInfo &amp;&amp; !byValInfo-&gt;tookSlowPath &amp;&amp; !m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadIdent) &amp;&amp; !m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
</span><del>-                    compiledAsGetById = true;
</del><ins>+                    compileAsGetById = true;
+                    compileAsPureGetById = !byValInfo-&gt;stubInfo-&gt;didSideEffects;
</ins><span class="cx">                     identifierNumber = m_graph.identifiers().ensure(byValInfo-&gt;cachedId.impl());
</span><span class="cx">                     UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
</span><span class="cx"> 
</span><span class="lines">@@ -4225,9 +4236,10 @@
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if (compiledAsGetById)
-                handleGetById(currentInstruction[1].u.operand, prediction, base, identifierNumber, getByIdStatus, AccessType::Get, OPCODE_LENGTH(op_get_by_val));
-            else {
</del><ins>+            if (compileAsGetById) {
+                AccessType type = compileAsPureGetById ? AccessType::PureGet : AccessType::Get;
+                handleGetById(currentInstruction[1].u.operand, prediction, base, identifierNumber, getByIdStatus, type, OPCODE_LENGTH(op_get_by_val));
+            } else {
</ins><span class="cx">                 ArrayMode arrayMode = getArrayMode(currentInstruction[4].u.arrayProfile, Array::Read);
</span><span class="cx">                 Node* getByVal = addToGraph(GetByVal, OpInfo(arrayMode.asWord()), OpInfo(prediction), base, property);
</span><span class="cx">                 m_exitOK = false; // GetByVal must be treated as if it clobbers exit state, since FixupPhase may make it generic.
</span><span class="lines">@@ -4363,7 +4375,18 @@
</span><span class="cx">                 m_inlineStackTop-&gt;m_profiledBlock, m_dfgCodeBlock,
</span><span class="cx">                 m_inlineStackTop-&gt;m_stubInfos, m_dfgStubInfos,
</span><span class="cx">                 currentCodeOrigin(), uid);
</span><del>-            AccessType type = op_try_get_by_id == opcodeID ? AccessType::GetPure : AccessType::Get;
</del><ins>+            AccessType type;
+            if (opcodeID == op_try_get_by_id) 
+                type = AccessType::TryGet;
+            else {
+                ConcurrentJITLocker locker(m_inlineStackTop-&gt;m_profiledBlock-&gt;m_lock);
+                unsigned bytecodeIndex = currentCodeOrigin().bytecodeIndex;
+                StructureStubInfo* info = m_inlineStackTop-&gt;m_stubInfos.get(CodeOrigin(bytecodeIndex));
+                if (info &amp;&amp; info-&gt;everConsidered &amp;&amp; !info-&gt;didSideEffects)
+                    type = AccessType::PureGet;
+                else
+                    type = AccessType::Get;
+            }
</ins><span class="cx"> 
</span><span class="cx">             unsigned opcodeLength = opcodeID == op_try_get_by_id ? OPCODE_LENGTH(op_try_get_by_id) : OPCODE_LENGTH(op_get_by_id);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -495,6 +495,35 @@
</span><span class="cx">         def(HeapLocation(IsFunctionLoc, MiscFields, node-&gt;child1()), LazyNode(node));
</span><span class="cx">         return;
</span><span class="cx">         
</span><ins>+    case PureGetById: {
+        // We model what is allowed inside a getOwnPropertySlot(VMInquiry) here.
+        // Some getOwnPropertySlot implementations will lazily inject properties, which
+        // may change the object's structure.
+
+        read(JSCell_structureID);
+        read(JSCell_typeInfoFlags);
+        read(JSCell_typeInfoType);
+        read(JSCell_indexingType);
+        read(JSObject_butterfly);
+        read(MiscFields);
+
+        AbstractHeap propertyNameHeap(NamedProperties, node-&gt;identifierNumber());
+        read(propertyNameHeap);
+
+        write(JSCell_structureID);
+        write(JSCell_typeInfoFlags);
+
+        write(Watchpoint_fire);
+        write(MiscFields);
+
+        // This can happen if lazily adding fields to an object happens in getOwnPropertySlot
+        // and we need to allocate out of line storage.
+        write(JSObject_butterfly);
+
+        def(HeapLocation(NamedPropertyLoc, propertyNameHeap, node-&gt;child1()), LazyNode(node));
+        return;
+    }
+
</ins><span class="cx">     case GetById:
</span><span class="cx">     case GetByIdFlush:
</span><span class="cx">     case GetByIdWithThis:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -448,6 +448,7 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         
</span><ins>+            case PureGetById:
</ins><span class="cx">             case GetById:
</span><span class="cx">             case GetByIdFlush: {
</span><span class="cx">                 Edge childEdge = node-&gt;child1();
</span><span class="lines">@@ -459,6 +460,9 @@
</span><span class="cx">                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
</span><span class="cx">                 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
</span><span class="cx"> 
</span><ins>+                if (!Options::useAccessInlining())
+                    break;
+
</ins><span class="cx">                 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()
</span><span class="cx">                     || (node-&gt;child1().useKind() == UntypedUse || (baseValue.m_type &amp; ~SpecCell)))
</span><span class="cx">                     break;
</span><span class="lines">@@ -514,6 +518,9 @@
</span><span class="cx">                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
</span><span class="cx">                 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
</span><span class="cx"> 
</span><ins>+                if (!Options::useAccessInlining())
+                    break;
+
</ins><span class="cx">                 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered())
</span><span class="cx">                     break;
</span><span class="cx">                 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -264,6 +264,7 @@
</span><span class="cx">     case ResolveScope:
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    case PureGetById: // We are modeling getOwnPropertySlot here, which may GC because it is allowed to allocate things.
</ins><span class="cx">     case CreateActivation:
</span><span class="cx">     case CreateDirectArguments:
</span><span class="cx">     case CreateScopedArguments:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -1167,6 +1167,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case PureGetById:
</ins><span class="cx">         case GetById:
</span><span class="cx">         case GetByIdFlush: {
</span><span class="cx">             // FIXME: This should be done in the ByteCodeParser based on reading the
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -532,7 +532,7 @@
</span><span class="cx">     
</span><span class="cx">     void convertToGetByOffset(StorageAccessData&amp; data, Edge storage, Edge base)
</span><span class="cx">     {
</span><del>-        ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
</del><ins>+        ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == PureGetById || m_op == MultiGetByOffset);
</ins><span class="cx">         m_opInfo = &amp;data;
</span><span class="cx">         children.setChild1(storage);
</span><span class="cx">         children.setChild2(base);
</span><span class="lines">@@ -542,7 +542,7 @@
</span><span class="cx">     
</span><span class="cx">     void convertToMultiGetByOffset(MultiGetByOffsetData* data)
</span><span class="cx">     {
</span><del>-        ASSERT(m_op == GetById || m_op == GetByIdFlush);
</del><ins>+        ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == PureGetById);
</ins><span class="cx">         m_opInfo = data;
</span><span class="cx">         child1().setUseKind(CellUse);
</span><span class="cx">         m_op = MultiGetByOffset;
</span><span class="lines">@@ -918,6 +918,7 @@
</span><span class="cx">         switch (op()) {
</span><span class="cx">         case TryGetById:
</span><span class="cx">         case GetById:
</span><ins>+        case PureGetById:
</ins><span class="cx">         case GetByIdFlush:
</span><span class="cx">         case GetByIdWithThis:
</span><span class="cx">         case PutById:
</span><span class="lines">@@ -1428,6 +1429,7 @@
</span><span class="cx">         case ArithCeil:
</span><span class="cx">         case ArithTrunc:
</span><span class="cx">         case GetDirectPname:
</span><ins>+        case PureGetById:
</ins><span class="cx">         case GetById:
</span><span class="cx">         case GetByIdFlush:
</span><span class="cx">         case GetByIdWithThis:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -185,6 +185,7 @@
</span><span class="cx">     macro(PutByVal, NodeMustGenerate | NodeHasVarArgs) \
</span><span class="cx">     macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs) \
</span><span class="cx">     macro(TryGetById, NodeResultJS) \
</span><ins>+    macro(PureGetById, NodeResultJS | NodeMustGenerate) \
</ins><span class="cx">     macro(GetById, NodeResultJS | NodeMustGenerate) \
</span><span class="cx">     macro(GetByIdFlush, NodeResultJS | NodeMustGenerate) \
</span><span class="cx">     macro(GetByIdWithThis, NodeResultJS | NodeMustGenerate) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -682,6 +682,7 @@
</span><span class="cx">         case RegExpTest:
</span><span class="cx">         case StringReplace:
</span><span class="cx">         case StringReplaceRegExp:
</span><ins>+        case PureGetById:
</ins><span class="cx">         case GetById:
</span><span class="cx">         case GetByIdFlush:
</span><span class="cx">         case GetByIdWithThis:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -199,6 +199,7 @@
</span><span class="cx">     case TryGetById:
</span><span class="cx">     case DeleteById:
</span><span class="cx">     case DeleteByVal:
</span><ins>+    case PureGetById:
</ins><span class="cx">     case GetById:
</span><span class="cx">     case GetByIdWithThis:
</span><span class="cx">     case GetByValWithThis:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -1003,7 +1003,7 @@
</span><span class="cx"> 
</span><span class="cx">         base.use();
</span><span class="cx"> 
</span><del>-        cachedGetById(node-&gt;origin.semantic, baseRegs, resultRegs, node-&gt;identifierNumber(), JITCompiler::Jump(), NeedToSpill, AccessType::GetPure);
</del><ins>+        cachedGetById(node-&gt;origin.semantic, baseRegs, resultRegs, node-&gt;identifierNumber(), JITCompiler::Jump(), NeedToSpill, AccessType::TryGet);
</ins><span class="cx"> 
</span><span class="cx">         jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
</span><span class="cx">         break;
</span><span class="lines">@@ -1020,7 +1020,7 @@
</span><span class="cx"> 
</span><span class="cx">         JITCompiler::Jump notCell = m_jit.branchIfNotCell(baseRegs);
</span><span class="cx"> 
</span><del>-        cachedGetById(node-&gt;origin.semantic, baseRegs, resultRegs, node-&gt;identifierNumber(), notCell, NeedToSpill, AccessType::GetPure);
</del><ins>+        cachedGetById(node-&gt;origin.semantic, baseRegs, resultRegs, node-&gt;identifierNumber(), notCell, NeedToSpill, AccessType::TryGet);
</ins><span class="cx"> 
</span><span class="cx">         jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
</span><span class="cx">         break;
</span><span class="lines">@@ -1032,6 +1032,42 @@
</span><span class="cx">     } 
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compilePureGetById(Node* node)
+{
+    ASSERT(node-&gt;op() == PureGetById);
+
+    switch (node-&gt;child1().useKind()) {
+    case CellUse: {
+        SpeculateCellOperand base(this, node-&gt;child1());
+        JSValueRegsTemporary result(this, Reuse, base);
+
+        JSValueRegs baseRegs = JSValueRegs::payloadOnly(base.gpr());
+        JSValueRegs resultRegs = result.regs();
+
+        cachedGetById(node-&gt;origin.semantic, baseRegs, resultRegs, node-&gt;identifierNumber(), JITCompiler::Jump(), NeedToSpill, AccessType::PureGet);
+
+        jsValueResult(resultRegs, node);
+        break;
+    }
+    case UntypedUse: {
+        JSValueOperand base(this, node-&gt;child1());
+        JSValueRegsTemporary result(this, Reuse, base);
+
+        JSValueRegs baseRegs = base.jsValueRegs();
+        JSValueRegs resultRegs = result.regs();
+    
+        JITCompiler::Jump notCell = m_jit.branchIfNotCell(baseRegs);
+    
+        cachedGetById(node-&gt;origin.semantic, baseRegs, resultRegs, node-&gt;identifierNumber(), notCell, NeedToSpill, AccessType::PureGet);
+    
+        jsValueResult(resultRegs, node);
+        break;
+    }
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileIn(Node* node)
</span><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand base(this, node-&gt;child2());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -721,6 +721,7 @@
</span><span class="cx">     void compileDeleteById(Node*);
</span><span class="cx">     void compileDeleteByVal(Node*);
</span><span class="cx">     void compileTryGetById(Node*);
</span><ins>+    void compilePureGetById(Node*);
</ins><span class="cx">     void compileIn(Node*);
</span><span class="cx">     
</span><span class="cx">     void nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -210,6 +210,8 @@
</span><span class="cx">     J_JITOperation_ESsiJI getByIdFunction;
</span><span class="cx">     if (type == AccessType::Get)
</span><span class="cx">         getByIdFunction = operationGetByIdOptimize;
</span><ins>+    else if (type == AccessType::PureGet)
+        getByIdFunction = operationPureGetByIdOptimize;
</ins><span class="cx">     else
</span><span class="cx">         getByIdFunction = operationTryGetByIdOptimize;
</span><span class="cx"> 
</span><span class="lines">@@ -4269,6 +4271,11 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case PureGetById: {
+        compilePureGetById(node);
+        break;
+    }
+
</ins><span class="cx">     case GetByIdWithThis: {
</span><span class="cx">         JSValueOperand base(this, node-&gt;child1());
</span><span class="cx">         JSValueRegs baseRegs = base.jsValueRegs();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -179,8 +179,11 @@
</span><span class="cx">         slowCases.append(slowPathTarget);
</span><span class="cx">     slowCases.append(gen.slowPathJump());
</span><span class="cx">     
</span><ins>+    auto slowPathFunction = type == AccessType::Get ? operationGetByIdOptimize :
+        type == AccessType::PureGet ? operationPureGetByIdOptimize : operationTryGetByIdOptimize;
+
</ins><span class="cx">     auto slowPath = slowPathCall(
</span><del>-        slowCases, this, type == AccessType::Get ? operationGetByIdOptimize : operationTryGetByIdOptimize,
</del><ins>+        slowCases, this, slowPathFunction,
</ins><span class="cx">         spillMode, ExceptionCheckRequirement::CheckNeeded,
</span><span class="cx">         resultGPR, gen.stubInfo(), baseGPR, identifierUID(identifierNumber));
</span><span class="cx">     
</span><span class="lines">@@ -4235,6 +4238,11 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case PureGetById: {
+        compilePureGetById(node);
+        break;
+    }
+
</ins><span class="cx">     case GetByIdFlush: {
</span><span class="cx">         if (!node-&gt;prediction()) {
</span><span class="cx">             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -176,6 +176,7 @@
</span><span class="cx">     case NewArrayWithSize:
</span><span class="cx">     case TryGetById:
</span><span class="cx">     case GetById:
</span><ins>+    case PureGetById:
</ins><span class="cx">     case GetByIdFlush:
</span><span class="cx">     case GetByIdWithThis:
</span><span class="cx">     case ToThis:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -623,8 +623,11 @@
</span><span class="cx">             compilePutStructure();
</span><span class="cx">             break;
</span><span class="cx">         case TryGetById:
</span><del>-            compileGetById(AccessType::GetPure);
</del><ins>+            compileGetById(AccessType::TryGet);
</ins><span class="cx">             break;
</span><ins>+        case PureGetById:
+            compileGetById(AccessType::PureGet);
+            break;
</ins><span class="cx">         case GetById:
</span><span class="cx">         case GetByIdFlush:
</span><span class="cx">             compileGetById(AccessType::Get);
</span><span class="lines">@@ -2788,7 +2791,7 @@
</span><span class="cx">     
</span><span class="cx">     void compileGetById(AccessType type)
</span><span class="cx">     {
</span><del>-        ASSERT(type == AccessType::Get || type == AccessType::GetPure);
</del><ins>+        ASSERT(type == AccessType::Get || type == AccessType::TryGet || type == AccessType::PureGet);
</ins><span class="cx">         switch (m_node-&gt;child1().useKind()) {
</span><span class="cx">         case CellUse: {
</span><span class="cx">             setJSValue(getById(lowCell(m_node-&gt;child1()), type));
</span><span class="lines">@@ -2815,6 +2818,8 @@
</span><span class="cx">             J_JITOperation_EJI getByIdFunction;
</span><span class="cx">             if (type == AccessType::Get)
</span><span class="cx">                 getByIdFunction = operationGetByIdGeneric;
</span><ins>+            else if (type == AccessType::PureGet)
+                getByIdFunction = operationPureGetByIdGeneric;
</ins><span class="cx">             else
</span><span class="cx">                 getByIdFunction = operationTryGetByIdGeneric;
</span><span class="cx"> 
</span><span class="lines">@@ -8838,6 +8843,8 @@
</span><span class="cx">                         J_JITOperation_ESsiJI optimizationFunction;
</span><span class="cx">                         if (type == AccessType::Get)
</span><span class="cx">                             optimizationFunction = operationGetByIdOptimize;
</span><ins>+                        else if (type == AccessType::PureGet)
+                            optimizationFunction = operationPureGetByIdOptimize;
</ins><span class="cx">                         else
</span><span class="cx">                             optimizationFunction = operationTryGetByIdOptimize;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -70,6 +70,35 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE static EncodedJSValue pureGetByIdCommon(VM&amp; vm, ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid, const std::function&lt;void (const PropertySlot&amp;, const Identifier&amp;)&gt;&amp; function = [] (const PropertySlot&amp;, const Identifier&amp;) { })
+{
+    Identifier ident = Identifier::fromUid(&amp;vm, uid);
+    JSValue baseValue = JSValue::decode(base);
+
+    ASSERT(JITCode::isOptimizingJIT(exec-&gt;codeBlock()-&gt;jitType()));
+
+    PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
+    return JSValue::encode(baseValue.getPropertySlot(exec, ident, slot, [&amp;] (bool, PropertySlot&amp;) -&gt; JSValue {
+        bool willDoSideEffects = !(slot.isValue() || slot.isUnset()) || slot.isTaintedByOpaqueObject();
+        if (UNLIKELY(willDoSideEffects)) {
+            {
+                CodeOrigin codeOrigin = exec-&gt;codeOrigin();
+                CodeBlock* currentBaseline = baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, exec-&gt;codeBlock()-&gt;alternative());
+                CodeOrigin originBytecodeIndex = CodeOrigin(codeOrigin.bytecodeIndex); // Since we're searching in the baseline, we just care about bytecode index.
+                ConcurrentJITLocker locker(currentBaseline-&gt;m_lock);
+                if (StructureStubInfo* stub = currentBaseline-&gt;findStubInfo(originBytecodeIndex))
+                    stub-&gt;didSideEffects = true;
+            }
+
+            exec-&gt;codeBlock()-&gt;jettison(Profiler::JettisonDueToPureGetByIdEffects);
+            return baseValue.get(exec, uid);
+        }
+
+        function(slot, ident);
+        return slot.isValue() ? slot.getValue(exec, ident) : jsUndefined();
+    }));
+}
+
</ins><span class="cx"> extern &quot;C&quot; {
</span><span class="cx"> 
</span><span class="cx"> #if COMPILER(MSVC)
</span><span class="lines">@@ -165,6 +194,38 @@
</span><span class="cx">     return missingArgCount;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JIT_OPERATION operationPureGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    return pureGetByIdCommon(*vm, exec, base, uid);
+}
+
+EncodedJSValue JIT_OPERATION operationPureGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    stubInfo-&gt;tookSlowPath = true;
+
+    return pureGetByIdCommon(*vm, exec, base, uid);
+}
+
+EncodedJSValue JIT_OPERATION operationPureGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    return pureGetByIdCommon(*vm, exec, base, uid, 
+        [&amp;] (const PropertySlot&amp; slot, const Identifier&amp; ident) {
+            ASSERT((slot.isValue() || slot.isUnset()) &amp;&amp; !slot.isTaintedByOpaqueObject());
+            JSValue baseValue = JSValue::decode(base);
+            if (stubInfo-&gt;considerCaching(baseValue.structureOrNull()))
+                repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Pure);
+        });
+}
+
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationTryGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
</span><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="lines">@@ -179,7 +240,6 @@
</span><span class="cx">     return JSValue::encode(slot.getPureResult());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> EncodedJSValue JIT_OPERATION operationTryGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
</span><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="lines">@@ -207,7 +267,7 @@
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="cx"> 
</span><span class="cx">     if (stubInfo-&gt;considerCaching(baseValue.structureOrNull()) &amp;&amp; !slot.isTaintedByOpaqueObject() &amp;&amp; (slot.isCacheableValue() || slot.isCacheableGetter() || slot.isUnset()))
</span><del>-        repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Pure);
</del><ins>+        repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Try);
</ins><span class="cx"> 
</span><span class="cx">     return JSValue::encode(slot.getPureResult());
</span><span class="cx"> }
</span><span class="lines">@@ -226,7 +286,10 @@
</span><span class="cx">     Identifier ident = Identifier::fromUid(vm, uid);
</span><span class="cx">     
</span><span class="cx">     LOG_IC((ICEvent::OperationGetById, baseValue.classInfoOrNull(), ident));
</span><del>-    return JSValue::encode(baseValue.get(exec, ident, slot));
</del><ins>+    JSValue result = baseValue.get(exec, ident, slot);
+    bool willDoSideEffects = !(slot.isValue() || slot.isUnset()) || slot.isTaintedByOpaqueObject();
+    stubInfo-&gt;didSideEffects |= willDoSideEffects;
+    return JSValue::encode(result);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
</span><span class="lines">@@ -255,6 +318,9 @@
</span><span class="cx">     LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(), ident));
</span><span class="cx"> 
</span><span class="cx">     return JSValue::encode(baseValue.getPropertySlot(exec, ident, [&amp;] (bool found, PropertySlot&amp; slot) -&gt; JSValue {
</span><ins>+        bool willDoSideEffects = !(slot.isValue() || slot.isUnset()) || slot.isTaintedByOpaqueObject();
+        stubInfo-&gt;didSideEffects |= willDoSideEffects;
+
</ins><span class="cx">         if (stubInfo-&gt;considerCaching(baseValue.structureOrNull()))
</span><span class="cx">             repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Normal);
</span><span class="cx">         return found ? slot.getValue(exec, ident) : jsUndefined();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -330,6 +330,9 @@
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationTryGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationTryGetByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationTryGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
</span><ins>+EncodedJSValue JIT_OPERATION operationPureGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationPureGetByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationPureGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -579,7 +579,7 @@
</span><span class="cx"> 
</span><span class="cx">     JITGetByIdGenerator gen(
</span><span class="cx">         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
</span><del>-        ident-&gt;impl(), JSValueRegs(regT0), JSValueRegs(regT0), AccessType::GetPure);
</del><ins>+        ident-&gt;impl(), JSValueRegs(regT0), JSValueRegs(regT0), AccessType::TryGet);
</ins><span class="cx">     gen.generateFastPath(*this);
</span><span class="cx">     addSlowCase(gen.slowPathJump());
</span><span class="cx">     m_getByIds.append(gen);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -594,7 +594,7 @@
</span><span class="cx"> 
</span><span class="cx">     JITGetByIdGenerator gen(
</span><span class="cx">         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
</span><del>-        ident-&gt;impl(), JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::GetPure);
</del><ins>+        ident-&gt;impl(), JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::TryGet);
</ins><span class="cx">     gen.generateFastPath(*this);
</span><span class="cx">     addSlowCase(gen.slowPathJump());
</span><span class="cx">     m_getByIds.append(gen);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -134,16 +134,34 @@
</span><span class="cx"> 
</span><span class="cx"> inline J_JITOperation_ESsiJI appropriateOptimizingGetByIdFunction(GetByIDKind kind)
</span><span class="cx"> {
</span><del>-    if (kind == GetByIDKind::Normal)
</del><ins>+    switch (kind) {
+    case GetByIDKind::Normal:
</ins><span class="cx">         return operationGetByIdOptimize;
</span><del>-    return operationTryGetByIdOptimize;
</del><ins>+    case GetByIDKind::Try:
+        return operationTryGetByIdOptimize;
+    case GetByIDKind::Pure:
+        return operationPureGetByIdOptimize;
+    default:
+        break;
+    }
+    ASSERT_NOT_REACHED();
+    return operationGetByIdOptimize;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline J_JITOperation_ESsiJI appropriateGenericGetByIdFunction(GetByIDKind kind)
</span><span class="cx"> {
</span><del>-    if (kind == GetByIDKind::Normal)
</del><ins>+    switch (kind) {
+    case GetByIDKind::Normal:
</ins><span class="cx">         return operationGetById;
</span><del>-    return operationTryGetById;
</del><ins>+    case GetByIDKind::Try:
+        return operationTryGetById;
+    case GetByIDKind::Pure:
+        return operationPureGetById;
+    default:
+        break;
+    }
+    ASSERT_NOT_REACHED();
+    return operationGetById;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier&amp; propertyName, const PropertySlot&amp; slot, StructureStubInfo&amp; stubInfo, GetByIDKind kind)
</span><span class="lines">@@ -271,6 +289,16 @@
</span><span class="cx">                 type = AccessCase::Load;
</span><span class="cx">             else if (slot.isUnset())
</span><span class="cx">                 type = AccessCase::Miss;
</span><ins>+            else
+                RELEASE_ASSERT_NOT_REACHED();
+
+            newCase = AccessCase::tryGet(vm, codeBlock, type, offset, structure, conditionSet, loadTargetFromProxy, slot.watchpointSet());
+        } else if (kind == GetByIDKind::Try) {
+            AccessCase::AccessType type;
+            if (slot.isCacheableValue())
+                type = AccessCase::Load;
+            else if (slot.isUnset())
+                type = AccessCase::Miss;
</ins><span class="cx">             else if (slot.isCacheableGetter())
</span><span class="cx">                 type = AccessCase::GetGetter;
</span><span class="cx">             else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/jit/Repatch.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> 
</span><span class="cx"> enum class GetByIDKind {
</span><span class="cx">     Normal,
</span><ins>+    Try,
</ins><span class="cx">     Pure
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfilerJettisonReasoncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -56,6 +56,9 @@
</span><span class="cx">     case JettisonDueToOSRExit:
</span><span class="cx">         out.print(&quot;OSRExit&quot;);
</span><span class="cx">         return;
</span><ins>+    case JettisonDueToPureGetByIdEffects:
+        out.print(&quot;PureGetByIdEffects&quot;);
+        return;
</ins><span class="cx">     case JettisonDueToProfiledWatchpoint:
</span><span class="cx">         out.print(&quot;ProfiledWatchpoint&quot;);
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfilerJettisonReasonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfilerJettisonReason.h (208116 => 208117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfilerJettisonReason.h        2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/JavaScriptCore/profiler/ProfilerJettisonReason.h        2016-10-30 01:38:22 UTC (rev 208117)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx">     JettisonDueToBaselineLoopReoptimizationTrigger,
</span><span class="cx">     JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail,
</span><span class="cx">     JettisonDueToOSRExit,
</span><ins>+    JettisonDueToPureGetByIdEffects,
</ins><span class="cx">     JettisonDueToProfiledWatchpoint,
</span><span class="cx">     JettisonDueToUnprofiledWatchpoint,
</span><span class="cx">     JettisonDueToOldAge
</span></span></pre>
</div>
</div>

</body>
</html>