<!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>[213467] 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/213467">213467</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-06 14:03:56 -0800 (Mon, 06 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>op_get_by_id_with_this should use inline caching
https://bugs.webkit.org/show_bug.cgi?id=162124

Patch by Caio Lima &lt;ticaiolima@gmail.com&gt; on 2017-03-06
Reviewed by Saam Barati.

JSTests:

* microbenchmarks/super-getter.js: Added.
(A.prototype.get f):
(A):
(B.prototype.get f):
(B):
* stress/super-force-ic-fail.js: Added.
(let.assert):
(let.aObj.get foo):
(let.obj.jaz):
(let.bObj.get foo):
(let.obj2.foo):
* stress/super-get-by-id.js: Added.
(assert):
(Base):
(Base.prototype.get name):
(Base.prototype.set name):
(Subclass.prototype.get name):
(Subclass):
(getterName):
(getterValue):
(PolymorphicSubclass.prototype.get value):
(PolymorphicSubclass):
(i.let.BaseCode):
(i.get value):
(MegamorphicSubclass.prototype.get value):
(MegamorphicSubclass):
(let.subObj.get value):
(i.catch):
(subObj.get value):
(BaseException):
(BaseException.prototype.get name):
(SubclassException.prototype.get name):
(SubclassException):
(prototype.foo):
(prototype.get name):
(SubclassExceptionComplex.prototype.get name):
(SubclassExceptionComplex):
* stress/super-getter-reset-ic.js: Added.
(let.assert):
(let.B.f):

Source/JavaScriptCore:

This patch is enabling inline cache for op_get_by_id_with_this in all
tiers. It means that operations using ```super.member``` are going to
be able to be optimized by PIC. To enable it, we introduced a new
member of StructureStubInfo.patch named thisGPR, created a new class
to manage the IC named JITGetByIdWithThisGenerator and changed
PolymorphicAccess.regenerate that uses StructureStubInfo.patch.thisGPR
to decide the correct this value on inline caches.
With inline cached enabled, ```super.member``` are ~4.5x faster,
according microbenchmarks.

