<!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>[171495] branches/ftlopt/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/171495">171495</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-07-23 16:06:55 -0700 (Wed, 23 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[ftlopt] Phantoms in SSA form should be aggressively hoisted
https://bugs.webkit.org/show_bug.cgi?id=135111

Reviewed by Oliver Hunt.
        
In CPS form, Phantom means three things: (1) that the children should be kept alive so long
as they are relevant to OSR (due to a MovHint), (2) that the children are live-in-bytecode
at the point of the Phantom, and (3) that some checks should be performed. In SSA, the
second meaning is not used but the other two stay.
        
The fact that a Phantom that is used to keep a node alive could be anywhere in the graph,
even in a totally different basic block, complicates some SSA transformations. It's not
possible to just jettison some successor, since tha successor could have a Phantom that we
care about.
        
This change rationalizes how Phantoms work so that:
        
1) Phantoms keep children alive so long as those children are relevant to OSR. This is true
   in both CPS and SSA. This was true before and it's true now.
        
2) Phantoms are used for live-in-bytecode only in CPS. This was true before and it's true
   now, except that now we also don't bother preserving the live-in-bytecode information
   that Phantoms convey, when we are in SSA.
        
3) Phantoms may incidentally have checks, but in cases where we only want checks, we now
   use Check instead of Phantom. Notably, DCE phase has dead nodes decay to Check, not
   Phantom.
        
The biggest part of this change is that in SSA, we canonicalize Phantoms:
        
- All Phantoms are replaced with Check nodes that include only those edges that have
  checks.
        
- Nodes that were the children of any Phantoms have a Phantom right after them.
        
For example, the following code:
        
    5: ArithAdd(@1, @2)
    6: ArithSub(@5, @3)
    7: Phantom(Int32:@5)
        
would be turned into the following:
        
    5: ArithAdd(@1, @2)
    8: Phantom(@5) // @5 was the child of a Phantom, so we create a new Phantom right after
                   // @5. This is the only Phantom we will have for @5.
    6: ArithSub(@5, @3)
    7: Check(Int32:@5) // We replace the Phantom with a Check; in this case since Int32: is
                       // a checking edge, we leave it.
        
