<!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>[204206] 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/204206">204206</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-08-05 17:46:50 -0700 (Fri, 05 Aug 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>various math operations don't properly check for an exception after calling toNumber() on the lhs
https://bugs.webkit.org/show_bug.cgi?id=160154

Reviewed by Mark Lam.

JSTests:

* stress/to-number-throws-correct-exception.js: Added.
(test.let.test.runTest.):
(test.let.test.runTest.get f):
(test.let.test.runTest):
(test.let.test):
(test):
(test2.runTest.):
(test2.runTest.get f):
(test2.runTest):
(test2):

Source/JavaScriptCore:

We must check for an exception after calling toNumber() on the lhs
because this can throw an exception. If we called toNumber() on
the rhs without first checking for an exception after the toNumber()
on the lhs, this can lead us to execute effectful code or deviate
from the standard in subtle ways. I fixed this bug in various places
by always checking for an exception after calling toNumber() on the
lhs for the various bit and arithmetic operations.

This patch also found a commutativity bug inside DFGStrengthReduction.
We could end up commuting the lhs and rhs of say an &quot;|&quot; expression
even when the lhs/rhs may not be numbers. This is wrong because
executing toNumber() on the lhs/rhs has strict ordering guarantees
by the specification and is observable by user programs.

* dfg/DFGOperations.cpp:
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleCommutativity):
* jit/JITOperations.cpp:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/Operations.cpp:
(JSC::jsAddSlowCase):</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="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOperationscpp">trunk/Source/JavaScriptCore/runtime/Operations.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstresstonumberthrowscorrectexceptionjs">trunk/JSTests/stress/to-number-throws-correct-exception.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (204205 => 204206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/JSTests/ChangeLog        2016-08-06 00:46:50 UTC (rev 204206)
</span><span class="lines">@@ -1,5 +1,23 @@
</span><span class="cx"> 2016-08-05  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        various math operations don't properly check for an exception after calling toNumber() on the lhs
+        https://bugs.webkit.org/show_bug.cgi?id=160154
+
+        Reviewed by Mark Lam.
+
+        * stress/to-number-throws-correct-exception.js: Added.
+        (test.let.test.runTest.):
+        (test.let.test.runTest.get f):
+        (test.let.test.runTest):
+        (test.let.test):
+        (test):
+        (test2.runTest.):
+        (test2.runTest.get f):
+        (test2.runTest):
+        (test2):
+
+2016-08-05  Saam Barati  &lt;sbarati@apple.com&gt;
+
</ins><span class="cx">         Assertion failure when accessing TDZ variable in catch through eval
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=160554
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJSTestsstresstonumberthrowscorrectexceptionjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/to-number-throws-correct-exception.js (0 => 204206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/to-number-throws-correct-exception.js                                (rev 0)
+++ trunk/JSTests/stress/to-number-throws-correct-exception.js        2016-08-06 00:46:50 UTC (rev 204206)
</span><span class="lines">@@ -0,0 +1,121 @@
</span><ins>+function test(op) {
+    let test = `
+        function runTest(iters) {
+            let shouldThrow = false;
+            let a = {
+                valueOf() { 
+                    if (shouldThrow)
+                        throw &quot;a&quot;;
+                    return 0;
+                }
+            };
+            let {proxy: b, revoke} = Proxy.revocable({}, {
+                get: function(target, prop) {
+                    if (prop === &quot;valueOf&quot;) {
+                        if (shouldThrow)
+                            throw new Error(&quot;Should not be here!&quot;);
+                        return function() {
+                            return 0;
+                        }
+                    }
+                }
+            });
+            function f(a, b) {
+                return a ${op} b;
+            }
+            noInline(f);
+            for (let i = 0; i &lt; iters; i++) {
+                f(a, b);
+            }
+
+            shouldThrow = true;
+            let validException = false;
+            let exception = null;
+            revoke();
+            try {
+                f(a, b);
+            } catch(e) {
+                validException = e === &quot;a&quot;;
+                exception = e;
+            }
+            if (!validException)
+                throw new Error(&quot;Bad operation: &quot; + exception.toString() + &quot; with iters: &quot; + iters);
+        }
+        runTest(2);
+        runTest(10);
+        runTest(50);
+        runTest(1000);
+        runTest(10000);
+    `;
+    eval(test);
+}
+let ops = [
+    &quot;+&quot;
+    , &quot;-&quot;
+    , &quot;*&quot;
+    , &quot;**&quot;
+    , &quot;/&quot;
+    , &quot;%&quot;
+    , &quot;&amp;&quot;
+    , &quot;|&quot;
+    , &quot;^&quot;
+    , &quot;&gt;&gt;&quot;
+    , &quot;&gt;&gt;&gt;&quot;
+    , &quot;&lt;&lt;&quot;
+];
+for (let op of ops)
+    test(op);
+
+function test2(op) {
+    function runTest(iters) {
+        let test = `
+            let shouldThrow = false;
+            let a = {
+                valueOf() { 
+                    if (shouldThrow)
+                        throw &quot;a&quot;;
+                    return 0;
+                }
+            };
+            let {proxy: b, revoke} = Proxy.revocable({}, {
+                get: function(target, prop) {
+                    if (prop === &quot;valueOf&quot;) {
+                        if (shouldThrow)
+                            throw new Error(&quot;Should not be here!&quot;);
+                        return function() {
+                            return 0;
+                        }
+                    }
+                }
+            });
+            function f(a, b) {
+                return a ${op} b;
+            }
+            noInline(f);
+            for (let i = 0; i &lt; ${iters}; i++) {
+                f(a, b);
+            }
+
+            shouldThrow = true;
+            let validException = false;
+            let exception = null;
+            revoke();
+            try {
+                f(a, b);
+            } catch(e) {
+                validException = e === &quot;a&quot;;
+                exception = e;
+            }
+            if (!validException)
+                throw new Error(&quot;Bad operation: &quot; + exception.toString() + &quot; with iters: &quot; + ${iters});
+        `;
+        eval(Math.random() + &quot;;&quot; + test);
+    }
+    runTest(2);
+    runTest(10);
+    runTest(50);
+    runTest(1000);
+    runTest(10000);
+}
+for (let op of ops)
+    test2(op);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (204205 => 204206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-08-06 00:46:50 UTC (rev 204206)
</span><span class="lines">@@ -1,3 +1,33 @@
</span><ins>+2016-08-05  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        various math operations don't properly check for an exception after calling toNumber() on the lhs
+        https://bugs.webkit.org/show_bug.cgi?id=160154
+
+        Reviewed by Mark Lam.
+
+        We must check for an exception after calling toNumber() on the lhs
+        because this can throw an exception. If we called toNumber() on
+        the rhs without first checking for an exception after the toNumber()
+        on the lhs, this can lead us to execute effectful code or deviate
+        from the standard in subtle ways. I fixed this bug in various places
+        by always checking for an exception after calling toNumber() on the
+        lhs for the various bit and arithmetic operations.
+
+        This patch also found a commutativity bug inside DFGStrengthReduction.
+        We could end up commuting the lhs and rhs of say an &quot;|&quot; expression
+        even when the lhs/rhs may not be numbers. This is wrong because
+        executing toNumber() on the lhs/rhs has strict ordering guarantees
+        by the specification and is observable by user programs.
+
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleCommutativity):
+        * jit/JITOperations.cpp:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/Operations.cpp:
+        (JSC::jsAddSlowCase):
+
</ins><span class="cx"> 2016-08-05  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         compilePutByValForIntTypedArray() has a slow path in the middle of its processing
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (204205 => 204206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-08-06 00:46:50 UTC (rev 204206)
</span><span class="lines">@@ -210,6 +210,8 @@
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="cx">     int32_t a = op1.toInt32(exec);
</span><ins>+    if (UNLIKELY(vm-&gt;exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     int32_t b = op2.toInt32(exec);
</span><span class="cx">     return JSValue::encode(jsNumber(a &amp; b));
</span><span class="cx"> }
</span><span class="lines">@@ -223,6 +225,8 @@
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="cx">     int32_t a = op1.toInt32(exec);
</span><ins>+    if (UNLIKELY(vm-&gt;exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     int32_t b = op2.toInt32(exec);
</span><span class="cx">     return JSValue::encode(jsNumber(a | b));
</span><span class="cx"> }
</span><span class="lines">@@ -236,6 +240,8 @@
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="cx">     int32_t a = op1.toInt32(exec);
</span><ins>+    if (UNLIKELY(vm-&gt;exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     int32_t b = op2.toInt32(exec);
</span><span class="cx">     return JSValue::encode(jsNumber(a ^ b));
</span><span class="cx"> }
</span><span class="lines">@@ -249,6 +255,8 @@
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="cx">     int32_t a = op1.toInt32(exec);
</span><ins>+    if (UNLIKELY(vm-&gt;exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     uint32_t b = op2.toUInt32(exec);
</span><span class="cx">     return JSValue::encode(jsNumber(a &lt;&lt; (b &amp; 0x1f)));
</span><span class="cx"> }
</span><span class="lines">@@ -262,6 +270,8 @@
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="cx">     int32_t a = op1.toInt32(exec);
</span><ins>+    if (UNLIKELY(vm-&gt;exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     uint32_t b = op2.toUInt32(exec);
</span><span class="cx">     return JSValue::encode(jsNumber(a &gt;&gt; (b &amp; 0x1f)));
</span><span class="cx"> }
</span><span class="lines">@@ -275,6 +285,8 @@
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="cx">     uint32_t a = op1.toUInt32(exec);
</span><ins>+    if (UNLIKELY(vm-&gt;exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     uint32_t b = op2.toUInt32(exec);
</span><span class="cx">     return JSValue::encode(jsNumber(static_cast&lt;int32_t&gt;(a &gt;&gt; (b &amp; 0x1f))));
</span><span class="cx"> }
</span><span class="lines">@@ -304,6 +316,8 @@
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="cx">     double a = op1.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm-&gt;exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     double b = op2.toNumber(exec);
</span><span class="cx">     return JSValue::encode(jsNumber(a / b));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp (204205 => 204206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-08-06 00:46:50 UTC (rev 204206)
</span><span class="lines">@@ -744,6 +744,11 @@
</span><span class="cx">     
</span><span class="cx">     void handleCommutativity()
</span><span class="cx">     {
</span><ins>+        // It's definitely not sound to swap the lhs and rhs when we may be performing effectful
+        // calls on the lhs/rhs for valueOf.
+        if (m_node-&gt;child1().useKind() == UntypedUse || m_node-&gt;child2().useKind() == UntypedUse)
+            return;
+
</ins><span class="cx">         // If the right side is a constant then there is nothing left to do.
</span><span class="cx">         if (m_node-&gt;child2()-&gt;hasConstant())
</span><span class="cx">             return;
</span><span class="lines">@@ -750,7 +755,7 @@
</span><span class="cx">         
</span><span class="cx">         // This case ensures that optimizations that look for x + const don't also have
</span><span class="cx">         // to look for const + x.
</span><del>-        if (m_node-&gt;child1()-&gt;hasConstant()) {
</del><ins>+        if (m_node-&gt;child1()-&gt;hasConstant() &amp;&amp; !m_node-&gt;child1()-&gt;asJSValue().isCell()) {
</ins><span class="cx">             std::swap(m_node-&gt;child1(), m_node-&gt;child2());
</span><span class="cx">             m_changed = true;
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (204205 => 204206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-08-06 00:46:50 UTC (rev 204206)
</span><span class="lines">@@ -2354,17 +2354,19 @@
</span><span class="cx">     return JSValue::encode(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE static EncodedJSValue unprofiledMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</del><ins>+ALWAYS_INLINE static EncodedJSValue unprofiledMul(VM&amp; vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</ins><span class="cx"> {
</span><span class="cx">     JSValue op1 = JSValue::decode(encodedOp1);
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="cx">     double a = op1.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     double b = op2.toNumber(exec);
</span><span class="cx">     return JSValue::encode(jsNumber(a * b));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE static EncodedJSValue profiledMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
</del><ins>+ALWAYS_INLINE static EncodedJSValue profiledMul(VM&amp; vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
</ins><span class="cx"> {
</span><span class="cx">     JSValue op1 = JSValue::decode(encodedOp1);
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="lines">@@ -2373,7 +2375,11 @@
</span><span class="cx">         arithProfile-&gt;observeLHSAndRHS(op1, op2);
</span><span class="cx"> 
</span><span class="cx">     double a = op1.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     double b = op2.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     
</span><span class="cx">     JSValue result = jsNumber(a * b);
</span><span class="cx">     arithProfile-&gt;observeResult(result);
</span><span class="lines">@@ -2385,7 +2391,7 @@
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx"> 
</span><del>-    return unprofiledMul(exec, encodedOp1, encodedOp2);
</del><ins>+    return unprofiledMul(*vm, exec, encodedOp1, encodedOp2);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueMulNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC*)
</span><span class="lines">@@ -2393,7 +2399,7 @@
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx"> 
</span><del>-    return unprofiledMul(exec, encodedOp1, encodedOp2);
</del><ins>+    return unprofiledMul(*vm, exec, encodedOp1, encodedOp2);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueMulOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC* mulIC)
</span><span class="lines">@@ -2410,7 +2416,7 @@
</span><span class="cx">     exec-&gt;codeBlock()-&gt;dumpMathICStats();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    return unprofiledMul(exec, encodedOp1, encodedOp2);
</del><ins>+    return unprofiledMul(*vm, exec, encodedOp1, encodedOp2);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
</span><span class="lines">@@ -2418,7 +2424,7 @@
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx"> 
</span><del>-    return profiledMul(exec, encodedOp1, encodedOp2, arithProfile);
</del><ins>+    return profiledMul(*vm, exec, encodedOp1, encodedOp2, arithProfile);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueMulProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITMulIC* mulIC)
</span><span class="lines">@@ -2434,7 +2440,7 @@
</span><span class="cx">     exec-&gt;codeBlock()-&gt;dumpMathICStats();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    return profiledMul(exec, encodedOp1, encodedOp2, arithProfile, false);
</del><ins>+    return profiledMul(*vm, exec, encodedOp1, encodedOp2, arithProfile, false);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueMulProfiledNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITMulIC*)
</span><span class="lines">@@ -2442,20 +2448,22 @@
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx"> 
</span><del>-    return profiledMul(exec, encodedOp1, encodedOp2, arithProfile);
</del><ins>+    return profiledMul(*vm, exec, encodedOp1, encodedOp2, arithProfile);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE static EncodedJSValue unprofiledSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</del><ins>+ALWAYS_INLINE static EncodedJSValue unprofiledSub(VM&amp; vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</ins><span class="cx"> {
</span><span class="cx">     JSValue op1 = JSValue::decode(encodedOp1);
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="cx">     double a = op1.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     double b = op2.toNumber(exec);
</span><span class="cx">     return JSValue::encode(jsNumber(a - b));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE static EncodedJSValue profiledSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
</del><ins>+ALWAYS_INLINE static EncodedJSValue profiledSub(VM&amp; vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
</ins><span class="cx"> {
</span><span class="cx">     JSValue op1 = JSValue::decode(encodedOp1);
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="lines">@@ -2464,7 +2472,11 @@
</span><span class="cx">         arithProfile-&gt;observeLHSAndRHS(op1, op2);
</span><span class="cx"> 
</span><span class="cx">     double a = op1.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     double b = op2.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     
</span><span class="cx">     JSValue result = jsNumber(a - b);
</span><span class="cx">     arithProfile-&gt;observeResult(result);
</span><span class="lines">@@ -2475,7 +2487,7 @@
</span><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><del>-    return unprofiledSub(exec, encodedOp1, encodedOp2);
</del><ins>+    return unprofiledSub(*vm, exec, encodedOp1, encodedOp2);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
</span><span class="lines">@@ -2483,7 +2495,7 @@
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx"> 
</span><del>-    return profiledSub(exec, encodedOp1, encodedOp2, arithProfile);
</del><ins>+    return profiledSub(*vm, exec, encodedOp1, encodedOp2, arithProfile);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSubOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC* subIC)
</span><span class="lines">@@ -2500,7 +2512,7 @@
</span><span class="cx">     exec-&gt;codeBlock()-&gt;dumpMathICStats();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    return unprofiledSub(exec, encodedOp1, encodedOp2);
</del><ins>+    return unprofiledSub(*vm, exec, encodedOp1, encodedOp2);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSubNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC*)
</span><span class="lines">@@ -2508,7 +2520,7 @@
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx"> 
</span><del>-    return unprofiledSub(exec, encodedOp1, encodedOp2);
</del><ins>+    return unprofiledSub(*vm, exec, encodedOp1, encodedOp2);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSubProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITSubIC* subIC)
</span><span class="lines">@@ -2524,7 +2536,7 @@
</span><span class="cx">     exec-&gt;codeBlock()-&gt;dumpMathICStats();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    return profiledSub(exec, encodedOp1, encodedOp2, arithProfile, false);
</del><ins>+    return profiledSub(*vm, exec, encodedOp1, encodedOp2, arithProfile, false);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSubProfiledNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITSubIC*)
</span><span class="lines">@@ -2532,7 +2544,7 @@
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx"> 
</span><del>-    return profiledSub(exec, encodedOp1, encodedOp2, arithProfile);
</del><ins>+    return profiledSub(*vm, exec, encodedOp1, encodedOp2, arithProfile);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT_OPERATION operationProcessTypeProfilerLog(ExecState* exec)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (204205 => 204206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-08-06 00:46:50 UTC (rev 204206)
</span><span class="lines">@@ -434,6 +434,8 @@
</span><span class="cx">     JSValue left = OP_C(2).jsValue();
</span><span class="cx">     JSValue right = OP_C(3).jsValue();
</span><span class="cx">     double a = left.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     double b = right.toNumber(exec);
</span><span class="cx">     JSValue result = jsNumber(a * b);
</span><span class="cx">     RETURN_WITH_PROFILING(result, {
</span><span class="lines">@@ -447,6 +449,8 @@
</span><span class="cx">     JSValue left = OP_C(2).jsValue();
</span><span class="cx">     JSValue right = OP_C(3).jsValue();
</span><span class="cx">     double a = left.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     double b = right.toNumber(exec);
</span><span class="cx">     JSValue result = jsNumber(a - b);
</span><span class="cx">     RETURN_WITH_PROFILING(result, {
</span><span class="lines">@@ -460,7 +464,11 @@
</span><span class="cx">     JSValue left = OP_C(2).jsValue();
</span><span class="cx">     JSValue right = OP_C(3).jsValue();
</span><span class="cx">     double a = left.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     double b = right.toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     JSValue result = jsNumber(a / b);
</span><span class="cx">     RETURN_WITH_PROFILING(result, {
</span><span class="cx">         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
</span><span class="lines">@@ -471,6 +479,8 @@
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     double a = OP_C(2).jsValue().toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     double b = OP_C(3).jsValue().toNumber(exec);
</span><span class="cx">     RETURN(jsNumber(jsMod(a, b)));
</span><span class="cx"> }
</span><span class="lines">@@ -479,7 +489,11 @@
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     double a = OP_C(2).jsValue().toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     double b = OP_C(3).jsValue().toNumber(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     RETURN(jsNumber(operationMathPow(a, b)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -487,6 +501,8 @@
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     int32_t a = OP_C(2).jsValue().toInt32(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
</span><span class="cx">     RETURN(jsNumber(a &lt;&lt; (b &amp; 31)));
</span><span class="cx"> }
</span><span class="lines">@@ -495,6 +511,8 @@
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     int32_t a = OP_C(2).jsValue().toInt32(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
</span><span class="cx">     RETURN(jsNumber(a &gt;&gt; (b &amp; 31)));
</span><span class="cx"> }
</span><span class="lines">@@ -503,6 +521,8 @@
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
</span><span class="cx">     RETURN(jsNumber(static_cast&lt;int32_t&gt;(a &gt;&gt; (b &amp; 31))));
</span><span class="cx"> }
</span><span class="lines">@@ -518,6 +538,8 @@
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     int32_t a = OP_C(2).jsValue().toInt32(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     int32_t b = OP_C(3).jsValue().toInt32(exec);
</span><span class="cx">     RETURN(jsNumber(a &amp; b));
</span><span class="cx"> }
</span><span class="lines">@@ -526,6 +548,8 @@
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     int32_t a = OP_C(2).jsValue().toInt32(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     int32_t b = OP_C(3).jsValue().toInt32(exec);
</span><span class="cx">     RETURN(jsNumber(a | b));
</span><span class="cx"> }
</span><span class="lines">@@ -534,6 +558,8 @@
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     int32_t a = OP_C(2).jsValue().toInt32(exec);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
</ins><span class="cx">     int32_t b = OP_C(3).jsValue().toInt32(exec);
</span><span class="cx">     RETURN(jsNumber(a ^ b));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Operations.cpp (204205 => 204206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Operations.cpp        2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/JavaScriptCore/runtime/Operations.cpp        2016-08-06 00:46:50 UTC (rev 204206)
</span><span class="lines">@@ -43,8 +43,13 @@
</span><span class="cx"> NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
</span><span class="cx"> {
</span><span class="cx">     // exception for the Date exception in defaultValue()
</span><ins>+    VM&amp; vm = callFrame-&gt;vm();
</ins><span class="cx">     JSValue p1 = v1.toPrimitive(callFrame);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        return JSValue();
</ins><span class="cx">     JSValue p2 = v2.toPrimitive(callFrame);
</span><ins>+    if (UNLIKELY(vm.exception()))
+        return JSValue();
</ins><span class="cx"> 
</span><span class="cx">     if (p1.isString())
</span><span class="cx">         return jsString(callFrame, asString(p1), p2.toString(callFrame));
</span></span></pre>
</div>
</div>

</body>
</html>