* bytecode/AccessCase.cpp:
(JSC::AccessCase::generateImpl):
* bytecode/PolymorphicAccess.cpp:
(JSC::PolymorphicAccess::regenerate):
* bytecode/PolymorphicAccess.h:
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::reset):
* bytecode/StructureStubInfo.h:
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::addGetByIdWithThis):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileIn):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetByIdWithThis):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetByIdWithThis):
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileGetByIdWithThis):
(JSC::FTL::DFG::LowerDFGToB3::compileIn):
(JSC::FTL::DFG::LowerDFGToB3::getByIdWithThis):
* jit/CCallHelpers.h:
(JSC::CCallHelpers::setupArgumentsWithExecState):
* jit/ICStats.h:
* jit/JIT.cpp:
(JSC::JIT::JIT):
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::link):
* jit/JIT.h:
* jit/JITInlineCacheGenerator.cpp:
(JSC::JITByIdGenerator::JITByIdGenerator):
(JSC::JITGetByIdWithThisGenerator::JITGetByIdWithThisGenerator):
(JSC::JITGetByIdWithThisGenerator::generateFastPath):
* jit/JITInlineCacheGenerator.h:
(JSC::JITGetByIdWithThisGenerator::JITGetByIdWithThisGenerator):
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_id_with_this):
(JSC::JIT::emitSlow_op_get_by_id_with_this):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_by_id_with_this):
(JSC::JIT::emitSlow_op_get_by_id_with_this):
* jit/Repatch.cpp:
(JSC::appropriateOptimizingGetByIdFunction):
(JSC::appropriateGenericGetByIdFunction):
(JSC::tryCacheGetByID):
* jit/Repatch.h:
* jsc.cpp:
(WTF::CustomGetter::getOwnPropertySlot):
(WTF::CustomGetter::customGetterAcessor):</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="#trunkSourceJavaScriptCorebytecodeAccessCasecpp">trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccessh">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h</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="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilerh">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.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="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCCallHelpersh">trunk/Source/JavaScriptCore/jit/CCallHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitICStatsh">trunk/Source/JavaScriptCore/jit/ICStats.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlineCacheGeneratorcpp">trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlineCacheGeneratorh">trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlinesh">trunk/Source/JavaScriptCore/jit/JITInlines.h</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="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsmicrobenchmarkssupergetterjs">trunk/JSTests/microbenchmarks/super-getter.js</a></li>
<li><a href="#trunkJSTestsstresssuperforceicfailjs">trunk/JSTests/stress/super-force-ic-fail.js</a></li>
<li><a href="#trunkJSTestsstresssupergetbyidjs">trunk/JSTests/stress/super-get-by-id.js</a></li>
<li><a href="#trunkJSTestsstresssupergetterreseticjs">trunk/JSTests/stress/super-getter-reset-ic.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/JSTests/ChangeLog        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2017-03-06  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        op_get_by_id_with_this should use inline caching
+        https://bugs.webkit.org/show_bug.cgi?id=162124
+
+        Reviewed by Saam Barati.
+
+        * microbenchmarks/super-getter.js: Added.
+        (A.prototype.get f):
+        (A):
+        (B.prototype.get f):
+        (B):
+        * stress/super-force-ic-fail.js: Added.
+        (let.assert):
+        (let.aObj.get foo):
+        (let.obj.jaz):
+        (let.bObj.get foo):
+        (let.obj2.foo):
+        * stress/super-get-by-id.js: Added.
+        (assert):
+        (Base):
+        (Base.prototype.get name):
+        (Base.prototype.set name):
+        (Subclass.prototype.get name):
+        (Subclass):
+        (getterName):
+        (getterValue):
+        (PolymorphicSubclass.prototype.get value):
+        (PolymorphicSubclass):
+        (i.let.BaseCode):
+        (i.get value):
+        (MegamorphicSubclass.prototype.get value):
+        (MegamorphicSubclass):
+        (let.subObj.get value):
+        (i.catch):
+        (subObj.get value):
+        (BaseException):
+        (BaseException.prototype.get name):
+        (SubclassException.prototype.get name):
+        (SubclassException):
+        (prototype.foo):
+        (prototype.get name):
+        (SubclassExceptionComplex.prototype.get name):
+        (SubclassExceptionComplex):
+        * stress/super-getter-reset-ic.js: Added.
+        (let.assert):
+        (let.B.f):
+
</ins><span class="cx"> 2017-03-06  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: implement init_expr for Element
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkssupergetterjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/super-getter.js (0 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/super-getter.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/super-getter.js        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+class A {
+    get f() {
+        return this._f;
+    }
+}
+
+class B extends A {
+    get f() {
+        return super.f;
+    }
+}
+
+(function() {
+    var o = new B();
+
+    o._f = 42;
+    var result = 0;
+    var n = 2000000;
+    for (var i = 0; i &lt; n; ++i)
+        result += o.f;
+    if (result != n * 42)
+        throw &quot;Error: bad result: &quot; + result;
+})();
+
</ins></span></pre></div>
<a id="trunkJSTestsstresssuperforceicfailjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/super-force-ic-fail.js (0 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/super-force-ic-fail.js                                (rev 0)
+++ trunk/JSTests/stress/super-force-ic-fail.js        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+let assert = (a) =&gt; {
+    if (!a)
+        throw Error(&quot;Bad Assertion&quot;);
+}
+
+let aObj =  {
+    get foo() { return this.a; }
+};
+
+let obj = {
+    jaz() {
+        return super.foo;
+    }
+};
+obj.a = &quot;foo&quot;;
+
+Object.setPrototypeOf(obj, aObj);
+
+noInline(obj.jaz);
+
+for (let i = 0; i &lt; 10000; i++) {
+    if (i == 9999) {
+        delete aObj.foo;
+        assert(obj.jaz() === undefined);
+    } else {
+        assert(obj.jaz() == &quot;foo&quot;);
+    }
+
+}
+
+let bObj =  {
+    get foo() { return this.a; }
+};
+
+let obj2 = {
+    foo() {
+        return super.foo;
+    }
+};
+obj2.a = &quot;foo&quot;;
+
+Object.setPrototypeOf(obj2, bObj);
+
+noInline(obj.jaz);
+
+for (let i = 0; i &lt; 10000; i++) {
+    if (i == 9999) {
+        Object.defineProperty(bObj, &quot;foo&quot;, {
+            get: () =&gt; {return &quot;boo&quot;; }
+        });
+        assert(obj2.foo() == &quot;boo&quot;);
+    } else {
+        assert(obj2.foo() == &quot;foo&quot;);
+    }
+}
+
</ins></span></pre></div>
<a id="trunkJSTestsstresssupergetbyidjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/super-get-by-id.js (0 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/super-get-by-id.js                                (rev 0)
+++ trunk/JSTests/stress/super-get-by-id.js        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -0,0 +1,205 @@
</span><ins>+&quot;use strict&quot;;
+
+function assert(a) {
+    if (!a)
+        throw new Error(&quot;Bad!&quot;);
+}
+
+var Base = class Base {
+    constructor() { this._name = &quot;Name&quot;; }
+    get name() { return this._name; } // If this instead returns a static: return &quot;Foo&quot; things somewhat work.
+    set name(x) { this._name = x; }
+};
+
+var Subclass = class Subclass extends Base {
+    get name() { return super.name; }
+};
+
+function getterName(instance) {
+    return instance.name;
+}
+
+noInline(getterName);
+
+function getterValue(instance) {
+    return instance.value;
+}
+
+noInline(getterValue);
+
+const runTimes = 10000;
+
+// Base case
+var instance = new Subclass;
+for (let i = 0; i &lt; runTimes; i++)
+  assert(getterName(instance) == &quot;Name&quot;);
+
+// Polymorphic case
+
+class PolymorphicSubclass {
+    get value() { return super.value; }
+};
+
+let numPolymorphicClasses = 4;
+let subclasses = new Array(numPolymorphicClasses);
+for (let i = 0; i &lt; numPolymorphicClasses; i++) {
+    let BaseCode = `
+       class Base${i} {
+            get value() { return this._value; }
+        };
+    `;
+
+    let Base = eval(BaseCode);
+    subclasses[i] = new PolymorphicSubclass();
+    subclasses[i]._value = i;
+
+    Object.setPrototypeOf(subclasses[i], Base.prototype);
+}
+
+for (let i = 0; i &lt; runTimes; i++) {
+    let index = i % numPolymorphicClasses;
+    let value = getterValue(subclasses[index]);
+    assert(value == index);
+}
+
+// Megamorphic case
+
+let nClasses = 1000;
+class MegamorphicSubclass {
+    get value() { return super.value; }
+};
+
+subclasses = new Array(nClasses);
+for (let i = 0; i &lt; nClasses; i++) {
+    let BaseCode = `
+       class Base${i + 4} {
+            get value() { return this._value; }
+        };
+    `;
+
+    let Base = eval(BaseCode);
+    subclasses[i] = new MegamorphicSubclass();
+    subclasses[i]._value = i;
+
+    Object.setPrototypeOf(subclasses[i], Base.prototype);
+}
+
+for (let i = 0; i &lt; runTimes; i++) {
+    let index = i % nClasses;
+    let value = getterValue(subclasses[index]);
+    assert(value == index);
+}
+
+// CustomGetter case
+
+let customGetter = createCustomGetterObject();
+Object.setPrototypeOf(customGetter, Object.prototype);
+
+let subObj = {
+    __proto__: customGetter,
+    get value () {
+        return super.customGetterAccessor;
+    }
+}
+
+for (let i = 0; i &lt; runTimes; i++) {
+    let value = getterValue(subObj);
+    assert(value == 100);
+}
+
+subObj.shouldThrow = true;
+for (let i = 0; i &lt; runTimes; i++) {
+    try {
+        getterValue(subObj);
+        assert(false);
+    } catch(e) {
+        assert(e instanceof TypeError);
+    };
+}
+
+// CustomValue case
+
+customGetter = createCustomGetterObject();
+Object.setPrototypeOf(customGetter, Object.prototype);
+
+subObj = {
+    __proto__: customGetter,
+    get value () {
+        return super.customGetter;
+    }
+}
+
+for (let i = 0; i &lt; runTimes; i++) {
+    let value = getterValue(subObj);
+    assert(value == 100);
+}
+
+subObj.shouldThrow = true;
+for (let i = 0; i &lt; runTimes; i++) {
+    let value = getterValue(subObj);
+    assert(value == 100);
+}
+
+// Exception handling case
+
+class BaseException {
+    constructor() { this._name = &quot;Name&quot;; }
+    get name() {
+        if (this.shouldThrow)
+            throw new Error(&quot;Forced Exception&quot;);
+        return this._name;
+    }
+};
+
+class SubclassException extends BaseException {
+    get name() { return super.name; }
+};
+
+let eObj = new SubclassException;
+for (let i = 0; i &lt; runTimes; i++)
+  assert(getterName(eObj) == &quot;Name&quot;);
+
+eObj.shouldThrow = true;
+for (let i = 0; i &lt; runTimes; i++) {
+    try {
+        getterValue(eObj);
+        assert(false);
+    } catch(e) {
+        eObj.shouldThrow = false;
+        assert(getterName(eObj) == &quot;Name&quot;);
+    };
+}
+
+// In getter exception handling
+
+class BaseExceptionComplex {
+    constructor() { this._name = &quot;Name&quot;; }
+    foo () {
+        if (this.shouldThrow)
+            throw new Error(&quot;Forced Exception&quot;);
+    }
+    get name() {
+        this.foo();
+        return this._name;
+    }
+};
+
+class SubclassExceptionComplex extends BaseExceptionComplex {
+    get name() {
+        try {
+            return super.name;
+        } catch(e) {
+            this.shouldThrow = false;
+            return super.name;
+        }
+    }
+};
+
+eObj = new SubclassExceptionComplex;
+for (let i = 0; i &lt; runTimes; i++)
+  assert(getterName(eObj) == &quot;Name&quot;);
+
+eObj.shouldThrow = true;
+for (let i = 0; i &lt; runTimes; i++)
+    assert(getterName(eObj) == &quot;Name&quot;);
+
</ins></span></pre></div>
<a id="trunkJSTestsstresssupergetterreseticjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/super-getter-reset-ic.js (0 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/super-getter-reset-ic.js                                (rev 0)
+++ trunk/JSTests/stress/super-getter-reset-ic.js        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+let assert = (a) =&gt; {
+    if (!a)
+        throw &quot;Bad!&quot;;
+}
+
+let n = 200;
+
+let A =  {
+    c: 42
+}
+
+let C = {
+    __proto__: A
+}
+
+let B = {
+    __proto__: C,
+    f(i) {
+        return super.c;
+    }
+}
+
+var result = 0;
+for (var i = 0; i &lt; n; ++i) {
+    if (i == n / 2 ) {
+        // This operation is going to force op_get_by_id_with_this to be regenerated 
+        Object.defineProperty(A, &quot;c&quot;, {get: () =&gt; 12});
+    }
+    result += B.f(i);
+}
+
+assert(result, 5400);
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -1,3 +1,81 @@
</span><ins>+2017-03-06  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        op_get_by_id_with_this should use inline caching
+        https://bugs.webkit.org/show_bug.cgi?id=162124
+
+        Reviewed by Saam Barati.
+
+        This patch is enabling inline cache for op_get_by_id_with_this in all
+        tiers. It means that operations using ```super.member``` are going to
+        be able to be optimized by PIC. To enable it, we introduced a new
+        member of StructureStubInfo.patch named thisGPR, created a new class
+        to manage the IC named JITGetByIdWithThisGenerator and changed
+        PolymorphicAccess.regenerate that uses StructureStubInfo.patch.thisGPR
+        to decide the correct this value on inline caches.
+        With inline cached enabled, ```super.member``` are ~4.5x faster,
+        according microbenchmarks.
+
+        * bytecode/AccessCase.cpp:
+        (JSC::AccessCase::generateImpl):
+        * bytecode/PolymorphicAccess.cpp:
+        (JSC::PolymorphicAccess::regenerate):
+        * bytecode/PolymorphicAccess.h:
+        * bytecode/StructureStubInfo.cpp:
+        (JSC::StructureStubInfo::reset):
+        * bytecode/StructureStubInfo.h:
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::link):
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::addGetByIdWithThis):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileIn):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::cachedGetByIdWithThis):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::cachedGetByIdWithThis):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetByIdWithThis):
+        (JSC::FTL::DFG::LowerDFGToB3::compileIn):
+        (JSC::FTL::DFG::LowerDFGToB3::getByIdWithThis):
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::setupArgumentsWithExecState):
+        * jit/ICStats.h:
+        * jit/JIT.cpp:
+        (JSC::JIT::JIT):
+        (JSC::JIT::privateCompileSlowCases):
+        (JSC::JIT::link):
+        * jit/JIT.h:
+        * jit/JITInlineCacheGenerator.cpp:
+        (JSC::JITByIdGenerator::JITByIdGenerator):
+        (JSC::JITGetByIdWithThisGenerator::JITGetByIdWithThisGenerator):
+        (JSC::JITGetByIdWithThisGenerator::generateFastPath):
+        * jit/JITInlineCacheGenerator.h:
+        (JSC::JITGetByIdWithThisGenerator::JITGetByIdWithThisGenerator):
+        * jit/JITInlines.h:
+        (JSC::JIT::callOperation):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_get_by_id_with_this):
+        (JSC::JIT::emitSlow_op_get_by_id_with_this):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emit_op_get_by_id_with_this):
+        (JSC::JIT::emitSlow_op_get_by_id_with_this):
+        * jit/Repatch.cpp:
+        (JSC::appropriateOptimizingGetByIdFunction):
+        (JSC::appropriateGenericGetByIdFunction):
+        (JSC::tryCacheGetByID):
+        * jit/Repatch.h:
+        * jsc.cpp:
+        (WTF::CustomGetter::getOwnPropertySlot):
+        (WTF::CustomGetter::customGetterAcessor):
+
</ins><span class="cx"> 2017-03-06  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: implement init_expr for Element
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeAccessCasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -418,6 +418,7 @@
</span><span class="cx">     const Identifier&amp; ident = *state.ident;
</span><span class="cx">     JSValueRegs valueRegs = state.valueRegs;
</span><span class="cx">     GPRReg baseGPR = state.baseGPR;
</span><ins>+    GPRReg thisGPR = state.thisGPR != InvalidGPRReg ? state.thisGPR : baseGPR;
</ins><span class="cx">     GPRReg scratchGPR = state.scratchGPR;
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_conditionSet.structuresEnsureValidityAssumingImpurePropertyWatchpoint());
</span><span class="lines">@@ -665,7 +666,7 @@
</span><span class="cx">                 loadedValueGPR, calleeFrame.withOffset(CallFrameSlot::callee * sizeof(Register)));
</span><span class="cx"> 
</span><span class="cx">             jit.storeCell(
</span><del>-                baseGPR,
</del><ins>+                thisGPR,
</ins><span class="cx">                 calleeFrame.withOffset(virtualRegisterForArgument(0).offset() * sizeof(Register)));
</span><span class="cx"> 
</span><span class="cx">             if (m_type == Setter) {
</span><span class="lines">@@ -725,28 +726,31 @@
</span><span class="cx">             // to make some space here.
</span><span class="cx">             jit.makeSpaceOnStackForCCall();
</span><span class="cx"> 
</span><ins>+            // Check if it is a super access
+            GPRReg baseForCustomGetGPR = baseGPR != thisGPR ? thisGPR : baseForGetGPR;
+
</ins><span class="cx">             // getter: EncodedJSValue (*GetValueFunc)(ExecState*, EncodedJSValue thisValue, PropertyName);
</span><span class="cx">             // setter: void (*PutValueFunc)(ExecState*, EncodedJSValue thisObject, EncodedJSValue value);
</span><span class="cx">             // Custom values are passed the slotBase (the property holder), custom accessors are passed the thisVaule (reciever).
</span><span class="cx">             // FIXME: Remove this differences in custom values and custom accessors.
</span><span class="cx">             // https://bugs.webkit.org/show_bug.cgi?id=158014
</span><del>-            GPRReg baseForCustomValue = m_type == CustomValueGetter || m_type == CustomValueSetter ? baseForAccessGPR : baseForGetGPR;
</del><ins>+            GPRReg baseForCustom = m_type == CustomValueGetter || m_type == CustomValueSetter ? baseForAccessGPR : baseForCustomGetGPR; 
</ins><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">             if (m_type == CustomValueGetter || m_type == CustomAccessorGetter) {
</span><span class="cx">                 jit.setupArgumentsWithExecState(
</span><del>-                    baseForCustomValue,
</del><ins>+                    baseForCustom,
</ins><span class="cx">                     CCallHelpers::TrustedImmPtr(ident.impl()));
</span><span class="cx">             } else
</span><del>-                jit.setupArgumentsWithExecState(baseForCustomValue, valueRegs.gpr());
</del><ins>+                jit.setupArgumentsWithExecState(baseForCustom, valueRegs.gpr());
</ins><span class="cx"> #else
</span><span class="cx">             if (m_type == CustomValueGetter || m_type == CustomAccessorGetter) {
</span><span class="cx">                 jit.setupArgumentsWithExecState(
</span><del>-                    EABI_32BIT_DUMMY_ARG baseForCustomValue,
</del><ins>+                    EABI_32BIT_DUMMY_ARG baseForCustom,
</ins><span class="cx">                     CCallHelpers::TrustedImm32(JSValue::CellTag),
</span><span class="cx">                     CCallHelpers::TrustedImmPtr(ident.impl()));
</span><span class="cx">             } else {
</span><span class="cx">                 jit.setupArgumentsWithExecState(
</span><del>-                    EABI_32BIT_DUMMY_ARG baseForCustomValue,
</del><ins>+                    EABI_32BIT_DUMMY_ARG baseForCustom,
</ins><span class="cx">                     CCallHelpers::TrustedImm32(JSValue::CellTag),
</span><span class="cx">                     valueRegs.payloadGPR(), valueRegs.tagGPR());
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -343,11 +343,14 @@
</span><span class="cx">     state.ident = &amp;ident;
</span><span class="cx">     
</span><span class="cx">     state.baseGPR = static_cast&lt;GPRReg&gt;(stubInfo.patch.baseGPR);
</span><ins>+    state.thisGPR = static_cast&lt;GPRReg&gt;(stubInfo.patch.thisGPR);
</ins><span class="cx">     state.valueRegs = stubInfo.valueRegs();
</span><span class="cx"> 
</span><span class="cx">     ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
</span><span class="cx">     state.allocator = &amp;allocator;
</span><span class="cx">     allocator.lock(state.baseGPR);
</span><ins>+    if (state.thisGPR != InvalidGPRReg)
+        allocator.lock(state.thisGPR);
</ins><span class="cx">     allocator.lock(state.valueRegs);
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">     allocator.lock(static_cast&lt;GPRReg&gt;(stubInfo.patch.baseTagGPR));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -192,6 +192,7 @@
</span><span class="cx">     MacroAssembler::JumpList failAndRepatch;
</span><span class="cx">     MacroAssembler::JumpList failAndIgnore;
</span><span class="cx">     GPRReg baseGPR { InvalidGPRReg };
</span><ins>+    GPRReg thisGPR { InvalidGPRReg };
</ins><span class="cx">     JSValueRegs valueRegs;
</span><span class="cx">     GPRReg scratchGPR { InvalidGPRReg };
</span><span class="cx">     const Identifier* ident;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -222,6 +222,9 @@
</span><span class="cx">     case AccessType::Get:
</span><span class="cx">         resetGetByID(codeBlock, *this, GetByIDKind::Normal);
</span><span class="cx">         break;
</span><ins>+    case AccessType::GetWithThis:
+        resetGetByID(codeBlock, *this, GetByIDKind::WithThis);
+        break;
</ins><span class="cx">     case AccessType::Put:
</span><span class="cx">         resetPutByID(codeBlock, *this);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> 
</span><span class="cx"> enum class AccessType : int8_t {
</span><span class="cx">     Get,
</span><ins>+    GetWithThis,
</ins><span class="cx">     TryGet,
</span><span class="cx">     Put,
</span><span class="cx">     In
</span><span class="lines">@@ -177,9 +178,11 @@
</span><span class="cx"> 
</span><span class="cx">         int8_t baseGPR;
</span><span class="cx">         int8_t valueGPR;
</span><ins>+        int8_t thisGPR;
</ins><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">         int8_t valueTagGPR;
</span><span class="cx">         int8_t baseTagGPR;
</span><ins>+        int8_t thisTagGPR;
</ins><span class="cx"> #endif
</span><span class="cx">     } patch;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -1250,6 +1250,14 @@
</span><span class="cx">                 fixEdge&lt;CellUse&gt;(node-&gt;child1());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        
+        case GetByIdWithThis: {
+            if (node-&gt;child1()-&gt;shouldSpeculateCell() &amp;&amp; node-&gt;child2()-&gt;shouldSpeculateCell()) {
+                fixEdge&lt;CellUse&gt;(node-&gt;child1());
+                fixEdge&lt;CellUse&gt;(node-&gt;child2());
+            }
+            break;
+        }
</ins><span class="cx"> 
</span><span class="cx">         case PutById:
</span><span class="cx">         case PutByIdFlush:
</span><span class="lines">@@ -1877,7 +1885,6 @@
</span><span class="cx">         case ExitOK:
</span><span class="cx">         case BottomValue:
</span><span class="cx">         case TypeOf:
</span><del>-        case GetByIdWithThis:
</del><span class="cx">         case PutByIdWithThis:
</span><span class="cx">         case PutByValWithThis:
</span><span class="cx">         case GetByValWithThis:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -253,6 +253,8 @@
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = m_getByIds.size(); i--;)
</span><span class="cx">         m_getByIds[i].finalize(linkBuffer);
</span><ins>+    for (unsigned i = m_getByIdsWithThis.size(); i--;)
+        m_getByIdsWithThis[i].finalize(linkBuffer);
</ins><span class="cx">     for (unsigned i = m_putByIds.size(); i--;)
</span><span class="cx">         m_putByIds[i].finalize(linkBuffer);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -197,6 +197,11 @@
</span><span class="cx">         m_getByIds.append(InlineCacheWrapper&lt;JITGetByIdGenerator&gt;(gen, slowPath));
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void addGetByIdWithThis(const JITGetByIdWithThisGenerator&amp; gen, SlowPathGenerator* slowPath)
+    {
+        m_getByIdsWithThis.append(InlineCacheWrapper&lt;JITGetByIdWithThisGenerator&gt;(gen, slowPath));
+    }
+    
</ins><span class="cx">     void addPutById(const JITPutByIdGenerator&amp; gen, SlowPathGenerator* slowPath)
</span><span class="cx">     {
</span><span class="cx">         m_putByIds.append(InlineCacheWrapper&lt;JITPutByIdGenerator&gt;(gen, slowPath));
</span><span class="lines">@@ -339,6 +344,7 @@
</span><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     Vector&lt;InlineCacheWrapper&lt;JITGetByIdGenerator&gt;, 4&gt; m_getByIds;
</span><ins>+    Vector&lt;InlineCacheWrapper&lt;JITGetByIdWithThisGenerator&gt;, 4&gt; m_getByIdsWithThis;
</ins><span class="cx">     Vector&lt;InlineCacheWrapper&lt;JITPutByIdGenerator&gt;, 4&gt; m_putByIds;
</span><span class="cx">     Vector&lt;InRecord, 4&gt; m_ins;
</span><span class="cx">     Vector&lt;JSCallRecord, 4&gt; m_jsCalls;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -1063,9 +1063,11 @@
</span><span class="cx">             stubInfo-&gt;codeOrigin = node-&gt;origin.semantic;
</span><span class="cx">             stubInfo-&gt;patch.baseGPR = static_cast&lt;int8_t&gt;(baseGPR);
</span><span class="cx">             stubInfo-&gt;patch.valueGPR = static_cast&lt;int8_t&gt;(resultGPR);
</span><ins>+            stubInfo-&gt;patch.thisGPR = static_cast&lt;int8_t&gt;(InvalidGPRReg);
</ins><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">             stubInfo-&gt;patch.valueTagGPR = static_cast&lt;int8_t&gt;(InvalidGPRReg);
</span><span class="cx">             stubInfo-&gt;patch.baseTagGPR = static_cast&lt;int8_t&gt;(InvalidGPRReg);
</span><ins>+            stubInfo-&gt;patch.thisTagGPR = static_cast&lt;int8_t&gt;(InvalidGPRReg);
</ins><span class="cx"> #endif
</span><span class="cx">             stubInfo-&gt;patch.usedRegisters = usedRegisters();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -772,9 +772,11 @@
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     void cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill, AccessType = AccessType::Get);
</span><span class="cx">     void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
</span><ins>+    void cachedGetByIdWithThis(CodeOrigin, GPRReg baseGPR, GPRReg thisGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget = JITCompiler::JumpList());
</ins><span class="cx"> #elif USE(JSVALUE32_64)
</span><span class="cx">     void cachedGetById(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill, AccessType = AccessType::Get);
</span><span class="cx">     void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
</span><ins>+    void cachedGetByIdWithThis(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg thisTagGPROrNone, GPRReg thisPayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget = JITCompiler::JumpList());
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void compileDeleteById(Node*);
</span><span class="lines">@@ -1563,6 +1565,11 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
</span><span class="cx">         return appendCallSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_ESsiJJI operation, GPRReg result, StructureStubInfo* stubInfo, GPRReg arg1, GPRReg arg2, UniquedStringImpl* uid)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, arg2, TrustedImmPtr(uid));
+        return appendCallSetResult(operation, result);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_EDA operation, GPRReg result, FPRReg arg1, GPRReg arg2)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2);
</span><span class="lines">@@ -2128,11 +2135,26 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1.payloadGPR(), arg1.tagGPR(), TrustedImmPtr(uid));
</span><span class="cx">         return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_ESsiJJI operation, JSValueRegs result, StructureStubInfo* stubInfo, JSValueRegs arg1, JSValueRegs arg2, UniquedStringImpl* uid)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), TrustedImmPtr(uid));
+        return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
+    }
+    JITCompiler::Call callOperation(J_JITOperation_ESsiJJI operation, JSValueRegs result, StructureStubInfo* stubInfo, int32_t arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, UniquedStringImpl* uid)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, TrustedImm32(arg1Tag), arg2Payload, arg2Tag, TrustedImmPtr(uid));
+        return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_ESsiJI operation, JSValueRegs result, StructureStubInfo* stubInfo, int32_t arg1Tag, GPRReg arg1Payload, UniquedStringImpl* uid)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, TrustedImm32(arg1Tag), TrustedImmPtr(uid));
</span><span class="cx">         return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_ESsiJJI operation, JSValueRegs result, StructureStubInfo* stubInfo, int32_t arg1Tag, GPRReg arg1Payload, int32_t arg2Tag, GPRReg arg2Payload, UniquedStringImpl* uid)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, TrustedImm32(arg1Tag), arg2Payload, TrustedImm32(arg2Tag), TrustedImmPtr(uid));
+        return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_ESsiJI operation, JSValueRegs result, StructureStubInfo* stubInfo, GPRReg arg1Tag, GPRReg arg1Payload, UniquedStringImpl* uid)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, arg1Tag, TrustedImmPtr(uid));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -230,6 +230,45 @@
</span><span class="cx">     addSlowPathGenerator(WTFMove(slowPath));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::cachedGetByIdWithThis(
+    CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg thisTagGPR, GPRReg thisPayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR,
+    unsigned identifierNumber, JITCompiler::JumpList slowPathTarget)
+{
+    RegisterSet usedRegisters = this-&gt;usedRegisters();
+    
+    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream-&gt;size());
+    JITGetByIdWithThisGenerator gen(
+        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
+        JSValueRegs(resultTagGPR, resultPayloadGPR), JSValueRegs(baseTagGPROrNone, basePayloadGPR), JSValueRegs(thisTagGPR, thisPayloadGPR), AccessType::GetWithThis);
+    
+    gen.generateFastPath(m_jit);
+    
+    JITCompiler::JumpList slowCases;
+    if (!slowPathTarget.empty())
+        slowCases.append(slowPathTarget);
+    slowCases.append(gen.slowPathJump());
+
+    std::unique_ptr&lt;SlowPathGenerator&gt; slowPath;
+    if (baseTagGPROrNone == InvalidGPRReg &amp;&amp; thisTagGPR == InvalidGPRReg) {
+        slowPath = slowPathCall(
+            slowCases, this, operationGetByIdWithThisOptimize,
+            JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(),
+            static_cast&lt;int32_t&gt;(JSValue::CellTag), basePayloadGPR,
+            static_cast&lt;int32_t&gt;(JSValue::CellTag), thisPayloadGPR,
+            identifierUID(identifierNumber));
+    } else {
+        ASSERT(baseTagGPROrNone != InvalidGPRReg);
+        ASSERT(thisTagGPR != InvalidGPRReg);
+        
+        slowPath = slowPathCall(
+            slowCases, this, operationGetByIdWithThisOptimize,
+            JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(), JSValueRegs(baseTagGPROrNone, basePayloadGPR), JSValueRegs(thisTagGPR, thisPayloadGPR), identifierUID(identifierNumber));
+    }
+
+    m_jit.addGetByIdWithThis(gen, slowPath.get());
+    addSlowPathGenerator(WTFMove(slowPath));
+}
+
</ins><span class="cx"> void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
</span><span class="cx"> {
</span><span class="cx">     RegisterSet usedRegisters = this-&gt;usedRegisters();
</span><span class="lines">@@ -4291,21 +4330,42 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case GetByIdWithThis: {
</span><del>-        JSValueOperand base(this, node-&gt;child1());
-        JSValueRegs baseRegs = base.jsValueRegs();
-        JSValueOperand thisValue(this, node-&gt;child2());
-        JSValueRegs thisRegs = thisValue.jsValueRegs();
-
-        GPRFlushedCallResult resultPayload(this);
-        GPRFlushedCallResult2 resultTag(this);
-        GPRReg resultPayloadGPR = resultPayload.gpr();
-        GPRReg resultTagGPR = resultTag.gpr();
-
-        flushRegisters();
-        callOperation(operationGetByIdWithThis, JSValueRegs(resultTagGPR, resultPayloadGPR), baseRegs, thisRegs, identifierUID(node-&gt;identifierNumber()));
-        m_jit.exceptionCheck();
-
-        jsValueResult(resultTagGPR, resultPayloadGPR, node);
</del><ins>+        if (node-&gt;child1().useKind() == CellUse &amp;&amp; node-&gt;child2().useKind() == CellUse) {
+            SpeculateCellOperand base(this, node-&gt;child1());
+            SpeculateCellOperand thisValue(this, node-&gt;child2());
+            GPRTemporary resultTag(this);
+            GPRTemporary resultPayload(this);
+            
+            GPRReg baseGPR = base.gpr();
+            GPRReg thisGPR = thisValue.gpr();
+            GPRReg resultTagGPR = resultTag.gpr();
+            GPRReg resultPayloadGPR = resultPayload.gpr();
+            
+            cachedGetByIdWithThis(node-&gt;origin.semantic, InvalidGPRReg, baseGPR, InvalidGPRReg, thisGPR, resultTagGPR, resultPayloadGPR, node-&gt;identifierNumber());
+            
+            jsValueResult(resultTagGPR, resultPayloadGPR, node);
+        } else {
+            JSValueOperand base(this, node-&gt;child1());
+            JSValueOperand thisValue(this, node-&gt;child2());
+            GPRTemporary resultTag(this);
+            GPRTemporary resultPayload(this);
+            
+            GPRReg baseTagGPR = base.tagGPR();
+            GPRReg basePayloadGPR = base.payloadGPR();
+            GPRReg thisTagGPR = thisValue.tagGPR();
+            GPRReg thisPayloadGPR = thisValue.payloadGPR();
+            GPRReg resultTagGPR = resultTag.gpr();
+            GPRReg resultPayloadGPR = resultPayload.gpr();
+            
+            JITCompiler::JumpList notCellList;
+            notCellList.append(m_jit.branchIfNotCell(base.jsValueRegs()));
+            notCellList.append(m_jit.branchIfNotCell(thisValue.jsValueRegs()));
+            
+            cachedGetByIdWithThis(node-&gt;origin.semantic, baseTagGPR, basePayloadGPR, thisTagGPR, thisPayloadGPR, resultTagGPR, resultPayloadGPR, node-&gt;identifierNumber(), notCellList);
+            
+            jsValueResult(resultTagGPR, resultPayloadGPR, node);
+        }
+        
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -188,6 +188,34 @@
</span><span class="cx">     addSlowPathGenerator(WTFMove(slowPath));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::cachedGetByIdWithThis(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg thisGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget)
+{
+    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream-&gt;size());
+    RegisterSet usedRegisters = this-&gt;usedRegisters();
+    // We've already flushed registers to the stack, we don't need to spill these.
+    usedRegisters.set(baseGPR, false);
+    usedRegisters.set(thisGPR, false);
+    usedRegisters.set(resultGPR, false);
+    
+    JITGetByIdWithThisGenerator gen(
+        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
+        JSValueRegs(resultGPR), JSValueRegs(baseGPR), JSValueRegs(thisGPR), AccessType::GetWithThis);
+    gen.generateFastPath(m_jit);
+    
+    JITCompiler::JumpList slowCases;
+    if (!slowPathTarget.empty())
+        slowCases.append(slowPathTarget);
+    slowCases.append(gen.slowPathJump());
+    
+    auto slowPath = slowPathCall(
+        slowCases, this, operationGetByIdWithThisOptimize,
+        DontSpill, ExceptionCheckRequirement::CheckNeeded,
+        resultGPR, gen.stubInfo(), baseGPR, thisGPR, identifierUID(identifierNumber));
+    
+    m_jit.addGetByIdWithThis(gen, slowPath.get());
+    addSlowPathGenerator(WTFMove(slowPath));
+}
+
</ins><span class="cx"> void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
</span><span class="cx"> {
</span><span class="cx">     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream-&gt;size());
</span><span class="lines">@@ -4310,19 +4338,41 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case GetByIdWithThis: {
</span><del>-        JSValueOperand base(this, node-&gt;child1());
-        GPRReg baseGPR = base.gpr();
-        JSValueOperand thisValue(this, node-&gt;child2());
-        GPRReg thisValueGPR = thisValue.gpr();
-
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-
-        flushRegisters();
-        callOperation(operationGetByIdWithThis, resultGPR, baseGPR, thisValueGPR, identifierUID(node-&gt;identifierNumber()));
-        m_jit.exceptionCheck();
-
-        jsValueResult(resultGPR, node);
</del><ins>+        if (node-&gt;child1().useKind() == CellUse &amp;&amp; node-&gt;child2().useKind() == CellUse) {
+            SpeculateCellOperand base(this, node-&gt;child1());
+            GPRReg baseGPR = base.gpr();
+            SpeculateCellOperand thisValue(this, node-&gt;child2());
+            GPRReg thisValueGPR = thisValue.gpr();
+            
+            GPRFlushedCallResult result(this);
+            GPRReg resultGPR = result.gpr();
+            
+            flushRegisters();
+            
+            cachedGetByIdWithThis(node-&gt;origin.semantic, baseGPR, thisValueGPR, resultGPR, node-&gt;identifierNumber(), JITCompiler::JumpList());
+            
+            jsValueResult(resultGPR, node);
+            
+        } else {
+            JSValueOperand base(this, node-&gt;child1());
+            GPRReg baseGPR = base.gpr();
+            JSValueOperand thisValue(this, node-&gt;child2());
+            GPRReg thisValueGPR = thisValue.gpr();
+            
+            GPRFlushedCallResult result(this);
+            GPRReg resultGPR = result.gpr();
+            
+            flushRegisters();
+            
+            JITCompiler::JumpList notCellList;
+            notCellList.append(m_jit.branchIfNotCell(JSValueRegs(baseGPR)));
+            notCellList.append(m_jit.branchIfNotCell(JSValueRegs(thisValueGPR)));
+            
+            cachedGetByIdWithThis(node-&gt;origin.semantic, baseGPR, thisValueGPR, resultGPR, node-&gt;identifierNumber(), notCellList);
+            
+            jsValueResult(resultGPR, node);
+        }
+        
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -2869,10 +2869,40 @@
</span><span class="cx"> 
</span><span class="cx">     void compileGetByIdWithThis()
</span><span class="cx">     {
</span><del>-        LValue base = lowJSValue(m_node-&gt;child1());
-        LValue thisValue = lowJSValue(m_node-&gt;child2());
-        LValue result = vmCall(Int64, m_out.operation(operationGetByIdWithThis), m_callFrame, base, thisValue, m_out.constIntPtr(m_graph.identifiers()[m_node-&gt;identifierNumber()]));
-        setJSValue(result);
</del><ins>+        if (m_node-&gt;child1().useKind() == CellUse &amp;&amp; m_node-&gt;child2().useKind() == CellUse)
+            setJSValue(getByIdWithThis(lowCell(m_node-&gt;child1()), lowCell(m_node-&gt;child2())));
+        else {
+            LValue base = lowJSValue(m_node-&gt;child1());
+            LValue thisValue = lowJSValue(m_node-&gt;child2());
+            
+            LBasicBlock baseCellCase = m_out.newBlock();
+            LBasicBlock notCellCase = m_out.newBlock();
+            LBasicBlock thisValueCellCase = m_out.newBlock();
+            LBasicBlock continuation = m_out.newBlock();
+            
+            m_out.branch(
+                isCell(base, provenType(m_node-&gt;child1())), unsure(baseCellCase), unsure(notCellCase));
+            
+            LBasicBlock lastNext = m_out.appendTo(baseCellCase, thisValueCellCase);
+            
+            m_out.branch(
+                isCell(thisValue, provenType(m_node-&gt;child2())), unsure(thisValueCellCase), unsure(notCellCase));
+            
+            m_out.appendTo(thisValueCellCase, notCellCase);
+            ValueFromBlock cellResult = m_out.anchor(getByIdWithThis(base, thisValue));
+            m_out.jump(continuation);
+
+            m_out.appendTo(notCellCase, continuation);
+            ValueFromBlock notCellResult = m_out.anchor(vmCall(
+                Int64, m_out.operation(operationGetByIdWithThis),
+                m_callFrame, base, thisValue,
+                m_out.constIntPtr(m_graph.identifiers()[m_node-&gt;identifierNumber()])));
+            m_out.jump(continuation);
+            
+            m_out.appendTo(continuation, lastNext);
+            setJSValue(m_out.phi(Int64, cellResult, notCellResult));
+        }
+        
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void compileGetByValWithThis()
</span><span class="lines">@@ -8079,6 +8109,7 @@
</span><span class="cx">                         stubInfo-&gt;codeOrigin = node-&gt;origin.semantic;
</span><span class="cx">                         stubInfo-&gt;patch.baseGPR = static_cast&lt;int8_t&gt;(baseGPR);
</span><span class="cx">                         stubInfo-&gt;patch.valueGPR = static_cast&lt;int8_t&gt;(resultGPR);
</span><ins>+                        stubInfo-&gt;patch.thisGPR = static_cast&lt;int8_t&gt;(InvalidGPRReg);
</ins><span class="cx">                         stubInfo-&gt;patch.usedRegisters = params.unavailableRegisters();
</span><span class="cx"> 
</span><span class="cx">                         CCallHelpers::PatchableJump jump = jit.patchableJump();
</span><span class="lines">@@ -9763,7 +9794,75 @@
</span><span class="cx"> 
</span><span class="cx">         return patchpoint;
</span><span class="cx">     }
</span><ins>+    
+    LValue getByIdWithThis(LValue base, LValue thisValue)
+    {
+        Node* node = m_node;
+        UniquedStringImpl* uid = m_graph.identifiers()[node-&gt;identifierNumber()];
</ins><span class="cx"> 
</span><ins>+        B3::PatchpointValue* patchpoint = m_out.patchpoint(Int64);
+        patchpoint-&gt;appendSomeRegister(base);
+        patchpoint-&gt;appendSomeRegister(thisValue);
+        patchpoint-&gt;append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
+        patchpoint-&gt;append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
+
+        patchpoint-&gt;clobber(RegisterSet::macroScratchRegisters());
+
+        RefPtr&lt;PatchpointExceptionHandle&gt; exceptionHandle =
+            preparePatchpointForExceptions(patchpoint);
+
+        State* state = &amp;m_ftlState;
+        patchpoint-&gt;setGenerator(
+            [=] (CCallHelpers&amp; jit, const StackmapGenerationParams&amp; params) {
+                AllowMacroScratchRegisterUsage allowScratch(jit);
+
+                CallSiteIndex callSiteIndex =
+                    state-&gt;jitCode-&gt;common.addUniqueCallSiteIndex(node-&gt;origin.semantic);
+
+                // This is the direct exit target for operation calls.
+                Box&lt;CCallHelpers::JumpList&gt; exceptions =
+                    exceptionHandle-&gt;scheduleExitCreation(params)-&gt;jumps(jit);
+
+                // This is the exit for call IC's created by the getById for getters. We don't have
+                // to do anything weird other than call this, since it will associate the exit with
+                // the callsite index.
+                exceptionHandle-&gt;scheduleExitCreationForUnwind(params, callSiteIndex);
+
+                auto generator = Box&lt;JITGetByIdWithThisGenerator&gt;::create(
+                    jit.codeBlock(), node-&gt;origin.semantic, callSiteIndex,
+                    params.unavailableRegisters(), uid, JSValueRegs(params[0].gpr()),
+                    JSValueRegs(params[1].gpr()), JSValueRegs(params[2].gpr()), AccessType::GetWithThis);
+
+                generator-&gt;generateFastPath(jit);
+                CCallHelpers::Label done = jit.label();
+
+                params.addLatePath(
+                    [=] (CCallHelpers&amp; jit) {
+                        AllowMacroScratchRegisterUsage allowScratch(jit);
+
+                        J_JITOperation_ESsiJJI optimizationFunction = operationGetByIdWithThisOptimize;
+
+                        generator-&gt;slowPathJump().link(&amp;jit);
+                        CCallHelpers::Label slowPathBegin = jit.label();
+                        CCallHelpers::Call slowPathCall = callOperation(
+                            *state, params.unavailableRegisters(), jit, node-&gt;origin.semantic,
+                            exceptions.get(), optimizationFunction, params[0].gpr(),
+                            CCallHelpers::TrustedImmPtr(generator-&gt;stubInfo()), params[1].gpr(),
+                            params[2].gpr(), CCallHelpers::TrustedImmPtr(uid)).call();
+                        jit.jump().linkTo(done, &amp;jit);
+
+                        generator-&gt;reportSlowPathCall(slowPathBegin, slowPathCall);
+
+                        jit.addLinkTask(
+                            [=] (LinkBuffer&amp; linkBuffer) {
+                                generator-&gt;finalize(linkBuffer);
+                            });
+                    });
+            });
+
+        return patchpoint;
+    }
+
</ins><span class="cx">     LValue isFastTypedArray(LValue object)
</span><span class="cx">     {
</span><span class="cx">         return m_out.equal(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCCallHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CCallHelpers.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -724,6 +724,18 @@
</span><span class="cx">         addCallArgument(arg3);
</span><span class="cx">         addCallArgument(arg4);
</span><span class="cx">     }
</span><ins>+    
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, TrustedImm32 arg5, TrustedImmPtr arg6)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+        addCallArgument(arg4);
+        addCallArgument(arg5);
+        addCallArgument(arg6);
+    }
</ins><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3, GPRReg arg4)
</span><span class="cx">     {
</span><span class="lines">@@ -735,6 +747,18 @@
</span><span class="cx">         addCallArgument(arg4);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5, TrustedImmPtr arg6)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+        addCallArgument(arg4);
+        addCallArgument(arg5);
+        addCallArgument(arg6);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, GPRReg arg3, GPRReg arg4)
</span><span class="cx">     {
</span><span class="cx">         resetCallArguments();
</span><span class="lines">@@ -1693,6 +1717,22 @@
</span><span class="cx">         poke(arg4, POKE_ARGUMENT_OFFSET);
</span><span class="cx">         setupArgumentsWithExecState(arg1, arg2, arg3);
</span><span class="cx">     }
</span><ins>+    
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5, TrustedImmPtr arg6)
+    {
+        poke(arg6, POKE_ARGUMENT_OFFSET + 2);
+        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
+        poke(arg4, POKE_ARGUMENT_OFFSET);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
+    
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, TrustedImm32 arg5, TrustedImmPtr arg6)
+    {
+        poke(arg6, POKE_ARGUMENT_OFFSET + 2);
+        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
+        poke(arg4, POKE_ARGUMENT_OFFSET);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
</ins><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitICStatsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ICStats.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ICStats.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/ICStats.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx">     macro(OperationGetByIdGeneric) \
</span><span class="cx">     macro(OperationGetByIdBuildList) \
</span><span class="cx">     macro(OperationGetByIdOptimize) \
</span><ins>+    macro(OperationGetByIdWithThisOptimize) \
</ins><span class="cx">     macro(OperationInOptimize) \
</span><span class="cx">     macro(OperationIn) \
</span><span class="cx">     macro(OperationGenericIn) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -83,6 +83,7 @@
</span><span class="cx">     , m_labels(codeBlock ? codeBlock-&gt;numberOfInstructions() : 0)
</span><span class="cx">     , m_bytecodeOffset(std::numeric_limits&lt;unsigned&gt;::max())
</span><span class="cx">     , m_getByIdIndex(UINT_MAX)
</span><ins>+    , m_getByIdWithThisIndex(UINT_MAX)
</ins><span class="cx">     , m_putByIdIndex(UINT_MAX)
</span><span class="cx">     , m_byValInstructionIndex(UINT_MAX)
</span><span class="cx">     , m_callLinkInfoIndex(UINT_MAX)
</span><span class="lines">@@ -437,6 +438,7 @@
</span><span class="cx">     Instruction* instructionsBegin = m_codeBlock-&gt;instructions().begin();
</span><span class="cx"> 
</span><span class="cx">     m_getByIdIndex = 0;
</span><ins>+    m_getByIdWithThisIndex = 0;
</ins><span class="cx">     m_putByIdIndex = 0;
</span><span class="cx">     m_byValInstructionIndex = 0;
</span><span class="cx">     m_callLinkInfoIndex = 0;
</span><span class="lines">@@ -492,6 +494,7 @@
</span><span class="cx">         case op_get_by_id_proto_load:
</span><span class="cx">         case op_get_by_id_unset:
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_get_by_id)
</span><ins>+        DEFINE_SLOWCASE_OP(op_get_by_id_with_this)
</ins><span class="cx">         DEFINE_SLOWCASE_OP(op_get_by_val)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_instanceof)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_instanceof_custom)
</span><span class="lines">@@ -551,6 +554,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(m_getByIdIndex == m_getByIds.size());
</span><ins>+    RELEASE_ASSERT(m_getByIdWithThisIndex == m_getByIdsWithThis.size());
</ins><span class="cx">     RELEASE_ASSERT(m_putByIdIndex == m_putByIds.size());
</span><span class="cx">     RELEASE_ASSERT(m_callLinkInfoIndex == m_callCompilationInfo.size());
</span><span class="cx">     RELEASE_ASSERT(numberOfValueProfiles == m_codeBlock-&gt;numberOfValueProfiles());
</span><span class="lines">@@ -773,6 +777,8 @@
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = m_getByIds.size(); i--;)
</span><span class="cx">         m_getByIds[i].finalize(patchBuffer);
</span><ins>+    for (unsigned i = m_getByIdsWithThis.size(); i--;)
+        m_getByIdsWithThis[i].finalize(patchBuffer);
</ins><span class="cx">     for (unsigned i = m_putByIds.size(); i--;)
</span><span class="cx">         m_putByIds[i].finalize(patchBuffer);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -623,6 +623,7 @@
</span><span class="cx">         void emitSlow_op_get_callee(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_try_get_by_id(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_get_by_id(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><ins>+        void emitSlow_op_get_by_id_with_this(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</ins><span class="cx">         void emitSlow_op_get_arguments_length(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_get_by_val(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_get_argument_by_val(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="lines">@@ -759,9 +760,11 @@
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, UniquedStringImpl*);
</span><span class="cx">         MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, UniquedStringImpl*);
</span><ins>+        MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJJI, int, StructureStubInfo*, GPRReg, GPRReg, UniquedStringImpl*);
</ins><span class="cx"> #else
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, GPRReg, UniquedStringImpl*);
</span><span class="cx">         MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, GPRReg, UniquedStringImpl*);
</span><ins>+        MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJJI, int, StructureStubInfo*, GPRReg, GPRReg, GPRReg, GPRReg, UniquedStringImpl*);
</ins><span class="cx"> #endif
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJI, int, GPRReg, UniquedStringImpl*);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg);
</span><span class="lines">@@ -932,6 +935,7 @@
</span><span class="cx">         Vector&lt;CallRecord&gt; m_calls;
</span><span class="cx">         Vector&lt;Label&gt; m_labels;
</span><span class="cx">         Vector&lt;JITGetByIdGenerator&gt; m_getByIds;
</span><ins>+        Vector&lt;JITGetByIdWithThisGenerator&gt; m_getByIdsWithThis;
</ins><span class="cx">         Vector&lt;JITPutByIdGenerator&gt; m_putByIds;
</span><span class="cx">         Vector&lt;ByValCompilationInfo&gt; m_byValCompilationInfo;
</span><span class="cx">         Vector&lt;CallCompilationInfo&gt; m_callCompilationInfo;
</span><span class="lines">@@ -946,6 +950,7 @@
</span><span class="cx">         Label m_exceptionHandler;
</span><span class="cx"> 
</span><span class="cx">         unsigned m_getByIdIndex;
</span><ins>+        unsigned m_getByIdWithThisIndex;
</ins><span class="cx">         unsigned m_putByIdIndex;
</span><span class="cx">         unsigned m_byValInstructionIndex;
</span><span class="cx">         unsigned m_callLinkInfoIndex;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlineCacheGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -62,9 +62,11 @@
</span><span class="cx">     
</span><span class="cx">     m_stubInfo-&gt;patch.baseGPR = static_cast&lt;int8_t&gt;(base.payloadGPR());
</span><span class="cx">     m_stubInfo-&gt;patch.valueGPR = static_cast&lt;int8_t&gt;(value.payloadGPR());
</span><ins>+    m_stubInfo-&gt;patch.thisGPR = static_cast&lt;int8_t&gt;(InvalidGPRReg);
</ins><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">     m_stubInfo-&gt;patch.baseTagGPR = static_cast&lt;int8_t&gt;(base.tagGPR());
</span><span class="cx">     m_stubInfo-&gt;patch.valueTagGPR = static_cast&lt;int8_t&gt;(value.tagGPR());
</span><ins>+    m_stubInfo-&gt;patch.thisTagGPR = static_cast&lt;int8_t&gt;(InvalidGPRReg);
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -116,6 +118,24 @@
</span><span class="cx">     generateFastCommon(jit, m_isLengthAccess ? InlineAccess::sizeForLengthAccess() : InlineAccess::sizeForPropertyAccess());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JITGetByIdWithThisGenerator::JITGetByIdWithThisGenerator(
+    CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet&amp; usedRegisters,
+    UniquedStringImpl*, JSValueRegs value, JSValueRegs base, JSValueRegs thisRegs, AccessType accessType)
+    : JITByIdGenerator(codeBlock, codeOrigin, callSite, accessType, usedRegisters, base, value)
+{
+    RELEASE_ASSERT(thisRegs.payloadGPR() != thisRegs.tagGPR());
+
+    m_stubInfo-&gt;patch.thisGPR = static_cast&lt;int8_t&gt;(thisRegs.payloadGPR());
+#if USE(JSVALUE32_64)
+    m_stubInfo-&gt;patch.thisTagGPR = static_cast&lt;int8_t&gt;(thisRegs.tagGPR());
+#endif
+}
+
+void JITGetByIdWithThisGenerator::generateFastPath(MacroAssembler&amp; jit)
+{
+    generateFastCommon(jit, InlineAccess::sizeForPropertyAccess());
+}
+
</ins><span class="cx"> JITPutByIdGenerator::JITPutByIdGenerator(
</span><span class="cx">     CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet&amp; usedRegisters,
</span><span class="cx">     JSValueRegs base, JSValueRegs value, GPRReg scratch, 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlineCacheGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -107,6 +107,17 @@
</span><span class="cx">     bool m_isLengthAccess;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class JITGetByIdWithThisGenerator : public JITByIdGenerator {
+public:
+    JITGetByIdWithThisGenerator() { }
+
+    JITGetByIdWithThisGenerator(
+        CodeBlock*, CodeOrigin, CallSiteIndex, const RegisterSet&amp; usedRegisters, UniquedStringImpl* propertyName,
+        JSValueRegs value, JSValueRegs base, JSValueRegs thisRegs, AccessType);
+
+    void generateFastPath(MacroAssembler&amp;);
+};
+
</ins><span class="cx"> class JITPutByIdGenerator : public JITByIdGenerator {
</span><span class="cx"> public:
</span><span class="cx">     JITPutByIdGenerator() { }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlines.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -518,6 +518,12 @@
</span><span class="cx">     return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_ESsiJJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1, GPRReg arg2, UniquedStringImpl* uid)
+{
+    setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, arg2, TrustedImmPtr(uid));
+    return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst);
+}
+
</ins><span class="cx"> ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_EJJ operation, int dst, GPRReg arg1, GPRReg arg2)
</span><span class="cx"> {
</span><span class="cx">     setupArgumentsWithExecState(arg1, arg2);
</span><span class="lines">@@ -704,6 +710,12 @@
</span><span class="cx">     return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_ESsiJJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, UniquedStringImpl* uid)
+{
+    setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, arg1Tag, arg2Payload, arg2Tag, TrustedImmPtr(uid));
+    return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst);
+}
+
</ins><span class="cx"> ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJ operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
</span><span class="cx"> {
</span><span class="cx">     setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2Payload, arg2Tag);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -265,6 +265,43 @@
</span><span class="cx">     }));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JIT_OPERATION operationGetByIdWithThisGeneric(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, EncodedJSValue thisEncoded, UniquedStringImpl* uid)
+{
+    SuperSamplerScope superSamplerScope(false);
+
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    Identifier ident = Identifier::fromUid(vm, uid);
+
+    stubInfo-&gt;tookSlowPath = true;
+
+    JSValue baseValue = JSValue::decode(base);
+    JSValue thisValue = JSValue::decode(thisEncoded);
+    PropertySlot slot(thisValue, PropertySlot::InternalMethodType::Get);
+
+    return JSValue::encode(baseValue.get(exec, ident, slot));
+}
+
+EncodedJSValue JIT_OPERATION operationGetByIdWithThisOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, EncodedJSValue thisEncoded, UniquedStringImpl* uid)
+{
+    SuperSamplerScope superSamplerScope(false);
+    
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    Identifier ident = Identifier::fromUid(vm, uid);
+
+    JSValue baseValue = JSValue::decode(base);
+    JSValue thisValue = JSValue::decode(thisEncoded);
+    LOG_IC((ICEvent::OperationGetByIdWithThisOptimize, baseValue.classInfoOrNull(*vm), ident));
+
+    PropertySlot slot(thisValue, PropertySlot::InternalMethodType::Get);
+    return JSValue::encode(baseValue.getPropertySlot(exec, ident, slot, [&amp;] (bool found, PropertySlot&amp; slot) -&gt; JSValue {
+        if (stubInfo-&gt;considerCaching(exec-&gt;codeBlock(), baseValue.structureOrNull()))
+            repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::WithThis);
+        return found ? slot.getValue(exec, ident) : jsUndefined();
+    }));
+}
+
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
</span><span class="cx"> {
</span><span class="cx">     SuperSamplerScope superSamplerScope(false);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -170,6 +170,7 @@
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_ESS)(ExecState*, size_t, size_t);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_ESsiCI)(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_ESsiJI)(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*);
</span><ins>+typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_ESsiJJI)(ExecState*, StructureStubInfo*, EncodedJSValue, EncodedJSValue, UniquedStringImpl*);
</ins><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EZ)(ExecState*, int32_t);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EZIcfZ)(ExecState*, int32_t, InlineCallFrame*, int32_t);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EZZ)(ExecState*, int32_t, int32_t);
</span><span class="lines">@@ -337,6 +338,8 @@
</span><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><ins>+EncodedJSValue JIT_OPERATION operationGetByIdWithThisGeneric(ExecState*, StructureStubInfo*, EncodedJSValue, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationGetByIdWithThisOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGenericIn(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -632,8 +632,25 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_get_by_id_with_this(Instruction* currentInstruction)
</span><span class="cx"> {
</span><del>-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_by_id_with_this);
-    slowPathCall.call();
</del><ins>+    int resultVReg = currentInstruction[1].u.operand;
+    int baseVReg = currentInstruction[2].u.operand;
+    int thisVReg = currentInstruction[3].u.operand;
+    const Identifier* ident = &amp;(m_codeBlock-&gt;identifier(currentInstruction[4].u.operand));
+
+    emitGetVirtualRegister(baseVReg, regT0);
+    emitGetVirtualRegister(thisVReg, regT1);
+    emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
+    emitJumpSlowCaseIfNotJSCell(regT1, thisVReg);
+
+    JITGetByIdWithThisGenerator gen(
+        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
+        ident-&gt;impl(), JSValueRegs(regT0), JSValueRegs(regT0), JSValueRegs(regT1), AccessType::GetWithThis);
+    gen.generateFastPath(*this);
+    addSlowCase(gen.slowPathJump());
+    m_getByIdsWithThis.append(gen);
+
+    emitValueProfilingSite();
+    emitPutVirtualRegister(resultVReg);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_get_by_val_with_this(Instruction* currentInstruction)
</span><span class="lines">@@ -660,6 +677,26 @@
</span><span class="cx">     gen.reportSlowPathCall(coldPathBegin, call);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emitSlow_op_get_by_id_with_this(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    int resultVReg = currentInstruction[1].u.operand;
+    int baseVReg = currentInstruction[2].u.operand;
+    int thisVReg = currentInstruction[3].u.operand;
+    const Identifier* ident = &amp;(m_codeBlock-&gt;identifier(currentInstruction[4].u.operand));
+
+    linkSlowCaseIfNotJSCell(iter, baseVReg);
+    linkSlowCaseIfNotJSCell(iter, thisVReg);
+    linkSlowCase(iter);
+
+    JITGetByIdWithThisGenerator&amp; gen = m_getByIdsWithThis[m_getByIdWithThisIndex++];
+    
+    Label coldPathBegin = label();
+    
+    Call call = callOperation(WithProfile, operationGetByIdWithThisOptimize, resultVReg, gen.stubInfo(), regT0, regT1, ident-&gt;impl());
+
+    gen.reportSlowPathCall(coldPathBegin, call);
+}
+
</ins><span class="cx"> void JIT::emit_op_put_by_id(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     int baseVReg = currentInstruction[1].u.operand;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -663,6 +663,49 @@
</span><span class="cx">     gen.reportSlowPathCall(coldPathBegin, call);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_get_by_id_with_this(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int thisVReg = currentInstruction[3].u.operand;
+    const Identifier* ident = &amp;(m_codeBlock-&gt;identifier(currentInstruction[4].u.operand));
+    
+    emitLoad(base, regT1, regT0);
+    emitLoad(thisVReg, regT4, regT3);
+    emitJumpSlowCaseIfNotJSCell(base, regT1);
+    emitJumpSlowCaseIfNotJSCell(thisVReg, regT4);
+
+    JITGetByIdWithThisGenerator gen(
+        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
+        ident-&gt;impl(), JSValueRegs(regT1, regT0), JSValueRegs::payloadOnly(regT0), JSValueRegs(regT4, regT3), AccessType::GetWithThis);
+    gen.generateFastPath(*this);
+    addSlowCase(gen.slowPathJump());
+    m_getByIdsWithThis.append(gen);
+
+    emitValueProfilingSite();
+    emitStore(dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_get_by_id_with_this(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    int resultVReg = currentInstruction[1].u.operand;
+    int baseVReg = currentInstruction[2].u.operand;
+    int thisVReg = currentInstruction[3].u.operand;
+    const Identifier* ident = &amp;(m_codeBlock-&gt;identifier(currentInstruction[4].u.operand));
+
+    linkSlowCaseIfNotJSCell(iter, baseVReg);
+    linkSlowCaseIfNotJSCell(iter, thisVReg);
+    linkSlowCase(iter);
+
+    JITGetByIdWithThisGenerator&amp; gen = m_getByIdsWithThis[m_getByIdWithThisIndex++];
+    
+    Label coldPathBegin = label();
+    
+    Call call = callOperation(WithProfile, operationGetByIdWithThisOptimize, resultVReg, gen.stubInfo(), regT1, regT0, regT4, regT3, ident-&gt;impl());
+    
+    gen.reportSlowPathCall(coldPathBegin, call);
+}
+
</ins><span class="cx"> void JIT::emit_op_put_by_id(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     // In order to be able to patch both the Structure, and the object offset, we store one pointer,
</span><span class="lines">@@ -1166,12 +1209,6 @@
</span><span class="cx">     store32(regT2, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier&lt;Unknown&gt;) + PayloadOffset));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emit_op_get_by_id_with_this(Instruction* currentInstruction)
-{
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_by_id_with_this);
-    slowPathCall.call();
-}
-
</del><span class="cx"> void JIT::emit_op_get_by_val_with_this(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_by_val_with_this);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -139,17 +139,21 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline J_JITOperation_ESsiJI appropriateOptimizingGetByIdFunction(GetByIDKind kind)
</del><ins>+inline FunctionPtr appropriateOptimizingGetByIdFunction(GetByIDKind kind)
</ins><span class="cx"> {
</span><span class="cx">     if (kind == GetByIDKind::Normal)
</span><span class="cx">         return operationGetByIdOptimize;
</span><ins>+    else if (kind == GetByIDKind::WithThis)
+        return operationGetByIdWithThisOptimize;
</ins><span class="cx">     return operationTryGetByIdOptimize;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline J_JITOperation_ESsiJI appropriateGenericGetByIdFunction(GetByIDKind kind)
</del><ins>+inline FunctionPtr appropriateGenericGetByIdFunction(GetByIDKind kind)
</ins><span class="cx"> {
</span><span class="cx">     if (kind == GetByIDKind::Normal)
</span><span class="cx">         return operationGetById;
</span><ins>+    else if (kind == GetByIDKind::WithThis)
+        return operationGetByIdWithThisGeneric;
</ins><span class="cx">     return operationTryGetById;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -304,6 +308,10 @@
</span><span class="cx">                 else
</span><span class="cx">                     type = AccessCase::CustomValueGetter;
</span><span class="cx"> 
</span><ins>+                // we don't emit IC for DOMJIT when op is get_by_id_with_this
+                if (Options::useDOMJIT() &amp;&amp; kind == GetByIDKind::WithThis &amp;&amp; type == AccessCase::CustomAccessorGetter &amp;&amp; domJIT)
+                    return GiveUpOnCache;
+
</ins><span class="cx">                 newCase = GetterSetterAccessCase::create(
</span><span class="cx">                     vm, codeBlock, type, offset, structure, conditionSet, loadTargetFromProxy,
</span><span class="cx">                     slot.watchpointSet(), slot.isCacheableCustom() ? slot.customGetter() : nullptr,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.h (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.h        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jit/Repatch.h        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -36,7 +36,8 @@
</span><span class="cx"> 
</span><span class="cx"> enum class GetByIDKind {
</span><span class="cx">     Normal,
</span><del>-    Try
</del><ins>+    Try,
+    WithThis
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> void repatchGetByID(ExecState*, JSValue, const Identifier&amp;, const PropertySlot&amp;, StructureStubInfo&amp;, GetByIDKind);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (213466 => 213467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2017-03-06 21:45:38 UTC (rev 213466)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2017-03-06 22:03:56 UTC (rev 213467)
</span><span class="lines">@@ -371,6 +371,12 @@
</span><span class="cx">             slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject-&gt;customGetter);
</span><span class="cx">             return true;
</span><span class="cx">         }
</span><ins>+        
+        if (propertyName == PropertyName(Identifier::fromString(exec, &quot;customGetterAccessor&quot;))) {
+            slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum | CustomAccessor, thisObject-&gt;customGetterAcessor);
+            return true;
+        }
+        
</ins><span class="cx">         return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -388,6 +394,20 @@
</span><span class="cx">             return throwVMTypeError(exec, scope);
</span><span class="cx">         return JSValue::encode(jsNumber(100));
</span><span class="cx">     }
</span><ins>+    
+    static EncodedJSValue customGetterAcessor(ExecState* exec, EncodedJSValue thisValue, PropertyName)
+    {
+        VM&amp; vm = exec-&gt;vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
+        
+        JSObject* thisObject = jsDynamicCast&lt;JSObject*&gt;(vm, JSValue::decode(thisValue));
+        if (!thisObject)
+            return throwVMTypeError(exec, scope);
+        bool shouldThrow = thisObject-&gt;get(exec, PropertyName(Identifier::fromString(exec, &quot;shouldThrow&quot;))).toBoolean(exec);
+        if (shouldThrow)
+            return throwVMTypeError(exec, scope);
+        return JSValue::encode(jsNumber(100));
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class RuntimeArray : public JSArray {
</span></span></pre>
</div>
</div>

</body>
</html>