<!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>[180736] releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore</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/180736">180736</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2015-02-27 03:57:41 -0800 (Fri, 27 Feb 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/180234">r180234</a> - Throwing from an FTL call IC slow path may result in tag registers being clobbered on 64-bit CPUs
https://bugs.webkit.org/show_bug.cgi?id=141717
rdar://problem/19863382

Reviewed by Geoffrey Garen.

The best solution is to ensure that the engine catching an exception restores tag registers.

Each of these new test cases reliably crashed prior to this patch and they don't crash at all now.

* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_catch):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter64.asm:
* tests/stress/throw-from-ftl-call-ic-slow-path-cells.js: Added.
* tests/stress/throw-from-ftl-call-ic-slow-path-undefined.js: Added.
* tests/stress/throw-from-ftl-call-ic-slow-path.js: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit28SourceJavaScriptCoreChangeLog">releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit28SourceJavaScriptCorejitJITOpcodescpp">releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit28SourceJavaScriptCorellintLowLevelInterpreterasm">releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#releasesWebKitGTKwebkit28SourceJavaScriptCorellintLowLevelInterpreter64asm">releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit28SourceJavaScriptCoretestsstressthrowfromftlcallicslowpathcellsjs">releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path-cells.js</a></li>
<li><a href="#releasesWebKitGTKwebkit28SourceJavaScriptCoretestsstressthrowfromftlcallicslowpathundefinedjs">releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path-undefined.js</a></li>
<li><a href="#releasesWebKitGTKwebkit28SourceJavaScriptCoretestsstressthrowfromftlcallicslowpathjs">releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit28SourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/ChangeLog (180735 => 180736)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/ChangeLog        2015-02-27 11:54:08 UTC (rev 180735)
+++ releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/ChangeLog        2015-02-27 11:57:41 UTC (rev 180736)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2015-02-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Throwing from an FTL call IC slow path may result in tag registers being clobbered on 64-bit CPUs
+        https://bugs.webkit.org/show_bug.cgi?id=141717
+        rdar://problem/19863382
+
+        Reviewed by Geoffrey Garen.
+        
+        The best solution is to ensure that the engine catching an exception restores tag registers.
+        
+        Each of these new test cases reliably crashed prior to this patch and they don't crash at all now.
+
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_catch):
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * tests/stress/throw-from-ftl-call-ic-slow-path-cells.js: Added.
+        * tests/stress/throw-from-ftl-call-ic-slow-path-undefined.js: Added.
+        * tests/stress/throw-from-ftl-call-ic-slow-path.js: Added.
+
</ins><span class="cx"> 2015-02-17  Csaba Osztrogonác  &lt;ossy@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [ARM] Add the necessary setupArgumentsWithExecState after bug141332
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit28SourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/jit/JITOpcodes.cpp (180735 => 180736)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-02-27 11:54:08 UTC (rev 180735)
+++ releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-02-27 11:57:41 UTC (rev 180736)
</span><span class="lines">@@ -492,6 +492,11 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_catch(Instruction* currentInstruction)
</span><span class="cx"> {
</span><ins>+    // Gotta restore the tag registers. We could be throwing from FTL, which may
+    // clobber them.
+    move(TrustedImm64(TagTypeNumber), tagTypeNumberRegister);
+    move(TrustedImm64(TagMask), tagMaskRegister);
+    
</ins><span class="cx">     move(TrustedImmPtr(m_vm), regT3);
</span><span class="cx">     load64(Address(regT3, VM::callFrameForThrowOffset()), callFrameRegister);
</span><span class="cx">     load64(Address(regT3, VM::vmEntryFrameForThrowOffset()), regT0);
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit28SourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (180735 => 180736)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-02-27 11:54:08 UTC (rev 180735)
+++ releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-02-27 11:57:41 UTC (rev 180736)
</span><span class="lines">@@ -66,6 +66,8 @@
</span><span class="cx">     const ValueTrue       = TagBitTypeOther | TagBitBool | 1
</span><span class="cx">     const ValueUndefined  = TagBitTypeOther | TagBitUndefined
</span><span class="cx">     const ValueNull       = TagBitTypeOther
</span><ins>+    const TagTypeNumber   = 0xffff000000000000
+    const TagMask         = TagTypeNumber | TagBitTypeOther
</ins><span class="cx"> else
</span><span class="cx">     const Int32Tag = -1
</span><span class="cx">     const BooleanTag = -2
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit28SourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (180735 => 180736)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-02-27 11:54:08 UTC (rev 180735)
+++ releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-02-27 11:57:41 UTC (rev 180736)
</span><span class="lines">@@ -1845,6 +1845,11 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> _llint_op_catch:
</span><ins>+    # Gotta restore the tag registers. We could be throwing from FTL, which may
+    # clobber them.
+    move TagTypeNumber, tagTypeNumber
+    move TagMask, tagMask
+    
</ins><span class="cx">     # This is where we end up from the JIT's throw trampoline (because the
</span><span class="cx">     # machine code return address will be set to _llint_op_catch), and from
</span><span class="cx">     # the interpreter's throw trampoline (see _llint_throw_trampoline).
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit28SourceJavaScriptCoretestsstressthrowfromftlcallicslowpathcellsjs"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path-cells.js (0 => 180736)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path-cells.js                                (rev 0)
+++ releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path-cells.js        2015-02-27 11:57:41 UTC (rev 180736)
</span><span class="lines">@@ -0,0 +1,192 @@
</span><ins>+// Attempts to induce a crash resulting from the FTL emitting code that clobbers the tag registers and then
+// throwing an exception without restoring those tag registers' values.
+
+function ftlFunction(array, callee) {
+    // Gotta use lots of gprs.
+    var x0 = array[0];
+    var x1 = array[1];
+    var x2 = array[2];
+    var x3 = array[3];
+    var x4 = array[4];
+    var x5 = array[5];
+    var x6 = array[6];
+    var x7 = array[7];
+    var x8 = array[8];
+    var x9 = array[9];
+    var x10 = array[10];
+    var x11 = array[11];
+    var x12 = array[12];
+    var x13 = array[13];
+    var x14 = array[14];
+    var x15 = array[15];
+    var x16 = array[16];
+    var x17 = array[17];
+    var x18 = array[18];
+    var x19 = array[19];
+    var x20 = array[20];
+    var x21 = array[21];
+    var x22 = array[22];
+    var x23 = array[23];
+    var x24 = array[24];
+    var x25 = array[25];
+    var x26 = array[26];
+    var x27 = array[27];
+    var x28 = array[28];
+    var x29 = array[29];
+    var x30 = array[30];
+    var x31 = array[31];
+    var x32 = array[32];
+    var x33 = array[33];
+    var x34 = array[34];
+    var x35 = array[35];
+    var x36 = array[36];
+    var x37 = array[37];
+    var x38 = array[38];
+    var x39 = array[39];
+    var x40 = array[40];
+    var x41 = array[41];
+    var x42 = array[42];
+    var x43 = array[43];
+    var x44 = array[44];
+    var x45 = array[45];
+    var x46 = array[46];
+    var x47 = array[47];
+    var x48 = array[48];
+    var x49 = array[49];
+    var x50 = array[50];
+    var x51 = array[51];
+    var x52 = array[52];
+    var x53 = array[53];
+    var x54 = array[54];
+    var x55 = array[55];
+    var x56 = array[56];
+    var x57 = array[57];
+    var x58 = array[58];
+    var x59 = array[59];
+    var x60 = array[60];
+    var x61 = array[61];
+    var x62 = array[62];
+    var x63 = array[63];
+    
+    // Make a call that will throw, when we ask it to.
+    callee(&quot;hello&quot;);
+    
+    // Use all of those crazy values.
+    return [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62, x63]
+}
+
+noInline(ftlFunction);
+
+// Create some callees that are too crazy to get inlined or devirtualized, but that don't have effects.
+
+function happyCallee0() { return 0 };
+function happyCallee1() { return 1 };
+function happyCallee2() { return 2 };
+function happyCallee3() { return 3 };
+function happyCallee4() { return 4 };
+function happyCallee5() { return 5 };
+function happyCallee6() { return 6 };
+function happyCallee7() { return 7 };
+function happyCallee8() { return 8 };
+function happyCallee9() { return 9 };
+function happyCallee10() { return 10 };
+function happyCallee11() { return 11 };
+function happyCallee12() { return 12 };
+function happyCallee13() { return 13 };
+function happyCallee14() { return 14 };
+function happyCallee15() { return 15 };
+function happyCallee16() { return 16 };
+function happyCallee17() { return 17 };
+function happyCallee18() { return 18 };
+function happyCallee19() { return 19 };
+function happyCallee20() { return 20 };
+function happyCallee21() { return 21 };
+function happyCallee22() { return 22 };
+function happyCallee23() { return 23 };
+function happyCallee24() { return 24 };
+function happyCallee25() { return 25 };
+function happyCallee26() { return 26 };
+function happyCallee27() { return 27 };
+function happyCallee28() { return 28 };
+function happyCallee29() { return 29 };
+function happyCallee30() { return 30 };
+function happyCallee31() { return 31 };
+function happyCallee32() { return 32 };
+function happyCallee33() { return 33 };
+function happyCallee34() { return 34 };
+function happyCallee35() { return 35 };
+function happyCallee36() { return 36 };
+function happyCallee37() { return 37 };
+function happyCallee38() { return 38 };
+function happyCallee39() { return 39 };
+function happyCallee40() { return 40 };
+function happyCallee41() { return 41 };
+function happyCallee42() { return 42 };
+function happyCallee43() { return 43 };
+function happyCallee44() { return 44 };
+function happyCallee45() { return 45 };
+function happyCallee46() { return 46 };
+function happyCallee47() { return 47 };
+function happyCallee48() { return 48 };
+function happyCallee49() { return 49 };
+function happyCallee50() { return 50 };
+function happyCallee51() { return 51 };
+function happyCallee52() { return 52 };
+function happyCallee53() { return 53 };
+function happyCallee54() { return 54 };
+function happyCallee55() { return 55 };
+function happyCallee56() { return 56 };
+function happyCallee57() { return 57 };
+function happyCallee58() { return 58 };
+function happyCallee59() { return 59 };
+function happyCallee60() { return 60 };
+function happyCallee61() { return 61 };
+function happyCallee62() { return 62 };
+function happyCallee63() { return 63 };
+
+var happyCallees = [happyCallee0, happyCallee1, happyCallee2, happyCallee3, happyCallee4, happyCallee5, happyCallee6, happyCallee7, happyCallee8, happyCallee9, happyCallee10, happyCallee11, happyCallee12, happyCallee13, happyCallee14, happyCallee15, happyCallee16, happyCallee17, happyCallee18, happyCallee19, happyCallee20, happyCallee21, happyCallee22, happyCallee23, happyCallee24, happyCallee25, happyCallee26, happyCallee27, happyCallee28, happyCallee29, happyCallee30, happyCallee31, happyCallee32, happyCallee33, happyCallee34, happyCallee35, happyCallee36, happyCallee37, happyCallee38, happyCallee39, happyCallee40, happyCallee41, happyCallee42, happyCallee43, happyCallee44, happyCallee45, happyCallee46, happyCallee47, happyCallee48, happyCallee49, happyCallee50, happyCallee51, happyCallee52, happyCallee53, happyCallee54, happyCallee55, happyCallee56, happyCallee57, happyCallee58, happyCallee59, happyCallee60, happyCallee61, happyCallee62, happyCallee63];
+
+for (var i = 0; i &lt; happyCallees.length; ++i)
+    noInline(happyCallees[i]);
+
+// Unlike the other test (throw-from-ftl-call-ic-slow-path.js), we want to populate the registers with cells in
+// this test.
+var array = new Array();
+for (var i = 0; i &lt; 64; ++i)
+    array[i] = new Object();
+
+// Now, do some warming up.
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = ftlFunction(array, happyCallees[i % happyCallees.length]);
+    if (result.length != array.length)
+        throw &quot;Error: bad length: &quot; + result;
+    for (var j = 0; j &lt; result.length; ++j) {
+        if (result[j] != array[j])
+            throw &quot;Error: bad entry at j = &quot; + j + &quot;: &quot; + result;
+    }
+}
+
+// Finally, attempt to trigger the bug.
+var notACell = 42;
+for (var i = 0; i &lt; 100; ++i) {
+    try {
+        ftlFunction(array, Int8Array);
+    } catch (e) {
+        if (e.message.indexOf(&quot;not a function&quot;) &lt; 0)
+            throw &quot;Error: bad exception message: &quot; + e.message;
+        var result = notACell.f;
+        if (result !== void 0) {
+            print(&quot;Bad outcome of accessing f on notACell.&quot;);
+            print(&quot;Here's notACell:&quot;, notACell, describe(notACell));
+            print(&quot;Here's the result:&quot;, result, describe(result));
+            throw &quot;Error: bad outcome of accessing f on &quot; + notACell + &quot;: &quot; + result;
+        }
+        var result2 = result + 5;
+        var result3 = notACell + 5;
+        if (&quot;&quot; + result2 != &quot;NaN&quot;)
+            throw &quot;Error: bad outcome of adding 5 to result: &quot; + result2;
+        if (result3 != 47)
+            throw &quot;Error: bad outcome of adding 5 to 42: &quot; + result3;
+    }
+}
+
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit28SourceJavaScriptCoretestsstressthrowfromftlcallicslowpathundefinedjs"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path-undefined.js (0 => 180736)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path-undefined.js                                (rev 0)
+++ releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path-undefined.js        2015-02-27 11:57:41 UTC (rev 180736)
</span><span class="lines">@@ -0,0 +1,192 @@
</span><ins>+// Attempts to induce a crash resulting from the FTL emitting code that clobbers the tag registers and then
+// throwing an exception without restoring those tag registers' values.
+
+function ftlFunction(array, callee) {
+    // Gotta use lots of gprs.
+    var x0 = array[0];
+    var x1 = array[1];
+    var x2 = array[2];
+    var x3 = array[3];
+    var x4 = array[4];
+    var x5 = array[5];
+    var x6 = array[6];
+    var x7 = array[7];
+    var x8 = array[8];
+    var x9 = array[9];
+    var x10 = array[10];
+    var x11 = array[11];
+    var x12 = array[12];
+    var x13 = array[13];
+    var x14 = array[14];
+    var x15 = array[15];
+    var x16 = array[16];
+    var x17 = array[17];
+    var x18 = array[18];
+    var x19 = array[19];
+    var x20 = array[20];
+    var x21 = array[21];
+    var x22 = array[22];
+    var x23 = array[23];
+    var x24 = array[24];
+    var x25 = array[25];
+    var x26 = array[26];
+    var x27 = array[27];
+    var x28 = array[28];
+    var x29 = array[29];
+    var x30 = array[30];
+    var x31 = array[31];
+    var x32 = array[32];
+    var x33 = array[33];
+    var x34 = array[34];
+    var x35 = array[35];
+    var x36 = array[36];
+    var x37 = array[37];
+    var x38 = array[38];
+    var x39 = array[39];
+    var x40 = array[40];
+    var x41 = array[41];
+    var x42 = array[42];
+    var x43 = array[43];
+    var x44 = array[44];
+    var x45 = array[45];
+    var x46 = array[46];
+    var x47 = array[47];
+    var x48 = array[48];
+    var x49 = array[49];
+    var x50 = array[50];
+    var x51 = array[51];
+    var x52 = array[52];
+    var x53 = array[53];
+    var x54 = array[54];
+    var x55 = array[55];
+    var x56 = array[56];
+    var x57 = array[57];
+    var x58 = array[58];
+    var x59 = array[59];
+    var x60 = array[60];
+    var x61 = array[61];
+    var x62 = array[62];
+    var x63 = array[63];
+    
+    // Make a call that will throw, when we ask it to.
+    callee(&quot;hello&quot;);
+    
+    // Use all of those crazy values.
+    return [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62, x63]
+}
+
+noInline(ftlFunction);
+
+// Create some callees that are too crazy to get inlined or devirtualized, but that don't have effects.
+
+function happyCallee0() { return 0 };
+function happyCallee1() { return 1 };
+function happyCallee2() { return 2 };
+function happyCallee3() { return 3 };
+function happyCallee4() { return 4 };
+function happyCallee5() { return 5 };
+function happyCallee6() { return 6 };
+function happyCallee7() { return 7 };
+function happyCallee8() { return 8 };
+function happyCallee9() { return 9 };
+function happyCallee10() { return 10 };
+function happyCallee11() { return 11 };
+function happyCallee12() { return 12 };
+function happyCallee13() { return 13 };
+function happyCallee14() { return 14 };
+function happyCallee15() { return 15 };
+function happyCallee16() { return 16 };
+function happyCallee17() { return 17 };
+function happyCallee18() { return 18 };
+function happyCallee19() { return 19 };
+function happyCallee20() { return 20 };
+function happyCallee21() { return 21 };
+function happyCallee22() { return 22 };
+function happyCallee23() { return 23 };
+function happyCallee24() { return 24 };
+function happyCallee25() { return 25 };
+function happyCallee26() { return 26 };
+function happyCallee27() { return 27 };
+function happyCallee28() { return 28 };
+function happyCallee29() { return 29 };
+function happyCallee30() { return 30 };
+function happyCallee31() { return 31 };
+function happyCallee32() { return 32 };
+function happyCallee33() { return 33 };
+function happyCallee34() { return 34 };
+function happyCallee35() { return 35 };
+function happyCallee36() { return 36 };
+function happyCallee37() { return 37 };
+function happyCallee38() { return 38 };
+function happyCallee39() { return 39 };
+function happyCallee40() { return 40 };
+function happyCallee41() { return 41 };
+function happyCallee42() { return 42 };
+function happyCallee43() { return 43 };
+function happyCallee44() { return 44 };
+function happyCallee45() { return 45 };
+function happyCallee46() { return 46 };
+function happyCallee47() { return 47 };
+function happyCallee48() { return 48 };
+function happyCallee49() { return 49 };
+function happyCallee50() { return 50 };
+function happyCallee51() { return 51 };
+function happyCallee52() { return 52 };
+function happyCallee53() { return 53 };
+function happyCallee54() { return 54 };
+function happyCallee55() { return 55 };
+function happyCallee56() { return 56 };
+function happyCallee57() { return 57 };
+function happyCallee58() { return 58 };
+function happyCallee59() { return 59 };
+function happyCallee60() { return 60 };
+function happyCallee61() { return 61 };
+function happyCallee62() { return 62 };
+function happyCallee63() { return 63 };
+
+var happyCallees = [happyCallee0, happyCallee1, happyCallee2, happyCallee3, happyCallee4, happyCallee5, happyCallee6, happyCallee7, happyCallee8, happyCallee9, happyCallee10, happyCallee11, happyCallee12, happyCallee13, happyCallee14, happyCallee15, happyCallee16, happyCallee17, happyCallee18, happyCallee19, happyCallee20, happyCallee21, happyCallee22, happyCallee23, happyCallee24, happyCallee25, happyCallee26, happyCallee27, happyCallee28, happyCallee29, happyCallee30, happyCallee31, happyCallee32, happyCallee33, happyCallee34, happyCallee35, happyCallee36, happyCallee37, happyCallee38, happyCallee39, happyCallee40, happyCallee41, happyCallee42, happyCallee43, happyCallee44, happyCallee45, happyCallee46, happyCallee47, happyCallee48, happyCallee49, happyCallee50, happyCallee51, happyCallee52, happyCallee53, happyCallee54, happyCallee55, happyCallee56, happyCallee57, happyCallee58, happyCallee59, happyCallee60, happyCallee61, happyCallee62, happyCallee63];
+
+for (var i = 0; i &lt; happyCallees.length; ++i)
+    noInline(happyCallees[i]);
+
+// Unlike the other test (throw-from-ftl-call-ic-slow-path.js), we want to populate the registers with undefined
+// in this test.
+var array = new Array();
+for (var i = 0; i &lt; 64; ++i)
+    array[i] = void 0;
+
+// Now, do some warming up.
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = ftlFunction(array, happyCallees[i % happyCallees.length]);
+    if (result.length != array.length)
+        throw &quot;Error: bad length: &quot; + result;
+    for (var j = 0; j &lt; result.length; ++j) {
+        if (result[j] != array[j])
+            throw &quot;Error: bad entry at j = &quot; + j + &quot;: &quot; + result;
+    }
+}
+
+// Finally, attempt to trigger the bug.
+var notACell = 42;
+for (var i = 0; i &lt; 100; ++i) {
+    try {
+        ftlFunction(array, Int8Array);
+    } catch (e) {
+        if (e.message.indexOf(&quot;not a function&quot;) &lt; 0)
+            throw &quot;Error: bad exception message: &quot; + e.message;
+        var result = notACell.f;
+        if (result !== void 0) {
+            print(&quot;Bad outcome of accessing f on notACell.&quot;);
+            print(&quot;Here's notACell:&quot;, notACell, describe(notACell));
+            print(&quot;Here's the result:&quot;, result, describe(result));
+            throw &quot;Error: bad outcome of accessing f on &quot; + notACell + &quot;: &quot; + result;
+        }
+        var result2 = result + 5;
+        var result3 = notACell + 5;
+        if (&quot;&quot; + result2 != &quot;NaN&quot;)
+            throw &quot;Error: bad outcome of adding 5 to result: &quot; + result2;
+        if (result3 != 47)
+            throw &quot;Error: bad outcome of adding 5 to 42: &quot; + result3;
+    }
+}
+
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit28SourceJavaScriptCoretestsstressthrowfromftlcallicslowpathjs"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path.js (0 => 180736)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path.js                                (rev 0)
+++ releases/WebKitGTK/webkit-2.8/Source/JavaScriptCore/tests/stress/throw-from-ftl-call-ic-slow-path.js        2015-02-27 11:57:41 UTC (rev 180736)
</span><span class="lines">@@ -0,0 +1,192 @@
</span><ins>+// Attempts to induce a crash resulting from the FTL emitting code that clobbers the tag registers and then
+// throwing an exception without restoring those tag registers' values.
+
+function ftlFunction(array, callee) {
+    // Gotta use lots of gprs.
+    var x0 = array[0];
+    var x1 = array[1];
+    var x2 = array[2];
+    var x3 = array[3];
+    var x4 = array[4];
+    var x5 = array[5];
+    var x6 = array[6];
+    var x7 = array[7];
+    var x8 = array[8];
+    var x9 = array[9];
+    var x10 = array[10];
+    var x11 = array[11];
+    var x12 = array[12];
+    var x13 = array[13];
+    var x14 = array[14];
+    var x15 = array[15];
+    var x16 = array[16];
+    var x17 = array[17];
+    var x18 = array[18];
+    var x19 = array[19];
+    var x20 = array[20];
+    var x21 = array[21];
+    var x22 = array[22];
+    var x23 = array[23];
+    var x24 = array[24];
+    var x25 = array[25];
+    var x26 = array[26];
+    var x27 = array[27];
+    var x28 = array[28];
+    var x29 = array[29];
+    var x30 = array[30];
+    var x31 = array[31];
+    var x32 = array[32];
+    var x33 = array[33];
+    var x34 = array[34];
+    var x35 = array[35];
+    var x36 = array[36];
+    var x37 = array[37];
+    var x38 = array[38];
+    var x39 = array[39];
+    var x40 = array[40];
+    var x41 = array[41];
+    var x42 = array[42];
+    var x43 = array[43];
+    var x44 = array[44];
+    var x45 = array[45];
+    var x46 = array[46];
+    var x47 = array[47];
+    var x48 = array[48];
+    var x49 = array[49];
+    var x50 = array[50];
+    var x51 = array[51];
+    var x52 = array[52];
+    var x53 = array[53];
+    var x54 = array[54];
+    var x55 = array[55];
+    var x56 = array[56];
+    var x57 = array[57];
+    var x58 = array[58];
+    var x59 = array[59];
+    var x60 = array[60];
+    var x61 = array[61];
+    var x62 = array[62];
+    var x63 = array[63];
+    
+    // Make a call that will throw, when we ask it to.
+    callee(&quot;hello&quot;);
+    
+    // Use all of those crazy values.
+    return [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62, x63]
+}
+
+noInline(ftlFunction);
+
+// Create some callees that are too crazy to get inlined or devirtualized, but that don't have effects.
+
+function happyCallee0() { return 0 };
+function happyCallee1() { return 1 };
+function happyCallee2() { return 2 };
+function happyCallee3() { return 3 };
+function happyCallee4() { return 4 };
+function happyCallee5() { return 5 };
+function happyCallee6() { return 6 };
+function happyCallee7() { return 7 };
+function happyCallee8() { return 8 };
+function happyCallee9() { return 9 };
+function happyCallee10() { return 10 };
+function happyCallee11() { return 11 };
+function happyCallee12() { return 12 };
+function happyCallee13() { return 13 };
+function happyCallee14() { return 14 };
+function happyCallee15() { return 15 };
+function happyCallee16() { return 16 };
+function happyCallee17() { return 17 };
+function happyCallee18() { return 18 };
+function happyCallee19() { return 19 };
+function happyCallee20() { return 20 };
+function happyCallee21() { return 21 };
+function happyCallee22() { return 22 };
+function happyCallee23() { return 23 };
+function happyCallee24() { return 24 };
+function happyCallee25() { return 25 };
+function happyCallee26() { return 26 };
+function happyCallee27() { return 27 };
+function happyCallee28() { return 28 };
+function happyCallee29() { return 29 };
+function happyCallee30() { return 30 };
+function happyCallee31() { return 31 };
+function happyCallee32() { return 32 };
+function happyCallee33() { return 33 };
+function happyCallee34() { return 34 };
+function happyCallee35() { return 35 };
+function happyCallee36() { return 36 };
+function happyCallee37() { return 37 };
+function happyCallee38() { return 38 };
+function happyCallee39() { return 39 };
+function happyCallee40() { return 40 };
+function happyCallee41() { return 41 };
+function happyCallee42() { return 42 };
+function happyCallee43() { return 43 };
+function happyCallee44() { return 44 };
+function happyCallee45() { return 45 };
+function happyCallee46() { return 46 };
+function happyCallee47() { return 47 };
+function happyCallee48() { return 48 };
+function happyCallee49() { return 49 };
+function happyCallee50() { return 50 };
+function happyCallee51() { return 51 };
+function happyCallee52() { return 52 };
+function happyCallee53() { return 53 };
+function happyCallee54() { return 54 };
+function happyCallee55() { return 55 };
+function happyCallee56() { return 56 };
+function happyCallee57() { return 57 };
+function happyCallee58() { return 58 };
+function happyCallee59() { return 59 };
+function happyCallee60() { return 60 };
+function happyCallee61() { return 61 };
+function happyCallee62() { return 62 };
+function happyCallee63() { return 63 };
+
+var happyCallees = [happyCallee0, happyCallee1, happyCallee2, happyCallee3, happyCallee4, happyCallee5, happyCallee6, happyCallee7, happyCallee8, happyCallee9, happyCallee10, happyCallee11, happyCallee12, happyCallee13, happyCallee14, happyCallee15, happyCallee16, happyCallee17, happyCallee18, happyCallee19, happyCallee20, happyCallee21, happyCallee22, happyCallee23, happyCallee24, happyCallee25, happyCallee26, happyCallee27, happyCallee28, happyCallee29, happyCallee30, happyCallee31, happyCallee32, happyCallee33, happyCallee34, happyCallee35, happyCallee36, happyCallee37, happyCallee38, happyCallee39, happyCallee40, happyCallee41, happyCallee42, happyCallee43, happyCallee44, happyCallee45, happyCallee46, happyCallee47, happyCallee48, happyCallee49, happyCallee50, happyCallee51, happyCallee52, happyCallee53, happyCallee54, happyCallee55, happyCallee56, happyCallee57, happyCallee58, happyCallee59, happyCallee60, happyCallee61, happyCallee62, happyCallee63];
+
+for (var i = 0; i &lt; happyCallees.length; ++i)
+    noInline(happyCallees[i]);
+
+// We want the input array to have an easy-to-deal-with type that isn't exactly the same as the type that
+// ftlFunction will return.
+var array = new Int32Array(64);
+for (var i = 0; i &lt; array.length; ++i)
+    array[i] = i;
+
+// Now, do some warming up.
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = ftlFunction(array, happyCallees[i % happyCallees.length]);
+    if (result.length != array.length)
+        throw &quot;Error: bad length: &quot; + result;
+    for (var j = 0; j &lt; result.length; ++j) {
+        if (result[j] != array[j])
+            throw &quot;Error: bad entry at j = &quot; + j + &quot;: &quot; + result;
+    }
+}
+
+// Finally, attempt to trigger the bug.
+var notACell = 42;
+for (var i = 0; i &lt; 100; ++i) {
+    try {
+        ftlFunction(array, Int8Array);
+    } catch (e) {
+        if (e.message.indexOf(&quot;not a function&quot;) &lt; 0)
+            throw &quot;Error: bad exception message: &quot; + e.message;
+        var result = notACell.f;
+        if (result !== void 0) {
+            print(&quot;Bad outcome of accessing f on notACell.&quot;);
+            print(&quot;Here's notACell:&quot;, notACell, describe(notACell));
+            print(&quot;Here's the result:&quot;, result, describe(result));
+            throw &quot;Error: bad outcome of accessing f on &quot; + notACell + &quot;: &quot; + result;
+        }
+        var result2 = result + 5;
+        var result3 = notACell + 5;
+        if (&quot;&quot; + result2 != &quot;NaN&quot;)
+            throw &quot;Error: bad outcome of adding 5 to result: &quot; + result2;
+        if (result3 != 47)
+            throw &quot;Error: bad outcome of adding 5 to 42: &quot; + result3;
+    }
+}
+
</ins></span></pre>
</div>
</div>

</body>
</html>