No subject


Tue May 3 15:05:30 PDT 2016


"This [assertion that register allocations are not branched around] protects
against the case where an allocation could have spilled register contents to free
up a register and that spill only occurs on one path of many through the code.
A subsequent fill of the spilled register may load garbage."

Because the branch isn't always emitted, this bug has gone unnoticed until now.
This patch fixes this issue by pre-allocating the registers before emitting the
branch in OverrideHasInstance.

Note: this issue is only present in DFGSpeculativeJIT64.cpp.  The 32-bit version
is doing it right.

* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):</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="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressOverrideHasInstanceshouldnotbranchacrossregisterallocationsjs">trunk/JSTests/stress/OverrideHasInstance-should-not-branch-across-register-allocations.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (204402 => 204403)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog	2016-08-12 01:33:48 UTC (rev 204402)
+++ trunk/JSTests/ChangeLog	2016-08-12 03:38:54 UTC (rev 204403)
</span><span class="lines">@@ -1,5 +1,15 @@
</span><span class="cx"> 2016-08-11  Mark Lam  &lt;mark.lam at apple.com&gt;
</span><span class="cx"> 
</span><ins>+        OverridesHasInstance should not branch across register allocations.
+        https://bugs.webkit.org/show_bug.cgi?id=160792
+        &lt;rdar://problem/27361778&gt;
+
+        Reviewed by Benjamin Poulain.
+
+        * stress/OverrideHasInstance-should-not-branch-across-register-allocations.js: Added.
+
+2016-08-11  Mark Lam  &lt;mark.lam at apple.com&gt;
+
</ins><span class="cx">         The jsc shell's Element host constructor should throw if it fails to construct an object.
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=160773
</span><span class="cx">         &lt;rdar://problem/27328608&gt;
</span></span></pre></div>
<a id="trunkJSTestsstressOverrideHasInstanceshouldnotbranchacrossregisterallocationsjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/OverrideHasInstance-should-not-branch-across-register-allocations.js (0 => 204403)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/OverrideHasInstance-should-not-branch-across-register-allocations.js	                        (rev 0)
+++ trunk/JSTests/stress/OverrideHasInstance-should-not-branch-across-register-allocations.js	2016-08-12 03:38:54 UTC (rev 204403)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+//@ runDefault
+
+// This test should not crash.
+
+delete this.Function;
+
+var test = function() { 
+    Math.cos(&quot;0&quot; instanceof arguments)
+}
+
+for (var k = 0; k &lt; 10000; ++k) {
+    try {
+        test();
+    } catch (e) {
+    }
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (204402 => 204403)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog	2016-08-12 01:33:48 UTC (rev 204402)
+++ trunk/Source/JavaScriptCore/ChangeLog	2016-08-12 03:38:54 UTC (rev 204403)
</span><span class="lines">@@ -1,3 +1,31 @@
</span><ins>+2016-08-11  Mark Lam  &lt;mark.lam at apple.com&gt;
+
+        OverridesHasInstance should not branch across register allocations.
+        https://bugs.webkit.org/show_bug.cgi?id=160792
+        &lt;rdar://problem/27361778&gt;
+
+        Reviewed by Benjamin Poulain.
+
+        The OverrideHasInstance node has a branch test that is emitted conditionally.
+        It also has a bug where it allocated a register after this branch, which is not
+        allowed and would fail an assertion introduced in https://trac.webkit.org/r145931.
+        From the ChangeLog for r145931:
+
+        &quot;This [assertion that register allocations are not branched around] protects
+        against the case where an allocation could have spilled register contents to free
+        up a register and that spill only occurs on one path of many through the code.
+        A subsequent fill of the spilled register may load garbage.&quot;
+
+        Because the branch isn't always emitted, this bug has gone unnoticed until now.
+        This patch fixes this issue by pre-allocating the registers before emitting the
+        branch in OverrideHasInstance.
+
+        Note: this issue is only present in DFGSpeculativeJIT64.cpp.  The 32-bit version
+        is doing it right.
+
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
</ins><span class="cx"> 2016-08-11  Benjamin Poulain  &lt;bpoulain at apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Make B3 Return opcode work without arguments
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (204402 => 204403)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp	2016-08-12 01:33:48 UTC (rev 204402)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp	2016-08-12 03:38:54 UTC (rev 204403)
</span><span class="lines">@@ -4575,15 +4575,18 @@
</span><span class="cx">         GPRTemporary result(this);
</span><span class="cx"> 
</span><span class="cx">         GPRReg resultGPR = result.gpr();
</span><ins>+        GPRReg baseGPR = base.gpr();
</ins><span class="cx"> 
</span><span class="cx">         // It would be great if constant folding handled automatically the case where we knew the hasInstance function
</span><span class="cx">         // was a constant. Unfortunately, the folding rule for OverridesHasInstance is in the strength reduction phase
</span><span class="cx">         // since it relies on OSR information. https://bugs.webkit.org/show_bug.cgi?id=154832
</span><del>-        if (!hasInstanceValueNode-&gt;isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode-&gt;asCell())
-            notDefault = m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValue.gpr(), TrustedImmPtr(defaultHasInstanceFunction));
</del><ins>+        if (!hasInstanceValueNode-&gt;isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode-&gt;asCell()) {
+            GPRReg hasInstanceValueGPR = hasInstanceValue.gpr();
+            notDefault = m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueGPR, TrustedImmPtr(defaultHasInstanceFunction));
+        }
</ins><span class="cx"> 
</span><span class="cx">         // Check that base 'ImplementsDefaultHasInstance'.
</span><del>-        m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(base.gpr(), JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR);
</del><ins>+        m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR);
</ins><span class="cx">         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
</span><span class="cx">         MacroAssembler::Jump done = m_jit.jump();
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>


More information about the webkit-changes mailing list