This is a slight speed-up across the board, presumably because we now do a better job of
reducing the size of the graph during compilation. It could also be a fluke, though. The
main purpose of this is to unlock some other work (like CFG simplification in SSA). It will
become a requirement to run phantom canonicalization prior to some SSA phases. None of the
current phases need it, but future phases probably will.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDCEPhase.cpp:
(JSC::DFG::DCEPhase::run):
(JSC::DFG::DCEPhase::findTypeCheckRoot):
(JSC::DFG::DCEPhase::countEdge):
(JSC::DFG::DCEPhase::fixupBlock):
(JSC::DFG::DCEPhase::eliminateIrrelevantPhantomChildren):
* dfg/DFGEdge.cpp:
(JSC::DFG::Edge::dump):
* dfg/DFGEdge.h:
(JSC::DFG::Edge::isProved):
(JSC::DFG::Edge::needsCheck): Deleted.
* dfg/DFGNodeFlags.h:
* dfg/DFGPhantomCanonicalizationPhase.cpp: Added.
(JSC::DFG::PhantomCanonicalizationPhase::PhantomCanonicalizationPhase):
(JSC::DFG::PhantomCanonicalizationPhase::run):
(JSC::DFG::performPhantomCanonicalization):
* dfg/DFGPhantomCanonicalizationPhase.h: Added.
* dfg/DFGPhantomRemovalPhase.cpp:
(JSC::DFG::PhantomRemovalPhase::run):
* dfg/DFGPhantomRemovalPhase.h:
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::lowJSValue):
(JSC::FTL::LowerDFGToLLVM::speculateObjectOrOther):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesftloptSourceJavaScriptCoreCMakeListstxt">branches/ftlopt/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreChangeLog">branches/ftlopt/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGDCEPhasecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGEdgecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGEdge.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGEdgeh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGEdge.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGGraphcpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGNodeFlagsh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeFlags.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGNodeTypeh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGPhantomRemovalPhasecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGPhantomRemovalPhaseh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGPlancpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">branches/ftlopt/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGPhantomCanonicalizationPhasecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGPhantomCanonicalizationPhaseh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesftloptSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/CMakeLists.txt (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/CMakeLists.txt        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/CMakeLists.txt        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -182,6 +182,7 @@
</span><span class="cx">     dfg/DFGOSRExitJumpPlaceholder.cpp
</span><span class="cx">     dfg/DFGOSRExitPreparation.cpp
</span><span class="cx">     dfg/DFGOperations.cpp
</span><ins>+    dfg/DFGPhantomCanonicalizationPhase.cpp
</ins><span class="cx">     dfg/DFGPhantomRemovalPhase.cpp
</span><span class="cx">     dfg/DFGPhase.cpp
</span><span class="cx">     dfg/DFGPlan.cpp
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/ChangeLog (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -1,3 +1,94 @@
</span><ins>+2014-07-20  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        [ftlopt] Phantoms in SSA form should be aggressively hoisted
+        https://bugs.webkit.org/show_bug.cgi?id=135111
+
+        Reviewed by Oliver Hunt.
+        
+        In CPS form, Phantom means three things: (1) that the children should be kept alive so long
+        as they are relevant to OSR (due to a MovHint), (2) that the children are live-in-bytecode
+        at the point of the Phantom, and (3) that some checks should be performed. In SSA, the
+        second meaning is not used but the other two stay.
+        
+        The fact that a Phantom that is used to keep a node alive could be anywhere in the graph,
+        even in a totally different basic block, complicates some SSA transformations. It's not
+        possible to just jettison some successor, since tha successor could have a Phantom that we
+        care about.
+        
+        This change rationalizes how Phantoms work so that:
+        
+        1) Phantoms keep children alive so long as those children are relevant to OSR. This is true
+           in both CPS and SSA. This was true before and it's true now.
+        
+        2) Phantoms are used for live-in-bytecode only in CPS. This was true before and it's true
+           now, except that now we also don't bother preserving the live-in-bytecode information
+           that Phantoms convey, when we are in SSA.
+        
+        3) Phantoms may incidentally have checks, but in cases where we only want checks, we now
+           use Check instead of Phantom. Notably, DCE phase has dead nodes decay to Check, not
+           Phantom.
+        
+        The biggest part of this change is that in SSA, we canonicalize Phantoms:
+        
+        - All Phantoms are replaced with Check nodes that include only those edges that have
+          checks.
+        
+        - Nodes that were the children of any Phantoms have a Phantom right after them.
+        
+        For example, the following code:
+        
+            5: ArithAdd(@1, @2)
+            6: ArithSub(@5, @3)
+            7: Phantom(Int32:@5)
+        
+        would be turned into the following:
+        
+            5: ArithAdd(@1, @2)
+            8: Phantom(@5) // @5 was the child of a Phantom, so we create a new Phantom right after
+                           // @5. This is the only Phantom we will have for @5.
+            6: ArithSub(@5, @3)
+            7: Check(Int32:@5) // We replace the Phantom with a Check; in this case since Int32: is
+                               // a checking edge, we leave it.
+        
+        This is a slight speed-up across the board, presumably because we now do a better job of
+        reducing the size of the graph during compilation. It could also be a fluke, though. The
+        main purpose of this is to unlock some other work (like CFG simplification in SSA). It will
+        become a requirement to run phantom canonicalization prior to some SSA phases. None of the
+        current phases need it, but future phases probably will.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDCEPhase.cpp:
+        (JSC::DFG::DCEPhase::run):
+        (JSC::DFG::DCEPhase::findTypeCheckRoot):
+        (JSC::DFG::DCEPhase::countEdge):
+        (JSC::DFG::DCEPhase::fixupBlock):
+        (JSC::DFG::DCEPhase::eliminateIrrelevantPhantomChildren):
+        * dfg/DFGEdge.cpp:
+        (JSC::DFG::Edge::dump):
+        * dfg/DFGEdge.h:
+        (JSC::DFG::Edge::isProved):
+        (JSC::DFG::Edge::needsCheck): Deleted.
+        * dfg/DFGNodeFlags.h:
+        * dfg/DFGPhantomCanonicalizationPhase.cpp: Added.
+        (JSC::DFG::PhantomCanonicalizationPhase::PhantomCanonicalizationPhase):
+        (JSC::DFG::PhantomCanonicalizationPhase::run):
+        (JSC::DFG::performPhantomCanonicalization):
+        * dfg/DFGPhantomCanonicalizationPhase.h: Added.
+        * dfg/DFGPhantomRemovalPhase.cpp:
+        (JSC::DFG::PhantomRemovalPhase::run):
+        * dfg/DFGPhantomRemovalPhase.h:
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::lowJSValue):
+        (JSC::FTL::LowerDFGToLLVM::speculateObjectOrOther):
+
</ins><span class="cx"> 2014-07-22  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ftlopt] Get rid of structure checks as a way of checking if a function is in fact a function
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -433,6 +433,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGOSRExitCompilerCommon.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGOSRExitJumpPlaceholder.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGOSRExitPreparation.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\dfg\DFGPhantomCanonicalizationPhase.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGPhantomRemovalPhase.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGPhase.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGPlan.cpp&quot; /&gt;
</span><span class="lines">@@ -1013,6 +1014,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGOSRExitCompilerCommon.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGOSRExitJumpPlaceholder.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGOSRExitPreparation.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGPhantomCanonicalizationPhase.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPhantomRemovalPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPlan.h&quot; /&gt;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -361,6 +361,8 @@
</span><span class="cx">                 0F7AB82F1958DA1C00C6881F /* ToThisStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7AB82D1958DA1C00C6881F /* ToThisStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0977E1469EBC400CF2442 /* DFGCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F7B3661197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7B365F197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp */; };
+                0F7B3662197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7B3660197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8023E91613832300A0BA45 /* ByValInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; };
</span><span class="cx">                 0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2542,6 +2544,8 @@
</span><span class="cx">                 0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7AB82C1958DA1C00C6881F /* ToThisStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ToThisStatus.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7AB82D1958DA1C00C6881F /* ToThisStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToThisStatus.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F7B365F197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPhantomCanonicalizationPhase.cpp; path = dfg/DFGPhantomCanonicalizationPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7B3660197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPhantomCanonicalizationPhase.h; path = dfg/DFGPhantomCanonicalizationPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F8023E91613832300A0BA45 /* ByValInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByValInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayAllocationProfile.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5190,6 +5194,8 @@
</span><span class="cx">                                 0FEFC9A81681A3B000567F53 /* DFGOSRExitJumpPlaceholder.h */,
</span><span class="cx">                                 0F235BE917178E7300690C7F /* DFGOSRExitPreparation.cpp */,
</span><span class="cx">                                 0F235BEA17178E7300690C7F /* DFGOSRExitPreparation.h */,
</span><ins>+                                0F7B365F197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp */,
+                                0F7B3660197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h */,
</ins><span class="cx">                                 0FBFDD02196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp */,
</span><span class="cx">                                 0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */,
</span><span class="cx">                                 0FFFC94F14EF909500C72532 /* DFGPhase.cpp */,
</span><span class="lines">@@ -6415,6 +6421,7 @@
</span><span class="cx">                                 0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
</span><span class="cx">                                 0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
</span><span class="cx">                                 0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
</span><ins>+                                0F7B3662197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h in Headers */,
</ins><span class="cx">                                 0F5A1274192D9FDF008764A3 /* DFGDoesGC.h in Headers */,
</span><span class="cx">                                 0F2B66F517B6B5AB00A7AE3F /* JSGenericTypedArrayViewPrototype.h in Headers */,
</span><span class="cx">                                 0F2B66F617B6B5AB00A7AE3F /* JSGenericTypedArrayViewPrototypeInlines.h in Headers */,
</span><span class="lines">@@ -7928,6 +7935,7 @@
</span><span class="cx">                                 A503FA1D188E0FB000110F14 /* JSJavaScriptCallFramePrototype.cpp in Sources */,
</span><span class="cx">                                 14280875107EC13E0013E7B2 /* JSLock.cpp in Sources */,
</span><span class="cx">                                 0F3D0BBC194A414300FC9CF9 /* ConstantStructureCheck.cpp in Sources */,
</span><ins>+                                0F7B3661197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp in Sources */,
</ins><span class="cx">                                 C25D709B16DE99F400FCA6BC /* JSManagedValue.mm in Sources */,
</span><span class="cx">                                 A700874117CBE8EB00C3E643 /* JSMap.cpp in Sources */,
</span><span class="cx">                                 A74DEF95182D991400522C22 /* JSMapIterator.cpp in Sources */,
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -1848,12 +1848,25 @@
</span><span class="cx">     case ProfileDidCall:
</span><span class="cx">     case Phantom:
</span><span class="cx">     case HardPhantom:
</span><del>-    case Check:
</del><span class="cx">     case CountExecution:
</span><span class="cx">     case CheckTierUpInLoop:
</span><span class="cx">     case CheckTierUpAtReturn:
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case Check: {
+        // Simplify out checks that don't actually do checking.
+        for (unsigned i = 0; i &lt; AdjacencyList::Size; ++i) {
+            Edge edge = node-&gt;children.child(i);
+            if (!edge)
+                break;
+            if (edge.isProved() || edge.willNotHaveCheck()) {
+                m_state.setFoundConstants(true);
+                break;
+            }
+        }
+        break;
+    }
+
</ins><span class="cx">     case StoreBarrier: {
</span><span class="cx">         filter(node-&gt;child1(), SpecCell);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -86,6 +86,7 @@
</span><span class="cx">             
</span><span class="cx">             Node* node = block-&gt;at(indexInBlock);
</span><span class="cx"> 
</span><ins>+            bool alreadyHandled = false;
</ins><span class="cx">             bool eliminated = false;
</span><span class="cx">                     
</span><span class="cx">             switch (node-&gt;op()) {
</span><span class="lines">@@ -166,7 +167,7 @@
</span><span class="cx">                 AbstractValue baseValue = m_state.forNode(base);
</span><span class="cx">                 
</span><span class="cx">                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
</span><del>-                eliminated = true; // Don't allow the default constant folder to do things to this.
</del><ins>+                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
</ins><span class="cx">                 
</span><span class="cx">                 for (unsigned i = 0; i &lt; data.variants.size(); ++i) {
</span><span class="cx">                     GetByIdVariant&amp; variant = data.variants[i];
</span><span class="lines">@@ -174,6 +175,7 @@
</span><span class="cx">                     if (variant.structureSet().isEmpty()) {
</span><span class="cx">                         data.variants[i--] = data.variants.last();
</span><span class="cx">                         data.variants.removeLast();
</span><ins>+                        changed = true;
</ins><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx">                 
</span><span class="lines">@@ -182,6 +184,7 @@
</span><span class="cx">                 
</span><span class="cx">                 emitGetByOffset(
</span><span class="cx">                     indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
</span><ins>+                changed = true;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><span class="lines">@@ -193,7 +196,7 @@
</span><span class="cx">                 AbstractValue baseValue = m_state.forNode(base);
</span><span class="cx"> 
</span><span class="cx">                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
</span><del>-                eliminated = true; // Don't allow the default constant folder to do things to this.
</del><ins>+                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
</ins><span class="cx">                 
</span><span class="cx"> 
</span><span class="cx">                 for (unsigned i = 0; i &lt; data.variants.size(); ++i) {
</span><span class="lines">@@ -203,6 +206,7 @@
</span><span class="cx">                     if (variant.oldStructure().isEmpty()) {
</span><span class="cx">                         data.variants[i--] = data.variants.last();
</span><span class="cx">                         data.variants.removeLast();
</span><ins>+                        changed = true;
</ins><span class="cx">                         continue;
</span><span class="cx">                     }
</span><span class="cx">                     
</span><span class="lines">@@ -211,6 +215,7 @@
</span><span class="cx">                         variant = PutByIdVariant::replace(
</span><span class="cx">                             variant.oldStructure(),
</span><span class="cx">                             variant.offset());
</span><ins>+                        changed = true;
</ins><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="lines">@@ -219,6 +224,7 @@
</span><span class="cx">                 
</span><span class="cx">                 emitPutByOffset(
</span><span class="cx">                     indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
</span><ins>+                changed = true;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         
</span><span class="lines">@@ -231,7 +237,7 @@
</span><span class="cx">                 AbstractValue baseValue = m_state.forNode(child);
</span><span class="cx"> 
</span><span class="cx">                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
</span><del>-                eliminated = true; // Don't allow the default constant folder to do things to this.
</del><ins>+                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
</ins><span class="cx"> 
</span><span class="cx">                 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()
</span><span class="cx">                     || (node-&gt;child1().useKind() == UntypedUse || (baseValue.m_type &amp; ~SpecCell)))
</span><span class="lines">@@ -253,6 +259,7 @@
</span><span class="cx">                 
</span><span class="cx">                 if (status.numVariants() == 1) {
</span><span class="cx">                     emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
</span><ins>+                    changed = true;
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                 
</span><span class="lines">@@ -263,6 +270,7 @@
</span><span class="cx">                 data-&gt;variants = status.variants();
</span><span class="cx">                 data-&gt;identifierNumber = identifierNumber;
</span><span class="cx">                 node-&gt;convertToMultiGetByOffset(data);
</span><ins>+                changed = true;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><span class="lines">@@ -279,7 +287,7 @@
</span><span class="cx">                 AbstractValue baseValue = m_state.forNode(child);
</span><span class="cx"> 
</span><span class="cx">                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
</span><del>-                eliminated = true; // Don't allow the default constant folder to do things to this.
</del><ins>+                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
</ins><span class="cx"> 
</span><span class="cx">                 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered())
</span><span class="cx">                     break;
</span><span class="lines">@@ -294,6 +302,13 @@
</span><span class="cx">                 if (!status.isSimple())
</span><span class="cx">                     break;
</span><span class="cx">                 
</span><ins>+                ASSERT(status.numVariants());
+                
+                if (status.numVariants() &gt; 1 &amp;&amp; !isFTL(m_graph.m_plan.mode))
+                    break;
+                
+                changed = true;
+                
</ins><span class="cx">                 for (unsigned i = status.numVariants(); i--;)
</span><span class="cx">                     addChecks(origin, indexInBlock, status[i].constantChecks());
</span><span class="cx">                 
</span><span class="lines">@@ -302,8 +317,7 @@
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                 
</span><del>-                if (!isFTL(m_graph.m_plan.mode))
-                    break;
</del><ins>+                ASSERT(isFTL(m_graph.m_plan.mode));
</ins><span class="cx"> 
</span><span class="cx">                 MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
</span><span class="cx">                 data-&gt;variants = status.variants();
</span><span class="lines">@@ -317,6 +331,7 @@
</span><span class="cx">                     break;
</span><span class="cx">                 
</span><span class="cx">                 node-&gt;convertToIdentity();
</span><ins>+                changed = true;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><span class="lines">@@ -347,16 +362,34 @@
</span><span class="cx">                 
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+                
+            case Check: {
+                alreadyHandled = true;
+                m_interpreter.execute(indexInBlock);
+                for (unsigned i = 0; i &lt; AdjacencyList::Size; ++i) {
+                    Edge edge = node-&gt;children.child(i);
+                    if (!edge)
+                        break;
+                    if (edge.isProved() || edge.willNotHaveCheck()) {
+                        node-&gt;children.removeEdge(i--);
+                        changed = true;
+                    }
+                }
+                break;
+            }
</ins><span class="cx"> 
</span><span class="cx">             default:
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-                
</del><ins>+            
</ins><span class="cx">             if (eliminated) {
</span><span class="cx">                 changed = true;
</span><span class="cx">                 continue;
</span><span class="cx">             }
</span><span class="cx">                 
</span><ins>+            if (alreadyHandled)
+                continue;
+            
</ins><span class="cx">             m_interpreter.execute(indexInBlock);
</span><span class="cx">             if (!m_state.isValid()) {
</span><span class="cx">                 // If we invalidated then we shouldn't attempt to constant-fold. Here's an
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGDCEPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -49,12 +49,22 @@
</span><span class="cx">         ASSERT(m_graph.m_form == ThreadedCPS || m_graph.m_form == SSA);
</span><span class="cx">         
</span><span class="cx">         // First reset the counts to 0 for all nodes.
</span><ins>+        //
+        // Also take this opportunity to pretend that Check nodes are not NodeMustGenerate. Check
+        // nodes are MustGenerate because they are executed for effect, but they follow the same
+        // DCE rules as nodes that aren't MustGenerate: they only contribute to the ref count of
+        // their children if the edges require checks. Non-checking edges are removed. Note that
+        // for any Checks left over, this phase will turn them back into NodeMustGenerate.
</ins><span class="cx">         for (BlockIndex blockIndex = 0; blockIndex &lt; m_graph.numBlocks(); ++blockIndex) {
</span><span class="cx">             BasicBlock* block = m_graph.block(blockIndex);
</span><span class="cx">             if (!block)
</span><span class="cx">                 continue;
</span><del>-            for (unsigned indexInBlock = block-&gt;size(); indexInBlock--;)
-                block-&gt;at(indexInBlock)-&gt;setRefCount(0);
</del><ins>+            for (unsigned indexInBlock = block-&gt;size(); indexInBlock--;) {
+                Node* node = block-&gt;at(indexInBlock);
+                if (node-&gt;op() == Check)
+                    node-&gt;clearFlags(NodeMustGenerate);
+                node-&gt;setRefCount(0);
+            }
</ins><span class="cx">             for (unsigned phiIndex = block-&gt;phis.size(); phiIndex--;)
</span><span class="cx">                 block-&gt;phis[phiIndex]-&gt;setRefCount(0);
</span><span class="cx">         }
</span><span class="lines">@@ -121,6 +131,30 @@
</span><span class="cx">             cleanVariables(m_graph.m_arguments);
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        // Just do a basic HardPhantom/Phantom/Check clean-up.
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            unsigned sourceIndex = 0;
+            unsigned targetIndex = 0;
+            while (sourceIndex &lt; block-&gt;size()) {
+                Node* node = block-&gt;at(sourceIndex++);
+                switch (node-&gt;op()) {
+                case Check:
+                case HardPhantom:
+                case Phantom:
+                    if (node-&gt;children.isEmpty())
+                        continue;
+                    break;
+                default:
+                    break;
+                }
+                block-&gt;at(targetIndex++) = node;
+            }
+            block-&gt;resize(targetIndex);
+        }
+        
</ins><span class="cx">         m_graph.m_refCountState = ExactRefCount;
</span><span class="cx">         
</span><span class="cx">         return true;
</span><span class="lines">@@ -131,7 +165,7 @@
</span><span class="cx">     {
</span><span class="cx">         // We may have an &quot;unproved&quot; untyped use for code that is unreachable. The CFA
</span><span class="cx">         // will just not have gotten around to it.
</span><del>-        if (edge.willNotHaveCheck())
</del><ins>+        if (edge.isProved() || edge.willNotHaveCheck())
</ins><span class="cx">             return;
</span><span class="cx">         if (!edge-&gt;postfixRef())
</span><span class="cx">             m_worklist.append(edge.node());
</span><span class="lines">@@ -147,7 +181,7 @@
</span><span class="cx">     void countEdge(Node*, Edge edge)
</span><span class="cx">     {
</span><span class="cx">         // Don't count edges that are already counted for their type checks.
</span><del>-        if (edge.willHaveCheck())
</del><ins>+        if (!(edge.isProved() || edge.willNotHaveCheck()))
</ins><span class="cx">             return;
</span><span class="cx">         countNode(edge.node());
</span><span class="cx">     }
</span><span class="lines">@@ -214,10 +248,10 @@
</span><span class="cx">                     for (unsigned childIdx = node-&gt;firstChild(); childIdx &lt; node-&gt;firstChild() + node-&gt;numChildren(); childIdx++) {
</span><span class="cx">                         Edge edge = m_graph.m_varArgChildren[childIdx];
</span><span class="cx"> 
</span><del>-                        if (!edge || edge.willNotHaveCheck())
</del><ins>+                        if (!edge || edge.isProved() || edge.willNotHaveCheck())
</ins><span class="cx">                             continue;
</span><span class="cx"> 
</span><del>-                        m_insertionSet.insertNode(indexInBlock, SpecNone, Phantom, node-&gt;origin, edge);
</del><ins>+                        m_insertionSet.insertNode(indexInBlock, SpecNone, Check, node-&gt;origin, edge);
</ins><span class="cx">                     }
</span><span class="cx"> 
</span><span class="cx">                     node-&gt;convertToPhantom();
</span><span class="lines">@@ -226,8 +260,14 @@
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                node-&gt;convertToPhantom();
-                eliminateIrrelevantPhantomChildren(node);
</del><ins>+                node-&gt;convertToCheck();
+                for (unsigned i = 0; i &lt; AdjacencyList::Size; ++i) {
+                    Edge edge = node-&gt;children.child(i);
+                    if (!edge)
+                        continue;
+                    if (edge.isProved() || edge.willNotHaveCheck())
+                        node-&gt;children.removeEdge(i--);
+                }
</ins><span class="cx">                 node-&gt;setRefCount(1);
</span><span class="cx">                 break;
</span><span class="cx">             } }
</span><span class="lines">@@ -236,17 +276,6 @@
</span><span class="cx">         m_insertionSet.execute(block);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void eliminateIrrelevantPhantomChildren(Node* node)
-    {
-        for (unsigned i = 0; i &lt; AdjacencyList::Size; ++i) {
-            Edge edge = node-&gt;children.child(i);
-            if (!edge)
-                continue;
-            if (edge.willNotHaveCheck())
-                node-&gt;children.removeEdge(i--);
-        }
-    }
-    
</del><span class="cx">     template&lt;typename VariablesVectorType&gt;
</span><span class="cx">     void cleanVariables(VariablesVectorType&amp; variables)
</span><span class="cx">     {
</span><span class="lines">@@ -254,7 +283,7 @@
</span><span class="cx">             Node* node = variables[i];
</span><span class="cx">             if (!node)
</span><span class="cx">                 continue;
</span><del>-            if (node-&gt;op() != Phantom &amp;&amp; node-&gt;shouldGenerate())
</del><ins>+            if (node-&gt;op() != Phantom &amp;&amp; node-&gt;op() != Check &amp;&amp; node-&gt;shouldGenerate())
</ins><span class="cx">                 continue;
</span><span class="cx">             if (node-&gt;op() == GetLocal) {
</span><span class="cx">                 node = node-&gt;child1().node();
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGEdgecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGEdge.cpp (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGEdge.cpp        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGEdge.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</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">@@ -36,7 +36,7 @@
</span><span class="cx"> void Edge::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     if (useKindUnchecked() != UntypedUse) {
</span><del>-        if (needsCheck())
</del><ins>+        if (!isProved())
</ins><span class="cx">             out.print(&quot;Check:&quot;);
</span><span class="cx">         out.print(useKind(), &quot;:&quot;);
</span><span class="cx">     }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGEdgeh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGEdge.h (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGEdge.h        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGEdge.h        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -115,10 +115,6 @@
</span><span class="cx">     {
</span><span class="cx">         return proofStatus() == IsProved;
</span><span class="cx">     }
</span><del>-    bool needsCheck() const
-    {
-        return proofStatus() == NeedsCheck;
-    }
</del><span class="cx">     
</span><span class="cx">     bool willNotHaveCheck() const
</span><span class="cx">     {
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.cpp (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -157,7 +157,6 @@
</span><span class="cx">     NodeType op = node-&gt;op();
</span><span class="cx"> 
</span><span class="cx">     unsigned refCount = node-&gt;refCount();
</span><del>-    bool skipped = !refCount;
</del><span class="cx">     bool mustGenerate = node-&gt;mustGenerate();
</span><span class="cx">     if (mustGenerate)
</span><span class="cx">         --refCount;
</span><span class="lines">@@ -181,8 +180,8 @@
</span><span class="cx">     //         arg# - an argument number.
</span><span class="cx">     //         id#  - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }.
</span><span class="cx">     //         var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations.
</span><del>-    out.printf(&quot;% 4d:%s&lt;%c%u:&quot;, (int)node-&gt;index(), skipped ? &quot;  skipped  &quot; : &quot;           &quot;, mustGenerate ? '!' : ' ', refCount);
-    if (node-&gt;hasResult() &amp;&amp; !skipped &amp;&amp; node-&gt;hasVirtualRegister())
</del><ins>+    out.printf(&quot;% 4d:&lt;%c%u:&quot;, (int)node-&gt;index(), mustGenerate ? '!' : ' ', refCount);
+    if (node-&gt;hasResult() &amp;&amp; node-&gt;hasVirtualRegister() &amp;&amp; node-&gt;virtualRegister().isValid())
</ins><span class="cx">         out.print(node-&gt;virtualRegister());
</span><span class="cx">     else
</span><span class="cx">         out.print(&quot;-&quot;);
</span><span class="lines">@@ -352,12 +351,10 @@
</span><span class="cx">     
</span><span class="cx">     out.print(&quot;)&quot;);
</span><span class="cx"> 
</span><del>-    if (!skipped) {
-        if (node-&gt;hasVariableAccessData(*this) &amp;&amp; node-&gt;tryGetVariableAccessData())
-            out.print(&quot;  predicting &quot;, SpeculationDump(node-&gt;tryGetVariableAccessData()-&gt;prediction()));
-        else if (node-&gt;hasHeapPrediction())
-            out.print(&quot;  predicting &quot;, SpeculationDump(node-&gt;getHeapPrediction()));
-    }
</del><ins>+    if (node-&gt;hasVariableAccessData(*this) &amp;&amp; node-&gt;tryGetVariableAccessData())
+        out.print(&quot;  predicting &quot;, SpeculationDump(node-&gt;tryGetVariableAccessData()-&gt;prediction()));
+    else if (node-&gt;hasHeapPrediction())
+        out.print(&quot;  predicting &quot;, SpeculationDump(node-&gt;getHeapPrediction()));
</ins><span class="cx">     
</span><span class="cx">     out.print(&quot;\n&quot;);
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGNodeFlagsh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeFlags.h (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeFlags.h        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeFlags.h        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -68,6 +68,9 @@
</span><span class="cx"> 
</span><span class="cx"> #define NodeIsFlushed                    0x8000 // Used by Graph::computeIsFlushed(), will tell you which local nodes are backwards-reachable from a Flush.
</span><span class="cx"> 
</span><ins>+#define NodeMiscFlag1                   0x10000
+#define NodeMiscFlag2                   0x20000
+
</ins><span class="cx"> typedef uint32_t NodeFlags;
</span><span class="cx"> 
</span><span class="cx"> static inline bool bytecodeUsesAsNumber(NodeFlags flags)
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeType.h (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx">     macro(GetArgument, NodeResultJS | NodeMustGenerate) \
</span><span class="cx">     macro(Phantom, NodeMustGenerate) \
</span><span class="cx">     macro(HardPhantom, NodeMustGenerate) /* Like Phantom, but we never remove any of its children. */ \
</span><del>-    macro(Check, 0) /* Used if we want just a type check but not liveness. DCE eithers kills this or converts it to Phantom. */\
</del><ins>+    macro(Check, NodeMustGenerate) /* Used if we want just a type check but not liveness. Non-checking uses will be removed. */\
</ins><span class="cx">     macro(Upsilon, NodeRelevantToOSR) \
</span><span class="cx">     macro(Phi, NodeRelevantToOSR) \
</span><span class="cx">     macro(Flush, NodeMustGenerate) \
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGPhantomCanonicalizationPhasecpp"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp (0 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -0,0 +1,137 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;DFGPhantomCanonicalizationPhase.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGGraph.h&quot;
+#include &quot;DFGInsertionSet.h&quot;
+#include &quot;DFGPhase.h&quot;
+#include &quot;DFGPredictionPropagationPhase.h&quot;
+#include &quot;DFGVariableAccessDataDump.h&quot;
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC { namespace DFG {
+
+static const NodeFlags NodeNeedsPhantom = NodeMiscFlag1;
+static const NodeFlags NodeNeedsHardPhantom = NodeMiscFlag2;
+
+class PhantomCanonicalizationPhase : public Phase {
+public:
+    PhantomCanonicalizationPhase(Graph&amp; graph)
+        : Phase(graph, &quot;phantom canonicalization&quot;)
+    {
+    }
+    
+    bool run()
+    {
+        ASSERT(m_graph.m_form == SSA);
+        
+        m_graph.clearFlagsOnAllNodes(NodeNeedsPhantom | NodeNeedsHardPhantom | NodeRelevantToOSR);
+        
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            
+            for (unsigned i = block-&gt;size(); i--;) {
+                Node* node = block-&gt;at(i);
+                if (node-&gt;op() == MovHint)
+                    node-&gt;child1()-&gt;mergeFlags(NodeRelevantToOSR);
+            }
+        }
+        
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            
+            unsigned sourceIndex = 0;
+            unsigned targetIndex = 0;
+            while (sourceIndex &lt; block-&gt;size()) {
+                Node* node = block-&gt;at(sourceIndex++);
+                if (node-&gt;op() == HardPhantom || node-&gt;op() == Phantom || node-&gt;op() == Check) {
+                    for (unsigned i = 0; i &lt; AdjacencyList::Size; ++i) {
+                        Edge edge = node-&gt;children.child(i);
+                        if (!edge)
+                            break;
+                        if (node-&gt;op() == HardPhantom)
+                            edge-&gt;mergeFlags(NodeNeedsHardPhantom);
+                        if ((edge-&gt;flags() &amp; NodeRelevantToOSR) &amp;&amp; node-&gt;op() == Phantom) {
+                            // A Phantom on a node that is RelevantToOSR means that we need to keep
+                            // a Phantom on this node instead of just having a Check.
+                            edge-&gt;mergeFlags(NodeNeedsPhantom);
+                        }
+                        if (edge.willHaveCheck())
+                            continue; // Keep the type check.
+                        
+                        node-&gt;children.removeEdge(i--);
+                    }
+                    
+                    if (node-&gt;children.isEmpty())
+                        continue;
+                    
+                    node-&gt;convertToCheck();
+                }
+                block-&gt;at(targetIndex++) = node;
+            }
+            block-&gt;resize(targetIndex);
+        }
+        
+        InsertionSet insertionSet(m_graph);
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            
+            for (unsigned nodeIndex = 0; nodeIndex &lt; block-&gt;size(); ++nodeIndex) {
+                Node* node = block-&gt;at(nodeIndex);
+                if (node-&gt;flags() &amp; NodeNeedsHardPhantom) {
+                    insertionSet.insertNode(
+                        nodeIndex + 1, SpecNone, HardPhantom, node-&gt;origin, node-&gt;defaultEdge());
+                } else if (node-&gt;flags() &amp; NodeNeedsPhantom) {
+                    insertionSet.insertNode(
+                        nodeIndex + 1, SpecNone, Phantom, node-&gt;origin, node-&gt;defaultEdge());
+                }
+            }
+            insertionSet.execute(block);
+        }
+        
+        return true;
+    }
+};
+    
+bool performPhantomCanonicalization(Graph&amp; graph)
+{
+    SamplingRegion samplingRegion(&quot;DFG Phantom Canonicalization Phase&quot;);
+    return runPhase&lt;PhantomCanonicalizationPhase&gt;(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGPhantomCanonicalizationPhaseh"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.h (0 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.h                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.h        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGPhantomCanonicalizationPhase_h
+#define DFGPhantomCanonicalizationPhase_h
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Replaces all pre-existing Phantoms with Checks or removes them if the Check is unnecessary. If
+// the Phantom was necessary (it uses a node that is relevant to OSR) then the Phantom is hoisted
+// to just below the node.
+//
+// This phase is only valid in SSA, because it's only in SSA that Phantoms are ignored for the
+// purpose of liveness-at-some-point and are only used for absolute liveness.
+//
+// This phase makes a lot of things easier, like CFG simplification: you don't have to insert any
+// phantoms when jettisoning a CFG edge.
+
+bool performPhantomCanonicalization(Graph&amp;);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGPhantomCanonicalizationPhase_h
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGPhantomRemovalPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -96,14 +96,15 @@
</span><span class="cx">             Node* lastNode = nullptr;
</span><span class="cx">             while (sourceIndex &lt; block-&gt;size()) {
</span><span class="cx">                 Node* node = block-&gt;at(sourceIndex++);
</span><del>-                if (node-&gt;op() == Phantom) {
</del><ins>+                switch (node-&gt;op()) {
+                case Phantom: {
</ins><span class="cx">                     if (lastNode &amp;&amp; (lastNode-&gt;origin.forExit != node-&gt;origin.forExit || (lastNode-&gt;flags() &amp; NodeHasVarArgs)))
</span><span class="cx">                         lastNode = nullptr;
</span><span class="cx">                     for (unsigned i = 0; i &lt; AdjacencyList::Size; ++i) {
</span><span class="cx">                         Edge edge = node-&gt;children.child(i);
</span><span class="cx">                         if (!edge)
</span><span class="cx">                             break;
</span><del>-                        if (edge.useKind() != UntypedUse)
</del><ins>+                        if (edge.willHaveCheck())
</ins><span class="cx">                             continue; // Keep the type check.
</span><span class="cx">                         if (edge-&gt;flags() &amp; NodeRelevantToOSR) {
</span><span class="cx">                             bool found = false;
</span><span class="lines">@@ -123,9 +124,39 @@
</span><span class="cx">                         changed = true;
</span><span class="cx">                     }
</span><span class="cx">                     
</span><ins>+                    if (node-&gt;children.isEmpty()) {
+                        changed = true;
+                        continue;
+                    }
+                    break;
+                }
+                    
+                case Check: {
+                    for (unsigned i = 0; i &lt; AdjacencyList::Size; ++i) {
+                        Edge edge = node-&gt;children.child(i);
+                        if (!edge)
+                            break;
+                        if (edge.willHaveCheck())
+                            continue;
+                        node-&gt;children.removeEdge(i--);
+                        changed = true;
+                    }
+                    if (node-&gt;children.isEmpty()) {
+                        changed = true;
+                        continue;
+                    }
+                    break;
+                }
+                    
+                case HardPhantom: {
</ins><span class="cx">                     if (node-&gt;children.isEmpty())
</span><span class="cx">                         continue;
</span><ins>+                    break;
</ins><span class="cx">                 }
</span><ins>+                    
+                default:
+                    break;
+                }
</ins><span class="cx">                 lastNode = node;
</span><span class="cx">                 block-&gt;at(targetIndex++) = node;
</span><span class="cx">             }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGPhantomRemovalPhaseh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.h (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.h        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.h        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -34,6 +34,9 @@
</span><span class="cx"> 
</span><span class="cx"> // Cleans up unnecessary Phantoms and Phanton children. This reduces live ranges, but also, it
</span><span class="cx"> // eliminates many Phantoms entirely. This invalidates liveness analysis.
</span><ins>+//
+// This should work over all IR forms; however, in SSA form it's better to run
+// PhantomCanonicalizationPhase since it's more powerful.
</ins><span class="cx"> 
</span><span class="cx"> bool performPhantomRemoval(Graph&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGPlan.cpp (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGPlan.cpp        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGPlan.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx"> #include &quot;DFGLoopPreHeaderCreationPhase.h&quot;
</span><span class="cx"> #include &quot;DFGOSRAvailabilityAnalysisPhase.h&quot;
</span><span class="cx"> #include &quot;DFGOSREntrypointCreationPhase.h&quot;
</span><ins>+#include &quot;DFGPhantomCanonicalizationPhase.h&quot;
</ins><span class="cx"> #include &quot;DFGPhantomRemovalPhase.h&quot;
</span><span class="cx"> #include &quot;DFGPredictionInjectionPhase.h&quot;
</span><span class="cx"> #include &quot;DFGPredictionPropagationPhase.h&quot;
</span><span class="lines">@@ -310,7 +311,7 @@
</span><span class="cx">             return FailPath;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        performPhantomRemoval(dfg);
</del><ins>+        performPhantomRemoval(dfg); // Reduce the graph size a bit.
</ins><span class="cx">         performCriticalEdgeBreaking(dfg);
</span><span class="cx">         performLoopPreHeaderCreation(dfg);
</span><span class="cx">         performCPSRethreading(dfg);
</span><span class="lines">@@ -320,6 +321,7 @@
</span><span class="cx">         performLivenessAnalysis(dfg);
</span><span class="cx">         performCFA(dfg);
</span><span class="cx">         performConstantFolding(dfg);
</span><ins>+        performPhantomCanonicalization(dfg); // Reduce the graph size a lot.
</ins><span class="cx">         if (performStrengthReduction(dfg)) {
</span><span class="cx">             // State-at-tail and state-at-head will be invalid if we did strength reduction since
</span><span class="cx">             // it might increase live ranges.
</span><span class="lines">@@ -327,7 +329,7 @@
</span><span class="cx">             performCFA(dfg);
</span><span class="cx">         }
</span><span class="cx">         performLICM(dfg);
</span><del>-        performPhantomRemoval(dfg);
</del><ins>+        performPhantomCanonicalization(dfg);
</ins><span class="cx">         performIntegerCheckCombining(dfg);
</span><span class="cx">         performGlobalCSE(dfg);
</span><span class="cx">         
</span><span class="lines">@@ -336,7 +338,7 @@
</span><span class="cx">         dfg.m_fixpointState = FixpointConverged;
</span><span class="cx">         
</span><span class="cx">         performStoreBarrierElision(dfg);
</span><del>-        performPhantomRemoval(dfg);
</del><ins>+        performPhantomCanonicalization(dfg);
</ins><span class="cx">         performLivenessAnalysis(dfg);
</span><span class="cx">         performCFA(dfg);
</span><span class="cx">         if (Options::validateFTLOSRExitLiveness())
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -1779,8 +1779,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MovHint:
</span><del>-    case ZombieHint:
-    case Check: {
</del><ins>+    case ZombieHint: {
</ins><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -4572,6 +4571,7 @@
</span><span class="cx"> 
</span><span class="cx">     case Phantom:
</span><span class="cx">     case HardPhantom:
</span><ins>+    case Check:
</ins><span class="cx">         DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
</span><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -1862,8 +1862,7 @@
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case MovHint:
</span><del>-    case ZombieHint:
-    case Check: {
</del><ins>+    case ZombieHint: {
</ins><span class="cx">         DFG_CRASH(m_jit.graph(), node, &quot;Unexpected node&quot;);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -4560,6 +4559,7 @@
</span><span class="cx"> 
</span><span class="cx">     case Phantom:
</span><span class="cx">     case HardPhantom:
</span><ins>+    case Check:
</ins><span class="cx">         DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
</span><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (171494 => 171495)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-07-23 22:55:37 UTC (rev 171494)
+++ branches/ftlopt/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-07-23 23:06:55 UTC (rev 171495)
</span><span class="lines">@@ -395,6 +395,7 @@
</span><span class="cx">             break;
</span><span class="cx">         case Phantom:
</span><span class="cx">         case HardPhantom:
</span><ins>+        case Check:
</ins><span class="cx">             compilePhantom();
</span><span class="cx">             break;
</span><span class="cx">         case ToThis:
</span><span class="lines">@@ -5217,7 +5218,7 @@
</span><span class="cx">     
</span><span class="cx">     LValue lowJSValue(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
</span><span class="cx">     {
</span><del>-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
</del><ins>+        DFG_ASSERT(m_graph, m_node, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
</ins><span class="cx">         DFG_ASSERT(m_graph, m_node, !isDouble(edge.useKind()));
</span><span class="cx">         DFG_ASSERT(m_graph, m_node, edge.useKind() != Int52RepUse);
</span><span class="cx">         
</span><span class="lines">@@ -5626,7 +5627,7 @@
</span><span class="cx">         if (!m_interpreter.needsTypeCheck(edge))
</span><span class="cx">             return;
</span><span class="cx">         
</span><del>-        LValue value = lowJSValue(edge);
</del><ins>+        LValue value = lowJSValue(edge, ManualOperandSpeculation);
</ins><span class="cx">         
</span><span class="cx">         LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, (&quot;speculateObjectOrOther cell case&quot;));
</span><span class="cx">         LBasicBlock primitiveCase = FTL_NEW_BLOCK(m_out, (&quot;speculateObjectOrOther primitive case&quot;));
</span></span></pre>
</div>
</div>

</body>
</html>