<!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>[165522] trunk/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/165522">165522</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-03-12 18:50:41 -0700 (Wed, 12 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>ASSERTION FAILED: node-&gt;op() == Phi || node-&gt;op() == SetArgument
https://bugs.webkit.org/show_bug.cgi?id=130069

Reviewed by Geoffrey Garen.
        
This was a great assertion, and it represents our strictest interpretation of the rules of
our intermediate representation. However, fixing DCE to actually preserve the relevant
property would be hard, and it wouldn't have an observable effect right now because nobody
actually uses the propery of CPS that this assertion is checking for.
        
In particular, we do always require, and rely on, the fact that non-captured variables
have variablesAtTail refer to the last interesting use of the variable: a SetLocal if the
block assigns to the variable, a GetLocal if it only reads from it, and a Flush,
PhantomLocal, or Phi otherwise. We do preserve this property successfully and DCE was not
broken in this regard. But, in the strictest sense, CPS also means that for captured
variables, variablesAtTail also continues to point to the last relevant use of the
variable. In particular, if there are multiple GetLocals, then it should point to the last
one. This is hard for DCE to preserve. Also, nobody relies on variablesAtTail for captured
variables, except to check the VariableAccessData; but in that case, we don't really need
the *last* relevant use of the variable - any node that mentions the same variable will do
just fine.
        
So, this change loosens the assertion and adds a detailed FIXME describing what we would
have to do if we wanted to preserve the more strict property.
        
This also makes changes to various debug printing paths so that validation doesn't crash
during graph dump. This also adds tests for the interesting cases of DCE failing to
preserve CPS in the strictest sense. This also attempts to win the record for longest test
name.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::hashAsStringIfPossible):
(JSC::CodeBlock::dumpAssumingJITType):
* bytecode/CodeBlock.h:
* bytecode/CodeOrigin.cpp:
(JSC::InlineCallFrame::hashAsStringIfPossible):
(JSC::InlineCallFrame::dumpBriefFunctionInformation):
* bytecode/CodeOrigin.h:
* dfg/DFGCPSRethreadingPhase.cpp:
(JSC::DFG::CPSRethreadingPhase::run):
* dfg/DFGDCEPhase.cpp:
(JSC::DFG::DCEPhase::cleanVariables):
* dfg/DFGInPlaceAbstractState.cpp:
(JSC::DFG::InPlaceAbstractState::mergeStateAtTail):
* runtime/FunctionExecutableDump.cpp:
(JSC::FunctionExecutableDump::dump):
* tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store-in-function-with-multiple-basic-blocks.js: Added.
(foo):
* tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store.js: Added.
(foo):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeOrigincpp">trunk/Source/JavaScriptCore/bytecode/CodeOrigin.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeOriginh">trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCPSRethreadingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDCEPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGInPlaceAbstractStatecpp">trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeFunctionExecutableDumpcpp">trunk/Source/JavaScriptCore/runtime/FunctionExecutableDump.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressdeadaccesstocapturedvariableprecededbyalivestoreinfunctionwithmultiplebasicblocksjs">trunk/Source/JavaScriptCore/tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store-in-function-with-multiple-basic-blocks.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressdeadaccesstocapturedvariableprecededbyalivestorejs">trunk/Source/JavaScriptCore/tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (165521 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-03-13 00:41:58 UTC (rev 165521)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -1,3 +1,56 @@
</span><ins>+2014-03-11  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        ASSERTION FAILED: node-&gt;op() == Phi || node-&gt;op() == SetArgument
+        https://bugs.webkit.org/show_bug.cgi?id=130069
+
+        Reviewed by Geoffrey Garen.
+        
+        This was a great assertion, and it represents our strictest interpretation of the rules of
+        our intermediate representation. However, fixing DCE to actually preserve the relevant
+        property would be hard, and it wouldn't have an observable effect right now because nobody
+        actually uses the propery of CPS that this assertion is checking for.
+        
+        In particular, we do always require, and rely on, the fact that non-captured variables
+        have variablesAtTail refer to the last interesting use of the variable: a SetLocal if the
+        block assigns to the variable, a GetLocal if it only reads from it, and a Flush,
+        PhantomLocal, or Phi otherwise. We do preserve this property successfully and DCE was not
+        broken in this regard. But, in the strictest sense, CPS also means that for captured
+        variables, variablesAtTail also continues to point to the last relevant use of the
+        variable. In particular, if there are multiple GetLocals, then it should point to the last
+        one. This is hard for DCE to preserve. Also, nobody relies on variablesAtTail for captured
+        variables, except to check the VariableAccessData; but in that case, we don't really need
+        the *last* relevant use of the variable - any node that mentions the same variable will do
+        just fine.
+        
+        So, this change loosens the assertion and adds a detailed FIXME describing what we would
+        have to do if we wanted to preserve the more strict property.
+        
+        This also makes changes to various debug printing paths so that validation doesn't crash
+        during graph dump. This also adds tests for the interesting cases of DCE failing to
+        preserve CPS in the strictest sense. This also attempts to win the record for longest test
+        name.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::hashAsStringIfPossible):
+        (JSC::CodeBlock::dumpAssumingJITType):
+        * bytecode/CodeBlock.h:
+        * bytecode/CodeOrigin.cpp:
+        (JSC::InlineCallFrame::hashAsStringIfPossible):
+        (JSC::InlineCallFrame::dumpBriefFunctionInformation):
+        * bytecode/CodeOrigin.h:
+        * dfg/DFGCPSRethreadingPhase.cpp:
+        (JSC::DFG::CPSRethreadingPhase::run):
+        * dfg/DFGDCEPhase.cpp:
+        (JSC::DFG::DCEPhase::cleanVariables):
+        * dfg/DFGInPlaceAbstractState.cpp:
+        (JSC::DFG::InPlaceAbstractState::mergeStateAtTail):
+        * runtime/FunctionExecutableDump.cpp:
+        (JSC::FunctionExecutableDump::dump):
+        * tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store-in-function-with-multiple-basic-blocks.js: Added.
+        (foo):
+        * tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store.js: Added.
+        (foo):
+
</ins><span class="cx"> 2014-03-12  Brian Burg  &lt;bburg@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Replay: add infrastructure for memoizing nondeterministic DOM APIs
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (165521 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-03-13 00:41:58 UTC (rev 165521)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -129,13 +129,16 @@
</span><span class="cx">     return reduceWhitespace(sourceCodeForTools());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CString CodeBlock::hashAsStringIfPossible() const
+{
+    if (hasHash() || isSafeToComputeHash())
+        return toCString(hash());
+    return &quot;&lt;no-hash&gt;&quot;;
+}
+
</ins><span class="cx"> void CodeBlock::dumpAssumingJITType(PrintStream&amp; out, JITCode::JITType jitType) const
</span><span class="cx"> {
</span><del>-    out.print(inferredName(), &quot;#&quot;);
-    if (hasHash() || isSafeToComputeHash())
-        out.print(hash());
-    else
-        out.print(&quot;&lt;no-hash&gt;&quot;);
</del><ins>+    out.print(inferredName(), &quot;#&quot;, hashAsStringIfPossible());
</ins><span class="cx">     out.print(&quot;:[&quot;, RawPointer(this), &quot;-&gt;&quot;);
</span><span class="cx">     if (!!m_alternative)
</span><span class="cx">         out.print(RawPointer(m_alternative.get()), &quot;-&gt;&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (165521 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2014-03-13 00:41:58 UTC (rev 165521)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -117,6 +117,7 @@
</span><span class="cx">     CodeBlockHash hash() const;
</span><span class="cx">     bool hasHash() const;
</span><span class="cx">     bool isSafeToComputeHash() const;
</span><ins>+    CString hashAsStringIfPossible() const;
</ins><span class="cx">     CString sourceCodeForTools() const; // Not quite the actual source we parsed; this will do things like prefix the source for a function with a reified signature.
</span><span class="cx">     CString sourceCodeOnOneLine() const; // As sourceCodeForTools(), but replaces all whitespace runs with a single space.
</span><span class="cx">     void dumpAssumingJITType(PrintStream&amp;, JITCode::JITType) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeOrigincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeOrigin.cpp (165521 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeOrigin.cpp        2014-03-13 00:41:58 UTC (rev 165521)
+++ trunk/Source/JavaScriptCore/bytecode/CodeOrigin.cpp        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -152,6 +152,12 @@
</span><span class="cx">         specializationKind())-&gt;hash();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CString InlineCallFrame::hashAsStringIfPossible() const
+{
+    return jsCast&lt;FunctionExecutable*&gt;(executable.get())-&gt;codeBlockFor(
+        specializationKind())-&gt;hashAsStringIfPossible();
+}
+
</ins><span class="cx"> CString InlineCallFrame::inferredName() const
</span><span class="cx"> {
</span><span class="cx">     return jsCast&lt;FunctionExecutable*&gt;(executable.get())-&gt;inferredName().utf8();
</span><span class="lines">@@ -164,7 +170,7 @@
</span><span class="cx"> 
</span><span class="cx"> void InlineCallFrame::dumpBriefFunctionInformation(PrintStream&amp; out) const
</span><span class="cx"> {
</span><del>-    out.print(inferredName(), &quot;#&quot;, hash());
</del><ins>+    out.print(inferredName(), &quot;#&quot;, hashAsStringIfPossible());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void InlineCallFrame::dumpInContext(PrintStream&amp; out, DumpContext* context) const
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeOriginh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h (165521 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h        2014-03-13 00:41:58 UTC (rev 165521)
+++ trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -151,6 +151,7 @@
</span><span class="cx">     
</span><span class="cx">     CString inferredName() const;
</span><span class="cx">     CodeBlockHash hash() const;
</span><ins>+    CString hashAsStringIfPossible() const;
</ins><span class="cx">     
</span><span class="cx">     CodeBlock* baselineCodeBlock() const;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCPSRethreadingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp (165521 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp        2014-03-13 00:41:58 UTC (rev 165521)
+++ trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -44,6 +44,8 @@
</span><span class="cx">     
</span><span class="cx">     bool run()
</span><span class="cx">     {
</span><ins>+        RELEASE_ASSERT(m_graph.m_refCountState == EverythingIsLive);
+        
</ins><span class="cx">         if (m_graph.m_form == ThreadedCPS)
</span><span class="cx">             return false;
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDCEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp (165521 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2014-03-13 00:41:58 UTC (rev 165521)
+++ trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -259,7 +259,39 @@
</span><span class="cx">                 continue;
</span><span class="cx">             if (node-&gt;op() == GetLocal) {
</span><span class="cx">                 node = node-&gt;child1().node();
</span><del>-                ASSERT(node-&gt;op() == Phi || node-&gt;op() == SetArgument);
</del><ins>+                
+                // FIXME: In the case that the variable is captured, we really want to be able
+                // to replace the variable-at-tail with the last use of the variable in the same
+                // way that CPS rethreading would do. The child of the GetLocal isn't necessarily
+                // the same as what CPS rethreading would do. For example, we may have:
+                //
+                // a: SetLocal(...) // live
+                // b: GetLocal(@a) // live
+                // c: GetLocal(@a) // dead
+                //
+                // When killing @c, the code below will set the variable-at-tail to @a, while CPS
+                // rethreading would have set @b. This is a benign bug, since all clients of CPS
+                // only use the variable-at-tail of captured variables to get the
+                // VariableAccessData and observe that it is in fact captured. But, this feels
+                // like it could cause bugs in the future.
+                //
+                // It's tempting to just dethread and then invoke CPS rethreading, but CPS
+                // rethreading fails to preserve exact ref-counts. So we would need a fixpoint.
+                // It's probably the case that this fixpoint will be guaranteed to converge after
+                // the second iteration (i.e. the second run of DCE will not kill anything and so
+                // will not need to dethread), but for now the safest approach is probably just to
+                // allow for this tiny bit of sloppiness.
+                //
+                // Another possible solution would be to simply say that DCE dethreads but then
+                // we never rethread before going to the backend. That feels intuitively right
+                // because it's unlikely that any of the phases after DCE in the backend rely on
+                // ThreadedCPS.
+                //
+                // https://bugs.webkit.org/show_bug.cgi?id=130115
+                ASSERT(
+                    node-&gt;op() == Phi || node-&gt;op() == SetArgument
+                    || node-&gt;variableAccessData()-&gt;isCaptured());
+                
</ins><span class="cx">                 if (node-&gt;shouldGenerate()) {
</span><span class="cx">                     variables[i] = node;
</span><span class="cx">                     continue;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGInPlaceAbstractStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp (165521 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp        2014-03-13 00:41:58 UTC (rev 165521)
+++ trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -254,7 +254,7 @@
</span><span class="cx">     if (node-&gt;variableAccessData()-&gt;isCaptured()) {
</span><span class="cx">         // If it's captured then we know that whatever value was stored into the variable last is the
</span><span class="cx">         // one we care about. This is true even if the variable at tail is dead, which might happen if
</span><del>-        // the last thing we did to the variable was a GetLocal and then ended up now using the
</del><ins>+        // the last thing we did to the variable was a GetLocal and then ended up not using the
</ins><span class="cx">         // GetLocal's result.
</span><span class="cx">         
</span><span class="cx">         source = inVariable;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeFunctionExecutableDumpcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/FunctionExecutableDump.cpp (165521 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/FunctionExecutableDump.cpp        2014-03-13 00:41:58 UTC (rev 165521)
+++ trunk/Source/JavaScriptCore/runtime/FunctionExecutableDump.cpp        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -34,12 +34,12 @@
</span><span class="cx"> {
</span><span class="cx">     out.print(m_executable-&gt;inferredName().string(), &quot;#&quot;);
</span><span class="cx">     if (m_executable-&gt;isGeneratedForCall())
</span><del>-        out.print(m_executable-&gt;codeBlockForCall()-&gt;hash());
</del><ins>+        out.print(m_executable-&gt;codeBlockForCall()-&gt;hashAsStringIfPossible());
</ins><span class="cx">     else
</span><span class="cx">         out.print(&quot;&lt;nogen&gt;&quot;);
</span><span class="cx">     out.print(&quot;/&quot;);
</span><span class="cx">     if (m_executable-&gt;isGeneratedForConstruct())
</span><del>-        out.print(m_executable-&gt;codeBlockForConstruct()-&gt;hash());
</del><ins>+        out.print(m_executable-&gt;codeBlockForConstruct()-&gt;hashAsStringIfPossible());
</ins><span class="cx">     else
</span><span class="cx">         out.print(&quot;&lt;nogen&gt;&quot;);
</span><span class="cx">     out.print(&quot;:[&quot;, RawPointer(m_executable), &quot;]&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressdeadaccesstocapturedvariableprecededbyalivestoreinfunctionwithmultiplebasicblocksjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store-in-function-with-multiple-basic-blocks.js (0 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store-in-function-with-multiple-basic-blocks.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store-in-function-with-multiple-basic-blocks.js        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+function foo(p) {
+    if (p) {
+        var x = 42;
+        (function() { x = 43; })();
+        x++;
+        var realResult = x;
+        (function() { x = 44; })();
+        var fakeResult = x;
+        return realResult;
+    }
+    var y = 45;
+    (function() { y = 46; })();
+    y++;
+    var realResult2 = y;
+    (function() { y = 47; })();
+    var fakeResult2 = y;
+    return realResult2;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(i &amp; 1);
+    if (result != ((i &amp; 1) ? 44 : 47))
+        throw &quot;Error: bad result with i = &quot; + i + &quot;: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressdeadaccesstocapturedvariableprecededbyalivestorejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store.js (0 => 165522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/dead-access-to-captured-variable-preceded-by-a-live-store.js        2014-03-13 01:50:41 UTC (rev 165522)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+function foo() {
+    var x = 42;
+    (function() { x = 43; })();
+    x++;
+    var realResult = x;
+    (function() { x = 44; })();
+    var fakeResult = x;
+    return realResult;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo();
+    if (result != 44)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre>
</div>
</div>

</body>
</html>