<!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>[152959] branches/dfgFourthTier/Source</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/152959">152959</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2013-07-21 21:04:41 -0700 (Sun, 21 Jul 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>fourthTier: DFG Nodes should be able to abstractly tell you what they read and what they write
https://bugs.webkit.org/show_bug.cgi?id=118910

Source/JavaScriptCore: 

Reviewed by Sam Weinig.
        
Add the notion of AbstractHeap to the DFG. This is analogous to the AbstractHeap in
the FTL, except that the FTL's AbstractHeaps are used during LLVM lowering and are
engineered to obey LLVM TBAA logic. The FTL's AbstractHeaps are also engineered to
be inexpensive to use (they just give you a TBAA node) but expensive to create (you
create them all up front). FTL AbstractHeaps also don't actually give you the
ability to reason about aliasing; they are *just* a mechanism for lowering to TBAA.
The DFG's AbstractHeaps are engineered to be both cheap to create and cheap to use.
They also give you aliasing machinery. The DFG AbstractHeaps are represented
internally by a int64_t. Many comparisons between them are just integer comaprisons.
AbstractHeaps form a three-level hierarchy (World is the supertype of everything,
Kind with a TOP payload is a direct subtype of World, and Kind with a non-TOP
payload is the direct subtype of its corresponding TOP Kind).
        
Add the notion of a ClobberSet. This is the set of AbstractHeaps that you had
clobbered. It represents the set that results from unifying a bunch of
AbstractHeaps, and is intended to quickly answer overlap questions: does the given
AbstractHeap overlap any AbstractHeap in the ClobberSet? To this end, if you add an
AbstractHeap to a set, it &quot;directly&quot; adds the heap itself, and &quot;super&quot; adds all of
its ancestors. An AbstractHeap is said to overlap a set if any direct or super
member is equal to it, or if any of its ancestors are equal to a direct member.
        
Example #1:
        
    - I add Variables(5). I.e. Variables is the Kind and 5 is the payload. This
      is a subtype of Variables, which is a subtype of World.
    - You query Variables. I.e. Variables with a TOP payload, which is the
      supertype of Variables(X) for any X, and a subtype of World.
            
    The set will have Variables(5) as a direct member, and Variables and World as
    super members. The Variables query will immediately return true, because
    Variables is indeed a super member.
        
Example #2:
        
    - I add Variables(5)
    - You query NamedProperties
            
    NamedProperties is not a member at all (neither direct or super). We next
    query World. World is a member, but it's a super member, so we return false.
        
Example #3:
        
    - I add Variables
    - You query Variables(5)
            
    The set will have Variables as a direct member, and World as a super member.
    The Variables(5) query will not find Variables(5) in the set, but then it
    will query Variables. Variables is a direct member, so we return true.
        
Example #4:
        
    - I add Variables
    - You query NamedProperties(5)
            
    Neither NamedProperties nor NamedProperties(5) are members. We next query
    World. World is a member, but it's a super member, so we return false.
        
Overlap queries require that either the heap being queried is in the set (either
direct or super), or that one of its ancestors is a direct member. Another way to
think about how this works is that two heaps A and B are said to overlap if
A.isSubtypeOf(B) or B.isSubtypeOf(A). This is sound since heaps form a
single-inheritance heirarchy. Consider that we wanted to implement a set that holds
heaps and answers the question, &quot;is any member in the set an ancestor (i.e.
supertype) of some other heap&quot;. We would have the set contain the heaps themselves,
and we would satisfy the query &quot;A.isSubtypeOfAny(set)&quot; by walking the ancestor
chain of A, and repeatedly querying its membership in the set. This is what the
&quot;direct&quot; members of our set do. Now consider the other part, where we want to ask if
any member of the set is a descendent of a heap, or &quot;A.isSupertypeOfAny(set)&quot;. We
would implement this by implementing set.add(B) as adding not just B but also all of
B's ancestors; then we would answer A.isSupertypeOfAny(set) by just checking if A is
in the set. With two such sets - one that answers isSubtypeOfAny() and another that
answers isSupertypeOfAny() - we could answer the &quot;do any of my heaps overlap your
heap&quot; question. ClobberSet does this, but combines the two sets into a single
HashMap. The HashMap's value, &quot;direct&quot;, means that the key is a member of both the
supertype set and the subtype set; if it's false then it's only a member of one of
them.
        
Finally, this adds a functorized clobberize() method that adds the read and write
clobbers of a DFG::Node to read and write functors. Common functors for adding to
ClobberSets, querying overlap, and doing nothing are provided. Convenient wrappers
are also provided. This allows you to say things like:
        
    ClobberSet set;
    addWrites(graph, node1, set);
    if (readsOverlap(graph, node2, set))
        // We know that node1 may write to something that node2 may read from.
        
Currently this facility is only used to improve graph dumping, but it will be
instrumental in both LICM and GVN. In the future, I want to completely kill the
NodeClobbersWorld and NodeMightClobber flags, and eradicate CSEPhase's hackish way
of accomplishing almost exactly what AbstractHeap gives you.

* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractHeap.cpp: Added.
(DFG):
(JSC::DFG::AbstractHeap::Payload::dump):
(JSC::DFG::AbstractHeap::dump):
(WTF):
(WTF::printInternal):
* dfg/DFGAbstractHeap.h: Added.
(DFG):
(AbstractHeap):
(Payload):
(JSC::DFG::AbstractHeap::Payload::Payload):
(JSC::DFG::AbstractHeap::Payload::top):
(JSC::DFG::AbstractHeap::Payload::isTop):
(JSC::DFG::AbstractHeap::Payload::value):
(JSC::DFG::AbstractHeap::Payload::valueImpl):
(JSC::DFG::AbstractHeap::Payload::operator==):
(JSC::DFG::AbstractHeap::Payload::operator!=):
(JSC::DFG::AbstractHeap::Payload::operator&lt;):
(JSC::DFG::AbstractHeap::Payload::isDisjoint):
(JSC::DFG::AbstractHeap::Payload::overlaps):
(JSC::DFG::AbstractHeap::AbstractHeap):
(JSC::DFG::AbstractHeap::operator!):
(JSC::DFG::AbstractHeap::kind):
(JSC::DFG::AbstractHeap::payload):
(JSC::DFG::AbstractHeap::isDisjoint):
(JSC::DFG::AbstractHeap::overlaps):
(JSC::DFG::AbstractHeap::supertype):
(JSC::DFG::AbstractHeap::hash):
(JSC::DFG::AbstractHeap::operator==):
(JSC::DFG::AbstractHeap::operator!=):
(JSC::DFG::AbstractHeap::operator&lt;):
(JSC::DFG::AbstractHeap::isHashTableDeletedValue):
(JSC::DFG::AbstractHeap::payloadImpl):
(JSC::DFG::AbstractHeap::encode):
(JSC::DFG::AbstractHeapHash::hash):
(JSC::DFG::AbstractHeapHash::equal):
(AbstractHeapHash):
(WTF):
* dfg/DFGClobberSet.cpp: Added.
(DFG):
(JSC::DFG::ClobberSet::ClobberSet):
(JSC::DFG::ClobberSet::~ClobberSet):
(JSC::DFG::ClobberSet::add):
(JSC::DFG::ClobberSet::addAll):
(JSC::DFG::ClobberSet::contains):
(JSC::DFG::ClobberSet::overlaps):
(JSC::DFG::ClobberSet::clear):
(JSC::DFG::ClobberSet::direct):
(JSC::DFG::ClobberSet::super):
(JSC::DFG::ClobberSet::dump):
(JSC::DFG::ClobberSet::setOf):
(JSC::DFG::addReads):
(JSC::DFG::addWrites):
(JSC::DFG::addReadsAndWrites):
(JSC::DFG::readsOverlap):
(JSC::DFG::writesOverlap):
* dfg/DFGClobberSet.h: Added.
(DFG):
(ClobberSet):
(JSC::DFG::ClobberSet::isEmpty):
(ClobberSetAdd):
(JSC::DFG::ClobberSetAdd::ClobberSetAdd):
(JSC::DFG::ClobberSetAdd::operator()):
(ClobberSetOverlaps):
(JSC::DFG::ClobberSetOverlaps::ClobberSetOverlaps):
(JSC::DFG::ClobberSetOverlaps::operator()):
(JSC::DFG::ClobberSetOverlaps::result):
* dfg/DFGClobberize.cpp: Added.
(DFG):
(JSC::DFG::didWrites):
* dfg/DFGClobberize.h: Added.
(DFG):
(JSC::DFG::clobberize):
(NoOpClobberize):
(JSC::DFG::NoOpClobberize::NoOpClobberize):
(JSC::DFG::NoOpClobberize::operator()):
(CheckClobberize):
(JSC::DFG::CheckClobberize::CheckClobberize):
(JSC::DFG::CheckClobberize::operator()):
(JSC::DFG::CheckClobberize::result):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):

Source/WTF: 

Reviewed by Sam Weinig.
        
Fix compile goof in sortedListDump().

* wtf/ListDump.h:
(WTF::sortedListDump):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreChangeLog">branches/dfgFourthTier/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">branches/dfgFourthTier/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGGraphcpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceWTFChangeLog">branches/dfgFourthTier/Source/WTF/ChangeLog</a></li>
<li><a href="#branchesdfgFourthTierSourceWTFwtfListDumph">branches/dfgFourthTier/Source/WTF/wtf/ListDump.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGAbstractHeapcpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGAbstractHeap.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGAbstractHeaph">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGAbstractHeap.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGClobberSetcpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberSet.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGClobberSeth">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberSet.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGClobberizecpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberize.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGClobberizeh">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesdfgFourthTierSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/ChangeLog (152958 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/ChangeLog        2013-07-22 03:57:32 UTC (rev 152958)
+++ branches/dfgFourthTier/Source/JavaScriptCore/ChangeLog        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -1,5 +1,188 @@
</span><span class="cx"> 2013-07-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        fourthTier: DFG Nodes should be able to abstractly tell you what they read and what they write
+        https://bugs.webkit.org/show_bug.cgi?id=118910
+
+        Reviewed by Sam Weinig.
+        
+        Add the notion of AbstractHeap to the DFG. This is analogous to the AbstractHeap in
+        the FTL, except that the FTL's AbstractHeaps are used during LLVM lowering and are
+        engineered to obey LLVM TBAA logic. The FTL's AbstractHeaps are also engineered to
+        be inexpensive to use (they just give you a TBAA node) but expensive to create (you
+        create them all up front). FTL AbstractHeaps also don't actually give you the
+        ability to reason about aliasing; they are *just* a mechanism for lowering to TBAA.
+        The DFG's AbstractHeaps are engineered to be both cheap to create and cheap to use.
+        They also give you aliasing machinery. The DFG AbstractHeaps are represented
+        internally by a int64_t. Many comparisons between them are just integer comaprisons.
+        AbstractHeaps form a three-level hierarchy (World is the supertype of everything,
+        Kind with a TOP payload is a direct subtype of World, and Kind with a non-TOP
+        payload is the direct subtype of its corresponding TOP Kind).
+        
+        Add the notion of a ClobberSet. This is the set of AbstractHeaps that you had
+        clobbered. It represents the set that results from unifying a bunch of
+        AbstractHeaps, and is intended to quickly answer overlap questions: does the given
+        AbstractHeap overlap any AbstractHeap in the ClobberSet? To this end, if you add an
+        AbstractHeap to a set, it &quot;directly&quot; adds the heap itself, and &quot;super&quot; adds all of
+        its ancestors. An AbstractHeap is said to overlap a set if any direct or super
+        member is equal to it, or if any of its ancestors are equal to a direct member.
+        
+        Example #1:
+        
+            - I add Variables(5). I.e. Variables is the Kind and 5 is the payload. This
+              is a subtype of Variables, which is a subtype of World.
+            - You query Variables. I.e. Variables with a TOP payload, which is the
+              supertype of Variables(X) for any X, and a subtype of World.
+            
+            The set will have Variables(5) as a direct member, and Variables and World as
+            super members. The Variables query will immediately return true, because
+            Variables is indeed a super member.
+        
+        Example #2:
+        
+            - I add Variables(5)
+            - You query NamedProperties
+            
+            NamedProperties is not a member at all (neither direct or super). We next
+            query World. World is a member, but it's a super member, so we return false.
+        
+        Example #3:
+        
+            - I add Variables
+            - You query Variables(5)
+            
+            The set will have Variables as a direct member, and World as a super member.
+            The Variables(5) query will not find Variables(5) in the set, but then it
+            will query Variables. Variables is a direct member, so we return true.
+        
+        Example #4:
+        
+            - I add Variables
+            - You query NamedProperties(5)
+            
+            Neither NamedProperties nor NamedProperties(5) are members. We next query
+            World. World is a member, but it's a super member, so we return false.
+        
+        Overlap queries require that either the heap being queried is in the set (either
+        direct or super), or that one of its ancestors is a direct member. Another way to
+        think about how this works is that two heaps A and B are said to overlap if
+        A.isSubtypeOf(B) or B.isSubtypeOf(A). This is sound since heaps form a
+        single-inheritance heirarchy. Consider that we wanted to implement a set that holds
+        heaps and answers the question, &quot;is any member in the set an ancestor (i.e.
+        supertype) of some other heap&quot;. We would have the set contain the heaps themselves,
+        and we would satisfy the query &quot;A.isSubtypeOfAny(set)&quot; by walking the ancestor
+        chain of A, and repeatedly querying its membership in the set. This is what the
+        &quot;direct&quot; members of our set do. Now consider the other part, where we want to ask if
+        any member of the set is a descendent of a heap, or &quot;A.isSupertypeOfAny(set)&quot;. We
+        would implement this by implementing set.add(B) as adding not just B but also all of
+        B's ancestors; then we would answer A.isSupertypeOfAny(set) by just checking if A is
+        in the set. With two such sets - one that answers isSubtypeOfAny() and another that
+        answers isSupertypeOfAny() - we could answer the &quot;do any of my heaps overlap your
+        heap&quot; question. ClobberSet does this, but combines the two sets into a single
+        HashMap. The HashMap's value, &quot;direct&quot;, means that the key is a member of both the
+        supertype set and the subtype set; if it's false then it's only a member of one of
+        them.
+        
+        Finally, this adds a functorized clobberize() method that adds the read and write
+        clobbers of a DFG::Node to read and write functors. Common functors for adding to
+        ClobberSets, querying overlap, and doing nothing are provided. Convenient wrappers
+        are also provided. This allows you to say things like:
+        
+            ClobberSet set;
+            addWrites(graph, node1, set);
+            if (readsOverlap(graph, node2, set))
+                // We know that node1 may write to something that node2 may read from.
+        
+        Currently this facility is only used to improve graph dumping, but it will be
+        instrumental in both LICM and GVN. In the future, I want to completely kill the
+        NodeClobbersWorld and NodeMightClobber flags, and eradicate CSEPhase's hackish way
+        of accomplishing almost exactly what AbstractHeap gives you.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGAbstractHeap.cpp: Added.
+        (DFG):
+        (JSC::DFG::AbstractHeap::Payload::dump):
+        (JSC::DFG::AbstractHeap::dump):
+        (WTF):
+        (WTF::printInternal):
+        * dfg/DFGAbstractHeap.h: Added.
+        (DFG):
+        (AbstractHeap):
+        (Payload):
+        (JSC::DFG::AbstractHeap::Payload::Payload):
+        (JSC::DFG::AbstractHeap::Payload::top):
+        (JSC::DFG::AbstractHeap::Payload::isTop):
+        (JSC::DFG::AbstractHeap::Payload::value):
+        (JSC::DFG::AbstractHeap::Payload::valueImpl):
+        (JSC::DFG::AbstractHeap::Payload::operator==):
+        (JSC::DFG::AbstractHeap::Payload::operator!=):
+        (JSC::DFG::AbstractHeap::Payload::operator&lt;):
+        (JSC::DFG::AbstractHeap::Payload::isDisjoint):
+        (JSC::DFG::AbstractHeap::Payload::overlaps):
+        (JSC::DFG::AbstractHeap::AbstractHeap):
+        (JSC::DFG::AbstractHeap::operator!):
+        (JSC::DFG::AbstractHeap::kind):
+        (JSC::DFG::AbstractHeap::payload):
+        (JSC::DFG::AbstractHeap::isDisjoint):
+        (JSC::DFG::AbstractHeap::overlaps):
+        (JSC::DFG::AbstractHeap::supertype):
+        (JSC::DFG::AbstractHeap::hash):
+        (JSC::DFG::AbstractHeap::operator==):
+        (JSC::DFG::AbstractHeap::operator!=):
+        (JSC::DFG::AbstractHeap::operator&lt;):
+        (JSC::DFG::AbstractHeap::isHashTableDeletedValue):
+        (JSC::DFG::AbstractHeap::payloadImpl):
+        (JSC::DFG::AbstractHeap::encode):
+        (JSC::DFG::AbstractHeapHash::hash):
+        (JSC::DFG::AbstractHeapHash::equal):
+        (AbstractHeapHash):
+        (WTF):
+        * dfg/DFGClobberSet.cpp: Added.
+        (DFG):
+        (JSC::DFG::ClobberSet::ClobberSet):
+        (JSC::DFG::ClobberSet::~ClobberSet):
+        (JSC::DFG::ClobberSet::add):
+        (JSC::DFG::ClobberSet::addAll):
+        (JSC::DFG::ClobberSet::contains):
+        (JSC::DFG::ClobberSet::overlaps):
+        (JSC::DFG::ClobberSet::clear):
+        (JSC::DFG::ClobberSet::direct):
+        (JSC::DFG::ClobberSet::super):
+        (JSC::DFG::ClobberSet::dump):
+        (JSC::DFG::ClobberSet::setOf):
+        (JSC::DFG::addReads):
+        (JSC::DFG::addWrites):
+        (JSC::DFG::addReadsAndWrites):
+        (JSC::DFG::readsOverlap):
+        (JSC::DFG::writesOverlap):
+        * dfg/DFGClobberSet.h: Added.
+        (DFG):
+        (ClobberSet):
+        (JSC::DFG::ClobberSet::isEmpty):
+        (ClobberSetAdd):
+        (JSC::DFG::ClobberSetAdd::ClobberSetAdd):
+        (JSC::DFG::ClobberSetAdd::operator()):
+        (ClobberSetOverlaps):
+        (JSC::DFG::ClobberSetOverlaps::ClobberSetOverlaps):
+        (JSC::DFG::ClobberSetOverlaps::operator()):
+        (JSC::DFG::ClobberSetOverlaps::result):
+        * dfg/DFGClobberize.cpp: Added.
+        (DFG):
+        (JSC::DFG::didWrites):
+        * dfg/DFGClobberize.h: Added.
+        (DFG):
+        (JSC::DFG::clobberize):
+        (NoOpClobberize):
+        (JSC::DFG::NoOpClobberize::NoOpClobberize):
+        (JSC::DFG::NoOpClobberize::operator()):
+        (CheckClobberize):
+        (JSC::DFG::CheckClobberize::CheckClobberize):
+        (JSC::DFG::CheckClobberize::operator()):
+        (JSC::DFG::CheckClobberize::result):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+
+2013-07-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         fourthTier: It should be easy to figure out which blocks nodes belong to
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=118957
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (152958 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2013-07-22 03:57:32 UTC (rev 152958)
+++ branches/dfgFourthTier/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -375,9 +375,15 @@
</span><span class="cx">                 0FE5058F1798AE7100B35F8C /* DFGMergeMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE5058E1798AE6F00B35F8C /* DFGMergeMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FE50591179A492400B35F8C /* DFGSaneStringGetByValSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE50590179A492400B35F8C /* DFGSaneStringGetByValSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FE50593179A604500B35F8C /* DFGEdgeUsesStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE50592179A604500B35F8C /* DFGEdgeUsesStructure.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0FE50599179B0F7200B35F8C /* DFGAbstractHeap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE50594179B0F7200B35F8C /* DFGAbstractHeap.cpp */; };
+                0FE5059A179B0F7200B35F8C /* DFGAbstractHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE50595179B0F7200B35F8C /* DFGAbstractHeap.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0FE5059B179B0F7200B35F8C /* DFGClobberize.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE50596179B0F7200B35F8C /* DFGClobberize.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0FE5059C179B0F7200B35F8C /* DFGClobberSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE50597179B0F7200B35F8C /* DFGClobberSet.cpp */; };
+                0FE5059D179B0F7200B35F8C /* DFGClobberSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE50598179B0F7200B35F8C /* DFGClobberSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0FE5059F179B4A2300B35F8C /* DFGSafeToExecute.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE5059E179B4A2000B35F8C /* DFGSafeToExecute.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FE505A2179B60ED00B35F8C /* FTLFail.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE505A0179B60ED00B35F8C /* FTLFail.cpp */; };
</span><span class="cx">                 0FE505A3179B60ED00B35F8C /* FTLFail.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE505A1179B60ED00B35F8C /* FTLFail.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0FE505A5179CE3EC00B35F8C /* DFGClobberize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE505A4179CE3EC00B35F8C /* DFGClobberize.cpp */; };
</ins><span class="cx">                 0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */; };
</span><span class="cx">                 0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FEA0A08170513DB00BB722C /* FTLAbbreviations.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEA09FD170513DB00BB722C /* FTLAbbreviations.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -1431,9 +1437,15 @@
</span><span class="cx">                 0FE5058E1798AE6F00B35F8C /* DFGMergeMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DFGMergeMode.h; path = dfg/DFGMergeMode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE50590179A492400B35F8C /* DFGSaneStringGetByValSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSaneStringGetByValSlowPathGenerator.h; path = dfg/DFGSaneStringGetByValSlowPathGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE50592179A604500B35F8C /* DFGEdgeUsesStructure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdgeUsesStructure.h; path = dfg/DFGEdgeUsesStructure.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FE50594179B0F7200B35F8C /* DFGAbstractHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractHeap.cpp; path = dfg/DFGAbstractHeap.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FE50595179B0F7200B35F8C /* DFGAbstractHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractHeap.h; path = dfg/DFGAbstractHeap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FE50596179B0F7200B35F8C /* DFGClobberize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGClobberize.h; path = dfg/DFGClobberize.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FE50597179B0F7200B35F8C /* DFGClobberSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGClobberSet.cpp; path = dfg/DFGClobberSet.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FE50598179B0F7200B35F8C /* DFGClobberSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGClobberSet.h; path = dfg/DFGClobberSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FE5059E179B4A2000B35F8C /* DFGSafeToExecute.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DFGSafeToExecute.h; path = dfg/DFGSafeToExecute.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE505A0179B60ED00B35F8C /* FTLFail.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLFail.cpp; path = ftl/FTLFail.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE505A1179B60ED00B35F8C /* FTLFail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLFail.h; path = ftl/FTLFail.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FE505A4179CE3EC00B35F8C /* DFGClobberize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGClobberize.cpp; path = dfg/DFGClobberize.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDesiredWatchpoints.cpp; path = dfg/DFGDesiredWatchpoints.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredWatchpoints.h; path = dfg/DFGDesiredWatchpoints.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FEA09FD170513DB00BB722C /* FTLAbbreviations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLAbbreviations.h; path = ftl/FTLAbbreviations.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2997,6 +3009,8 @@
</span><span class="cx">                 86EC9DB31328DF44002B2AD7 /* dfg */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                0FE50594179B0F7200B35F8C /* DFGAbstractHeap.cpp */,
+                                0FE50595179B0F7200B35F8C /* DFGAbstractHeap.h */,
</ins><span class="cx">                                 0FE505861798ABF500B35F8C /* DFGAbstractInterpreter.h */,
</span><span class="cx">                                 0FE505871798ABF500B35F8C /* DFGAbstractInterpreterInlines.h */,
</span><span class="cx">                                 0F55C19317276E4600CEABFD /* DFGAbstractValue.cpp */,
</span><span class="lines">@@ -3032,6 +3046,10 @@
</span><span class="cx">                                 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */,
</span><span class="cx">                                 0F3B3A241544C991003ED0FF /* DFGCFGSimplificationPhase.cpp */,
</span><span class="cx">                                 0F3B3A251544C991003ED0FF /* DFGCFGSimplificationPhase.h */,
</span><ins>+                                0FE505A4179CE3EC00B35F8C /* DFGClobberize.cpp */,
+                                0FE50596179B0F7200B35F8C /* DFGClobberize.h */,
+                                0FE50597179B0F7200B35F8C /* DFGClobberSet.cpp */,
+                                0FE50598179B0F7200B35F8C /* DFGClobberSet.h */,
</ins><span class="cx">                                 0FB4B51A16B62772003F696B /* DFGCommon.cpp */,
</span><span class="cx">                                 0FC0977E1469EBC400CF2442 /* DFGCommon.h */,
</span><span class="cx">                                 0FEA0A2D170D40BF00BB722C /* DFGCommonData.cpp */,
</span><span class="lines">@@ -3389,6 +3407,7 @@
</span><span class="cx">                                 0FE5058F1798AE7100B35F8C /* DFGMergeMode.h in Headers */,
</span><span class="cx">                                 FEF6835F174343CC00A32E25 /* JITStubsARMv7.h in Headers */,
</span><span class="cx">                                 FE24596217601D580074FCE0 /* CallFrameInlines.h in Headers */,
</span><ins>+                                0FE5059A179B0F7200B35F8C /* DFGAbstractHeap.h in Headers */,
</ins><span class="cx">                                 FEF68360174343CC00A32E25 /* JITStubsX86_64.h in Headers */,
</span><span class="cx">                                 FEF6835E174343CC00A32E25 /* JITStubsARM.h in Headers */,
</span><span class="cx">                                 FE940322174442590047CF6E /* JITStubsX86Common.h in Headers */,
</span><span class="lines">@@ -3580,6 +3599,7 @@
</span><span class="cx">                                 0FEA0A1F1708B00700BB722C /* FTLAbstractHeapRepository.h in Headers */,
</span><span class="cx">                                 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */,
</span><span class="cx">                                 BC11667B0E199C05008066DD /* InternalFunction.h in Headers */,
</span><ins>+                                0FE5059D179B0F7200B35F8C /* DFGClobberSet.h in Headers */,
</ins><span class="cx">                                 1429D77C0ED20D7300B89619 /* Interpreter.h in Headers */,
</span><span class="cx">                                 0FEA0A08170513DB00BB722C /* FTLAbbreviations.h in Headers */,
</span><span class="cx">                                 860BD801148EA6F200112B2F /* Intrinsic.h in Headers */,
</span><span class="lines">@@ -3625,6 +3645,7 @@
</span><span class="cx">                                 148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */,
</span><span class="cx">                                 978801411471AD920041B016 /* JSDateMath.h in Headers */,
</span><span class="cx">                                 C2A7F688160432D400F76B98 /* JSDestructibleObject.h in Headers */,
</span><ins>+                                0FE5059B179B0F7200B35F8C /* DFGClobberize.h in Headers */,
</ins><span class="cx">                                 86E3C614167BABD7006D760A /* JSExport.h in Headers */,
</span><span class="cx">                                 0FDB2CDC1742D804007B3C1B /* DFGFinalizer.h in Headers */,
</span><span class="cx">                                 A7B4ACAF1484C9CE00B38A36 /* JSExportMacros.h in Headers */,
</span><span class="lines">@@ -4304,6 +4325,7 @@
</span><span class="cx">                                 0FEA0A0B170513DB00BB722C /* FTLCompile.cpp in Sources */,
</span><span class="cx">                                 147F39C3107EC37600427A48 /* DateConstructor.cpp in Sources */,
</span><span class="cx">                                 147F39C4107EC37600427A48 /* DateConversion.cpp in Sources */,
</span><ins>+                                0FE50599179B0F7200B35F8C /* DFGAbstractHeap.cpp in Sources */,
</ins><span class="cx">                                 147F39C5107EC37600427A48 /* DateInstance.cpp in Sources */,
</span><span class="cx">                                 147F39C6107EC37600427A48 /* DatePrototype.cpp in Sources */,
</span><span class="cx">                                 14280823107EC02C0013E7B2 /* Debugger.cpp in Sources */,
</span><span class="lines">@@ -4455,6 +4477,7 @@
</span><span class="cx">                                 A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */,
</span><span class="cx">                                 862553D116136DA9009F17D0 /* JSProxy.cpp in Sources */,
</span><span class="cx">                                 14874AE515EBDE4A002E3587 /* JSScope.cpp in Sources */,
</span><ins>+                                0FE505A5179CE3EC00B35F8C /* DFGClobberize.cpp in Sources */,
</ins><span class="cx">                                 A7C0C4AD1681067E0017011D /* JSScriptRef.cpp in Sources */,
</span><span class="cx">                                 0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */,
</span><span class="cx">                                 1428083A107EC0750013E7B2 /* JSStack.cpp in Sources */,
</span><span class="lines">@@ -4463,6 +4486,7 @@
</span><span class="cx">                                 0F4E1A0E173AEDDC007EE2D3 /* IntendedStructureChain.cpp in Sources */,
</span><span class="cx">                                 1482B74E0A43032800517CFC /* JSStringRef.cpp in Sources */,
</span><span class="cx">                                 146AAB380B66A94400E55F16 /* JSStringRefCF.cpp in Sources */,
</span><ins>+                                0FE5059C179B0F7200B35F8C /* DFGClobberSet.cpp in Sources */,
</ins><span class="cx">                                 0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */,
</span><span class="cx">                                 86E3C61A167BABEE006D760A /* JSValue.mm in Sources */,
</span><span class="cx">                                 14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */,
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGAbstractHeapcpp"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGAbstractHeap.cpp (0 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGAbstractHeap.cpp                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGAbstractHeap.cpp        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -0,0 +1,71 @@
</span><ins>+/*
+ * Copyright (C) 2013 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;DFGAbstractHeap.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+void AbstractHeap::Payload::dump(PrintStream&amp; out) const
+{
+    if (isTop())
+        out.print(&quot;TOP&quot;);
+    else
+        out.print(value());
+}
+
+void AbstractHeap::dump(PrintStream&amp; out) const
+{
+    out.print(kind());
+    if (kind() == InvalidAbstractHeap || kind() == World || payload().isTop())
+        return;
+    out.print(&quot;(&quot;, payload(), &quot;)&quot;);
+}
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+using namespace JSC::DFG;
+
+void printInternal(PrintStream&amp; out, AbstractHeapKind kind)
+{
+    switch (kind) {
+#define ABSTRACT_HEAP_DUMP(name)            \
+    case name:                              \
+        out.print(#name);                   \
+        return;
+    FOR_EACH_ABSTRACT_HEAP_KIND(ABSTRACT_HEAP_DUMP)
+#undef ABSTRACT_HEAP_DUMP
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGAbstractHeaph"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGAbstractHeap.h (0 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGAbstractHeap.h                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGAbstractHeap.h        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -0,0 +1,307 @@
</span><ins>+/*
+ * Copyright (C) 2013 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 DFGAbstractHeap_h
+#define DFGAbstractHeap_h
+
+#include &lt;wtf/Platform.h&gt;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;VirtualRegister.h&quot;
+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace JSC { namespace DFG {
+
+// Implements a three-level type hierarchy:
+// - World is the supertype of all of the things.
+// - Kind with TOP payload is the direct subtype of World.
+// - Kind with non-TOP payload is the direct subtype of its corresponding TOP Kind.
+
+#define FOR_EACH_ABSTRACT_HEAP_KIND(macro) \
+    macro(InvalidAbstractHeap) \
+    macro(World) \
+    macro(Arguments_numArguments) \
+    macro(Arguments_overrideLength) \
+    macro(Arguments_registers) \
+    macro(Arguments_slowArguments) \
+    macro(Butterfly_publicLength) \
+    macro(Butterfly_vectorLength) \
+    macro(JSCell_structure) \
+    macro(JSFunction_executable) \
+    macro(JSFunction_scopeChain) \
+    macro(JSObject_butterfly) \
+    macro(JSVariableObject_registers) \
+    macro(NamedProperties) \
+    macro(IndexedInt32Properties) \
+    macro(IndexedDoubleProperties) \
+    macro(IndexedContiguousProperties) \
+    macro(ArrayStorageProperties) \
+    macro(Variables) \
+    macro(TypedArrayStoragePointer) \
+    macro(TypedArrayProperties) \
+    macro(TypedArrayLength) \
+    macro(GCState) \
+    macro(RegExpState) \
+    macro(InternalState) \
+    macro(Absolute) \
+    /* Use this for reads only, just to indicate that if the world got clobbered, then this operation will not work. */\
+    macro(MiscFields) \
+    /* Use this for writes only, just to indicate that hoisting the node is invalid. This works because we don't hoist anything that has any side effects at all. */\
+    macro(SideState)
+
+enum AbstractHeapKind {
+#define ABSTRACT_HEAP_DECLARATION(name) name,
+    FOR_EACH_ABSTRACT_HEAP_KIND(ABSTRACT_HEAP_DECLARATION)
+#undef ABSTRACT_HEAP_DECLARATION
+};
+
+class AbstractHeap {
+public:
+    class Payload {
+    public:
+        Payload()
+            : m_isTop(false)
+            , m_value(0)
+        {
+        }
+        
+        Payload(bool isTop, int64_t value)
+            : m_isTop(isTop)
+            , m_value(value)
+        {
+            ASSERT(!(isTop &amp;&amp; value));
+        }
+        
+        Payload(int64_t value)
+            : m_isTop(false)
+            , m_value(value)
+        {
+        }
+        
+        Payload(const void* pointer)
+            : m_isTop(false)
+            , m_value(bitwise_cast&lt;intptr_t&gt;(pointer))
+        {
+        }
+        
+        Payload(VirtualRegister operand)
+            : m_isTop(false)
+            , m_value(static_cast&lt;int&gt;(operand))
+        {
+        }
+        
+        static Payload top() { return Payload(true, 0); }
+        
+        bool isTop() const { return m_isTop; }
+        int64_t value() const
+        {
+            ASSERT(!isTop());
+            return valueImpl();
+        }
+        int64_t valueImpl() const
+        {
+            return m_value;
+        }
+        
+        bool operator==(const Payload&amp; other) const
+        {
+            return m_isTop == other.m_isTop
+                &amp;&amp; m_value == other.m_value;
+        }
+        
+        bool operator!=(const Payload&amp; other) const
+        {
+            return !(*this == other);
+        }
+        
+        bool operator&lt;(const Payload&amp; other) const
+        {
+            if (isTop())
+                return !other.isTop();
+            if (other.isTop())
+                return false;
+            return value() &lt; other.value();
+        }
+        
+        bool isDisjoint(const Payload&amp; other) const
+        {
+            if (isTop())
+                return false;
+            if (other.isTop())
+                return false;
+            return m_value != other.m_value;
+        }
+        
+        bool overlaps(const Payload&amp; other) const
+        {
+            return !isDisjoint(other);
+        }
+        
+        void dump(PrintStream&amp;) const;
+        
+    private:
+        bool m_isTop;
+        int64_t m_value;
+    };
+    
+    AbstractHeap()
+    {
+        m_value = encode(InvalidAbstractHeap, Payload());
+    }
+    
+    AbstractHeap(AbstractHeapKind kind)
+    {
+        ASSERT(kind != InvalidAbstractHeap);
+        m_value = encode(kind, Payload::top());
+    }
+    
+    AbstractHeap(AbstractHeapKind kind, Payload payload)
+    {
+        ASSERT(kind != InvalidAbstractHeap &amp;&amp; kind != World);
+        m_value = encode(kind, payload);
+    }
+    
+    AbstractHeap(WTF::HashTableDeletedValueType)
+    {
+        m_value = encode(InvalidAbstractHeap, Payload::top());
+    }
+    
+    bool operator!() const { return kind() == InvalidAbstractHeap &amp;&amp; !payloadImpl().isTop(); }
+    
+    AbstractHeapKind kind() const { return static_cast&lt;AbstractHeapKind&gt;(m_value &amp; ((1 &lt;&lt; topShift) - 1)); }
+    Payload payload() const
+    {
+        ASSERT(kind() != World &amp;&amp; kind() != InvalidAbstractHeap);
+        return payloadImpl();
+    }
+    
+    bool isDisjoint(const AbstractHeap&amp; other)
+    {
+        ASSERT(kind() != InvalidAbstractHeap);
+        ASSERT(other.kind() != InvalidAbstractHeap);
+        if (kind() == World)
+            return false;
+        if (other.kind() == World)
+            return false;
+        if (kind() != other.kind())
+            return true;
+        return payload().isDisjoint(other.payload());
+    }
+    
+    bool overlaps(const AbstractHeap&amp; other)
+    {
+        return !isDisjoint(other);
+    }
+    
+    AbstractHeap supertype() const
+    {
+        ASSERT(kind() != InvalidAbstractHeap);
+        if (kind() == World)
+            return AbstractHeap();
+        if (payload().isTop())
+            return World;
+        return AbstractHeap(kind());
+    }
+    
+    unsigned hash() const
+    {
+        return WTF::IntHash&lt;int64_t&gt;::hash(m_value);
+    }
+    
+    bool operator==(const AbstractHeap&amp; other) const
+    {
+        return m_value == other.m_value;
+    }
+    
+    bool operator!=(const AbstractHeap&amp; other) const
+    {
+        return !(*this == other);
+    }
+    
+    bool operator&lt;(const AbstractHeap&amp; other) const
+    {
+        if (kind() != other.kind())
+            return kind() &lt; other.kind();
+        return payload() &lt; other.payload();
+    }
+    
+    bool isHashTableDeletedValue() const
+    {
+        return kind() == InvalidAbstractHeap &amp;&amp; payloadImpl().isTop();
+    }
+    
+    void dump(PrintStream&amp; out) const;
+    
+private:
+    static const unsigned valueShift = 15;
+    static const unsigned topShift = 14;
+    
+    Payload payloadImpl() const
+    {
+        return Payload((m_value &gt;&gt; topShift) &amp; 1, m_value &gt;&gt; valueShift);
+    }
+    
+    static int64_t encode(AbstractHeapKind kind, Payload payload)
+    {
+        int64_t kindAsInt = static_cast&lt;int64_t&gt;(kind);
+        ASSERT(kindAsInt &lt; (1 &lt;&lt; topShift));
+        return kindAsInt | (payload.isTop() &lt;&lt; topShift) | (payload.valueImpl() &lt;&lt; valueShift);
+    }
+    
+    // The layout of the value is:
+    // Low 14 bits: the Kind
+    // 15th bit: whether or not the payload is TOP.
+    // The upper bits: the payload.value().
+    int64_t m_value;
+};
+
+struct AbstractHeapHash {
+    static unsigned hash(const AbstractHeap&amp; key) { return key.hash(); }
+    static bool equal(const AbstractHeap&amp; a, const AbstractHeap&amp; b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+void printInternal(PrintStream&amp;, JSC::DFG::AbstractHeapKind);
+
+template&lt;typename T&gt; struct DefaultHash;
+template&lt;&gt; struct DefaultHash&lt;JSC::DFG::AbstractHeap&gt; {
+    typedef JSC::DFG::AbstractHeapHash Hash;
+};
+
+template&lt;typename T&gt; struct HashTraits;
+template&lt;&gt; struct HashTraits&lt;JSC::DFG::AbstractHeap&gt; : SimpleClassHashTraits&lt;JSC::DFG::AbstractHeap&gt; { };
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGAbstractHeap_h
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGClobberSetcpp"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberSet.cpp (0 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberSet.cpp                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberSet.cpp        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -0,0 +1,159 @@
</span><ins>+/*
+ * Copyright (C) 2013 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;DFGClobberSet.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGClobberize.h&quot;
+#include &quot;Operations.h&quot;
+#include &lt;wtf/ListDump.h&gt;
+
+namespace JSC { namespace DFG {
+
+ClobberSet::ClobberSet() { }
+ClobberSet::~ClobberSet() { }
+
+void ClobberSet::add(AbstractHeap heap)
+{
+    HashMap&lt;AbstractHeap, bool&gt;::AddResult result = m_clobbers.add(heap, true);
+    if (result.isNewEntry) {
+        if (result.iterator-&gt;value)
+            return;
+        result.iterator-&gt;value = true;
+    }
+    while (heap.kind() != World) {
+        heap = heap.supertype();
+        if (!m_clobbers.add(heap, false).isNewEntry)
+            return;
+    }
+}
+
+void ClobberSet::addAll(const ClobberSet&amp; other)
+{
+    // If the other set has a direct heap, we make sure we have it and we set its
+    // value to be true.
+    //
+    // If the other heap has a super heap, we make sure it's present but don't
+    // modify its value - so we had it directly already then this doesn't change.
+    
+    HashMap&lt;AbstractHeap, bool&gt;::const_iterator iter = other.m_clobbers.begin();
+    HashMap&lt;AbstractHeap, bool&gt;::const_iterator end = other.m_clobbers.end();
+    for (; iter != end; ++iter)
+        m_clobbers.add(iter-&gt;key, iter-&gt;value).iterator-&gt;value |= iter-&gt;value;
+}
+
+bool ClobberSet::contains(AbstractHeap heap) const
+{
+    HashMap&lt;AbstractHeap, bool&gt;::const_iterator iter = m_clobbers.find(heap);
+    if (iter == m_clobbers.end())
+        return false;
+    return iter-&gt;value;
+}
+
+bool ClobberSet::overlaps(AbstractHeap heap) const
+{
+    if (m_clobbers.find(heap) != m_clobbers.end())
+        return true;
+    while (heap.kind() != World) {
+        heap = heap.supertype();
+        if (contains(heap))
+            return true;
+    }
+    return false;
+}
+
+void ClobberSet::clear()
+{
+    m_clobbers.clear();
+}
+
+HashSet&lt;AbstractHeap&gt; ClobberSet::direct() const
+{
+    return setOf(true);
+}
+
+HashSet&lt;AbstractHeap&gt; ClobberSet::super() const
+{
+    return setOf(false);
+}
+
+void ClobberSet::dump(PrintStream&amp; out) const
+{
+    out.print(&quot;(Direct:[&quot;, sortedListDump(direct()), &quot;], Super:[&quot;, sortedListDump(super()), &quot;])&quot;);
+}
+
+HashSet&lt;AbstractHeap&gt; ClobberSet::setOf(bool direct) const
+{
+    HashSet&lt;AbstractHeap&gt; result;
+    for (HashMap&lt;AbstractHeap, bool&gt;::const_iterator iter = m_clobbers.begin(); iter != m_clobbers.end(); ++iter) {
+        if (iter-&gt;value == direct)
+            result.add(iter-&gt;key);
+    }
+    return result;
+}
+
+void addReads(Graph&amp; graph, Node* node, ClobberSet&amp; readSet)
+{
+    ClobberSetAdd addRead(readSet);
+    NoOpClobberize addWrite;
+    clobberize(graph, node, addRead, addWrite);
+}
+
+void addWrites(Graph&amp; graph, Node* node, ClobberSet&amp; writeSet)
+{
+    NoOpClobberize addRead;
+    ClobberSetAdd addWrite(writeSet);
+    clobberize(graph, node, addRead, addWrite);
+}
+
+void addReadsAndWrites(Graph&amp; graph, Node* node, ClobberSet&amp; readSet, ClobberSet&amp; writeSet)
+{
+    ClobberSetAdd addRead(readSet);
+    ClobberSetAdd addWrite(writeSet);
+    clobberize(graph, node, addRead, addWrite);
+}
+
+bool readsOverlap(Graph&amp; graph, Node* node, ClobberSet&amp; readSet)
+{
+    ClobberSetOverlaps addRead(readSet);
+    NoOpClobberize addWrite;
+    clobberize(graph, node, addRead, addWrite);
+    return addRead.result();
+}
+
+bool writesOverlap(Graph&amp; graph, Node* node, ClobberSet&amp; writeSet)
+{
+    NoOpClobberize addRead;
+    ClobberSetOverlaps addWrite(writeSet);
+    clobberize(graph, node, addRead, addWrite);
+    return addWrite.result();
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGClobberSeth"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberSet.h (0 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberSet.h                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberSet.h        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -0,0 +1,125 @@
</span><ins>+/*
+ * Copyright (C) 2013 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 DFGClobberSet_h
+#define DFGClobberSet_h
+
+#include &lt;wtf/Platform.h&gt;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGAbstractHeap.h&quot;
+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/HashSet.h&gt;
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace JSC { namespace DFG {
+
+class Graph;
+struct Node;
+
+// FIXME: If we ever want to compare if two nodes clobber each other, we should
+// have a SmallClobberSet, which just keeps an array of the AbstractHeaps and
+// satisfies overlaps() requests by looping over all of them. This will probably
+// be faster than a full HashMap in a lot of cases. Or, maybe, we could have
+// ClobberSet be smart and use a vector so long as it was small.
+
+class ClobberSet {
+public:
+    ClobberSet();
+    ~ClobberSet();
+    
+    bool isEmpty() const { return m_clobbers.isEmpty(); }
+    
+    void add(AbstractHeap);
+    void addAll(const ClobberSet&amp;);
+    bool contains(AbstractHeap) const;
+    bool overlaps(AbstractHeap) const;
+    void clear();
+    
+    // Calls useful for debugging the ClobberSet.
+    
+    HashSet&lt;AbstractHeap&gt; direct() const;
+    HashSet&lt;AbstractHeap&gt; super() const;
+    
+    void dump(PrintStream&amp;) const;
+    
+private:
+    HashSet&lt;AbstractHeap&gt; setOf(bool direct) const;
+    
+    // Maps heap to:
+    // true --&gt; it's a direct clobber
+    // false --&gt; it's just a supertype of a direct clobber
+    HashMap&lt;AbstractHeap, bool&gt; m_clobbers;
+};
+
+class ClobberSetAdd {
+public:
+    ClobberSetAdd(ClobberSet&amp; set)
+        : m_set(set)
+    {
+    }
+    
+    void operator()(AbstractHeap heap)
+    {
+        m_set.add(heap);
+    }
+private:
+    ClobberSet&amp; m_set;
+};
+
+class ClobberSetOverlaps {
+public:
+    ClobberSetOverlaps(const ClobberSet&amp; set)
+        : m_set(set)
+        , m_result(false)
+    {
+    }
+    
+    void operator()(AbstractHeap heap)
+    {
+        m_result |= m_set.overlaps(heap);
+    }
+    
+    bool result() const { return m_result; }
+    
+private:
+    const ClobberSet&amp; m_set;
+    bool m_result;
+};
+
+void addReads(Graph&amp;, Node*, ClobberSet&amp;);
+void addWrites(Graph&amp;, Node*, ClobberSet&amp;);
+void addReadsAndWrites(Graph&amp;, Node*, ClobberSet&amp; reads, ClobberSet&amp; writes);
+
+bool readsOverlap(Graph&amp;, Node*, ClobberSet&amp;);
+bool writesOverlap(Graph&amp;, Node*, ClobberSet&amp;);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGClobberSet_h
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGClobberizecpp"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberize.cpp (0 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberize.cpp                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberize.cpp        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+/*
+ * Copyright (C) 2013 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;DFGClobberize.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+bool didWrites(Graph&amp; graph, Node* node)
+{
+    NoOpClobberize addRead;
+    CheckClobberize addWrite;
+    clobberize(graph, node, addRead, addWrite);
+    return addWrite.result();
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberize.h (0 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberize.h                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGClobberize.h        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -0,0 +1,632 @@
</span><ins>+/*
+ * Copyright (C) 2013 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 DFGClobberize_h
+#define DFGClobberize_h
+
+#include &lt;wtf/Platform.h&gt;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGAbstractHeap.h&quot;
+#include &quot;DFGEdgeUsesStructure.h&quot;
+#include &quot;DFGGraph.h&quot;
+
+namespace JSC { namespace DFG {
+
+template&lt;typename ReadFunctor, typename WriteFunctor&gt;
+void clobberize(Graph&amp; graph, Node* node, ReadFunctor&amp; read, WriteFunctor&amp; write)
+{
+    // Some notes:
+    //
+    // - We cannot hoist, or sink, anything that has effects. This means that the
+    //   easiest way of indicating that something cannot be hoisted is to claim
+    //   that it side-effects some miscellaneous thing.
+    //
+    // - We cannot hoist forward-exiting nodes without some additional effort. I
+    //   believe that what it comes down to is that forward-exiting generally have
+    //   their NodeExitsForward cleared upon hoist, except for forward-exiting
+    //   nodes that take bogus state as their input. Those are substantially
+    //   harder. We disable it for now. In the future we could enable it by having
+    //   versions of those nodes that backward-exit instead, but I'm not convinced
+    //   of the soundness.
+    //
+    // - Some nodes lie, and claim that they do not read the JSCell_structure.
+    //   These are nodes that use the structure in a way that does not depend on
+    //   things that change under structure transitions.
+    //
+    // - It's implicitly understood that OSR exits read the world. This is why we
+    //   generally don't move or eliminate stores. Every node can exit, so the
+    //   read set does not reflect things that would be read if we exited.
+    //   Instead, the read set reflects what the node will have to read if it
+    //   *doesn't* exit.
+    //
+    // - Broadly, we don't say that we're reading something if that something is
+    //   immutable.
+    //
+    // - We try to make this work even prior to type inference, just so that we
+    //   can use it for IR dumps. No promises on whether the answers are sound
+    //   prior to type inference - though they probably could be if we did some
+    //   small hacking.
+    
+    if (edgesUseStructure(graph, node))
+        read(JSCell_structure);
+    
+    switch (node-&gt;op()) {
+    case JSConstant:
+    case WeakJSConstant:
+    case Identity:
+    case Phantom:
+    case BitAnd:
+    case BitOr:
+    case BitXor:
+    case BitLShift:
+    case BitRShift:
+    case BitURShift:
+    case ValueToInt32:
+    case ArithAdd:
+    case ArithSub:
+    case ArithNegate:
+    case ArithMul:
+    case ArithDiv:
+    case ArithMod:
+    case ArithAbs:
+    case ArithMin:
+    case ArithMax:
+    case ArithSqrt:
+    case GetScope:
+    case SkipScope:
+    case CheckFunction:
+    case StringCharCodeAt:
+    case CompareEqConstant:
+    case CompareStrictEqConstant:
+    case CompareStrictEq:
+    case IsUndefined:
+    case IsBoolean:
+    case IsNumber:
+    case IsString:
+    case LogicalNot:
+    case Int32ToDouble:
+        return;
+        
+    case MovHintAndCheck:
+    case MovHint:
+    case ZombieHint:
+    case Upsilon:
+    case Phi:
+    case Flush:
+    case PhantomLocal:
+    case SetArgument:
+    case InlineStart:
+    case Breakpoint:
+    case CreateActivation:
+    case CreateArguments:
+    case PhantomArguments:
+    case Jump:
+    case Branch:
+    case Switch:
+    case Throw:
+    case ForceOSRExit:
+    case Return:
+        write(SideState);
+        return;
+
+    // These are forward-exiting nodes that assume that the subsequent instruction
+    // is a MovHint, and they try to roll forward over this MovHint in their
+    // execution. This makes hoisting them impossible without additional magic. We
+    // may add such magic eventually, but just not yet.
+    case UInt32ToNumber:
+    case DoubleAsInt32:
+        write(SideState);
+        return;
+        
+    case CreateThis:
+    case ToThis:
+    case VarInjectionWatchpoint:
+    case AllocationProfileWatchpoint:
+    case IsObject:
+    case IsFunction:
+    case TypeOf:
+        read(MiscFields);
+        return;
+        
+    case GetById:
+    case GetByIdFlush:
+    case PutById:
+    case PutByIdDirect:
+    case ArrayPush:
+    case ArrayPop:
+    case Call:
+    case Construct:
+    case ToPrimitive:
+    case In:
+    case GetMyArgumentsLengthSafe:
+    case GetMyArgumentByValSafe:
+        read(World);
+        write(World);
+        return;
+        
+    case ValueAdd:
+        switch (node-&gt;binaryUseKind()) {
+        case Int32Use:
+        case NumberUse:
+            return;
+        case UntypedUse:
+            read(World);
+            write(World);
+            return;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return;
+        }
+        
+    case GetCallee:
+        read(AbstractHeap(Variables, JSStack::Callee));
+        return;
+        
+    case SetCallee:
+        write(AbstractHeap(Variables, JSStack::Callee));
+        return;
+        
+    case GetLocal:
+    case GetArgument:
+        read(AbstractHeap(Variables, node-&gt;local()));
+        return;
+        
+    case SetLocal:
+        write(AbstractHeap(Variables, node-&gt;local()));
+        return;
+        
+    case GetLocalUnlinked:
+        read(AbstractHeap(Variables, node-&gt;unlinkedLocal()));
+        return;
+        
+    case GetByVal: {
+        ArrayMode mode = node-&gt;arrayMode();
+        switch (mode.type()) {
+        case Array::SelectUsingPredictions:
+        case Array::Unprofiled:
+        case Array::Undecided:
+            // Assume the worst since we don't have profiling yet.
+            read(World);
+            write(World);
+            return;
+            
+        case Array::ForceExit:
+            write(SideState);
+            return;
+            
+        case Array::Generic:
+            read(World);
+            write(World);
+            return;
+            
+        case Array::String:
+            if (mode.isOutOfBounds()) {
+                read(World);
+                write(World);
+                return;
+            }
+            // This appears to read nothing because it's only reading immutable data.
+            return;
+            
+        case Array::Arguments:
+            read(Arguments_registers);
+            read(Variables);
+            return;
+            
+        case Array::Int32:
+            if (mode.isInBounds()) {
+                read(Butterfly_publicLength);
+                read(Butterfly_vectorLength);
+                read(IndexedInt32Properties);
+                return;
+            }
+            read(World);
+            write(World);
+            return;
+            
+        case Array::Double:
+            if (mode.isInBounds()) {
+                read(Butterfly_publicLength);
+                read(Butterfly_vectorLength);
+                read(IndexedDoubleProperties);
+                return;
+            }
+            read(World);
+            write(World);
+            return;
+            
+        case Array::Contiguous:
+            if (mode.isInBounds()) {
+                read(Butterfly_publicLength);
+                read(Butterfly_vectorLength);
+                read(IndexedContiguousProperties);
+                return;
+            }
+            read(World);
+            write(World);
+            return;
+            
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage:
+            // Give up on life for now.
+            read(World);
+            write(World);
+            return;
+            
+        case Array::Int8Array:
+        case Array::Int16Array:
+        case Array::Int32Array:
+        case Array::Uint8Array:
+        case Array::Uint8ClampedArray:
+        case Array::Uint16Array:
+        case Array::Uint32Array:
+        case Array::Float32Array:
+        case Array::Float64Array:
+            read(TypedArrayProperties);
+            return;
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return;
+    }
+        
+    case PutByVal:
+    case PutByValAlias: {
+        ArrayMode mode = node-&gt;arrayMode();
+        switch (mode.modeForPut().type()) {
+        case Array::SelectUsingPredictions:
+        case Array::Unprofiled:
+        case Array::Undecided:
+        case Array::String:
+            // Assume the worst since we don't have profiling yet.
+            read(World);
+            write(World);
+            return;
+            
+        case Array::ForceExit:
+            write(SideState);
+            return;
+            
+        case Array::Generic:
+            read(World);
+            write(World);
+            return;
+            
+        case Array::Arguments:
+            read(Arguments_registers);
+            read(Arguments_numArguments);
+            read(Arguments_slowArguments);
+            write(Variables);
+            return;
+            
+        case Array::Int32:
+            if (node-&gt;arrayMode().isOutOfBounds()) {
+                read(World);
+                write(World);
+                return;
+            }
+            read(Butterfly_publicLength);
+            read(Butterfly_vectorLength);
+            read(IndexedInt32Properties);
+            write(IndexedInt32Properties);
+            return;
+            
+        case Array::Double:
+            if (node-&gt;arrayMode().isOutOfBounds()) {
+                read(World);
+                write(World);
+                return;
+            }
+            read(Butterfly_publicLength);
+            read(Butterfly_vectorLength);
+            read(IndexedDoubleProperties);
+            write(IndexedDoubleProperties);
+            return;
+            
+        case Array::Contiguous:
+            if (node-&gt;arrayMode().isOutOfBounds()) {
+                read(World);
+                write(World);
+                return;
+            }
+            read(Butterfly_publicLength);
+            read(Butterfly_vectorLength);
+            read(IndexedContiguousProperties);
+            write(IndexedContiguousProperties);
+            return;
+            
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage:
+            // Give up on life for now.
+            read(World);
+            write(World);
+            return;
+
+        case Array::Int8Array:
+        case Array::Int16Array:
+        case Array::Int32Array:
+        case Array::Uint8Array:
+        case Array::Uint8ClampedArray:
+        case Array::Uint16Array:
+        case Array::Uint32Array:
+        case Array::Float32Array:
+        case Array::Float64Array:
+            write(TypedArrayProperties);
+            return;
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return;
+    }
+        
+    case CheckStructure:
+    case StructureTransitionWatchpoint:
+    case CheckArray:
+    case CheckHasInstance:
+    case InstanceOf:
+        read(JSCell_structure);
+        return;
+        
+    case CheckExecutable:
+        read(JSFunction_executable);
+        return;
+        
+    case PutStructure:
+    case PhantomPutStructure:
+        write(JSCell_structure);
+        return;
+        
+    case AllocatePropertyStorage:
+        write(JSObject_butterfly);
+        return;
+        
+    case ReallocatePropertyStorage:
+        read(JSObject_butterfly);
+        write(JSObject_butterfly);
+        return;
+        
+    case GetButterfly:
+        read(JSObject_butterfly);
+        return;
+        
+    case Arrayify:
+    case ArrayifyToStructure:
+        read(JSCell_structure);
+        read(JSObject_butterfly);
+        write(JSCell_structure);
+        write(JSObject_butterfly);
+        return;
+        
+    case GetIndexedPropertyStorage:
+        if (node-&gt;arrayMode().type() == Array::String)
+            return;
+        read(TypedArrayStoragePointer);
+        return;
+        
+    case GetByOffset:
+        read(AbstractHeap(NamedProperties, graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber));
+        return;
+        
+    case PutByOffset:
+        write(AbstractHeap(NamedProperties, graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber));
+        return;
+        
+    case GetArrayLength: {
+        ArrayMode mode = node-&gt;arrayMode();
+        switch (mode.type()) {
+        case Array::Int32:
+        case Array::Double:
+        case Array::Contiguous:
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage:
+            read(Butterfly_publicLength);
+            return;
+            
+        case Array::String:
+            return;
+            
+        case Array::Arguments:
+            read(Arguments_overrideLength);
+            read(Arguments_numArguments);
+            return;
+            
+        default:
+            read(TypedArrayLength);
+            return;
+        }
+    }
+        
+    case GetMyScope:
+        read(AbstractHeap(Variables, JSStack::ScopeChain));
+        return;
+        
+    case SetMyScope:
+        write(AbstractHeap(Variables, JSStack::ScopeChain));
+        return;
+        
+    case SkipTopScope:
+        read(AbstractHeap(Variables, graph.m_codeBlock-&gt;activationRegister()));
+        return;
+        
+    case GetClosureRegisters:
+        read(JSVariableObject_registers);
+        return;
+        
+    case GetClosureVar:
+        read(AbstractHeap(Variables, node-&gt;varNumber()));
+        return;
+        
+    case PutClosureVar:
+        write(AbstractHeap(Variables, node-&gt;varNumber()));
+        return;
+        
+    case GetGlobalVar:
+    case GlobalVarWatchpoint:
+        read(AbstractHeap(Absolute, node-&gt;registerPointer()));
+        return;
+        
+    case PutGlobalVar:
+        write(AbstractHeap(Absolute, node-&gt;registerPointer()));
+        return;
+
+    case NewObject:
+    case NewArray:
+    case NewArrayWithSize:
+    case NewArrayBuffer:
+    case NewRegexp:
+    case NewStringObject:
+    case MakeRope:
+    case NewFunctionNoCheck:
+    case NewFunction:
+    case NewFunctionExpression:
+        read(GCState);
+        write(GCState);
+        return;
+        
+    case RegExpExec:
+    case RegExpTest:
+        read(RegExpState);
+        write(RegExpState);
+        return;
+
+    case StringCharAt:
+        if (node-&gt;arrayMode().isOutOfBounds()) {
+            read(World);
+            write(World);
+            return;
+        }
+        return;
+        
+    case CompareLess:
+    case CompareLessEq:
+    case CompareGreater:
+    case CompareGreaterEq:
+        if (graph.isPredictedNumerical(node))
+            return;
+        read(World);
+        write(World);
+        return;
+        
+    case CompareEq:
+        if (graph.isPredictedNumerical(node)
+            || node-&gt;isBinaryUseKind(StringUse)
+            || node-&gt;isBinaryUseKind(StringIdentUse))
+            return;
+        
+        if ((node-&gt;child1().useKind() == ObjectUse || node-&gt;child1().useKind() == ObjectOrOtherUse)
+            &amp;&amp; (node-&gt;child2().useKind() == ObjectUse || node-&gt;child2().useKind() == ObjectOrOtherUse))
+            return;
+        
+        read(World);
+        write(World);
+        return;
+        
+    case ToString:
+        switch (node-&gt;child1().useKind()) {
+        case StringObjectUse:
+        case StringOrStringObjectUse:
+            return;
+            
+        case CellUse:
+        case UntypedUse:
+            read(World);
+            write(World);
+            return;
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return;
+        }
+
+    case TearOffActivation:
+        write(JSVariableObject_registers);
+        return;
+        
+    case TearOffArguments:
+        write(Arguments_registers);
+        return;
+        
+    case GetMyArgumentsLength:
+        read(AbstractHeap(Variables, graph.argumentsRegisterFor(node-&gt;codeOrigin)));
+        read(AbstractHeap(Variables, JSStack::ArgumentCount));
+        return;
+        
+    case GetMyArgumentByVal:
+        read(Variables);
+        return;
+        
+    case CheckArgumentsNotCreated:
+        read(AbstractHeap(Variables, graph.argumentsRegisterFor(node-&gt;codeOrigin)));
+        return;
+
+    case ThrowReferenceError:
+        write(SideState);
+        read(GCState);
+        write(GCState);
+        return;
+        
+    case CountExecution:
+    case CheckWatchdogTimer:
+        read(InternalState);
+        write(InternalState);
+        return;
+        
+    case LastNodeType:
+        RELEASE_ASSERT_NOT_REACHED();
+        return;
+    }
+    
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+class NoOpClobberize {
+public:
+    NoOpClobberize() { }
+    void operator()(AbstractHeap) { }
+};
+
+class CheckClobberize {
+public:
+    CheckClobberize()
+        : m_result(false)
+    {
+    }
+    
+    void operator()(AbstractHeap) { m_result = true; }
+    
+    bool result() const { return m_result; }
+    
+private:
+    bool m_result;
+};
+
+bool didWrites(Graph&amp;, Node*);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGClobberize_h
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.cpp (152958 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.cpp        2013-07-22 03:57:32 UTC (rev 152958)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.cpp        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;CodeBlockWithJITType.h&quot;
</span><ins>+#include &quot;DFGClobberSet.h&quot;
</ins><span class="cx"> #include &quot;DFGVariableAccessDataDump.h&quot;
</span><span class="cx"> #include &quot;FunctionExecutableDump.h&quot;
</span><span class="cx"> #include &quot;Operations.h&quot;
</span><span class="lines">@@ -258,6 +259,13 @@
</span><span class="cx">             out.print(comma, data-&gt;cases[i].value, &quot;:&quot;, *data-&gt;cases[i].target);
</span><span class="cx">         out.print(comma, &quot;default:&quot;, *data-&gt;fallThrough);
</span><span class="cx">     }
</span><ins>+    ClobberSet reads;
+    ClobberSet writes;
+    addReadsAndWrites(*this, node, reads, writes);
+    if (!reads.isEmpty())
+        out.print(comma, &quot;R:&quot;, sortedListDump(reads.direct(), &quot;,&quot;));
+    if (!writes.isEmpty())
+        out.print(comma, &quot;W:&quot;, sortedListDump(writes.direct(), &quot;,&quot;));
</ins><span class="cx">     out.print(comma, &quot;bc#&quot;, node-&gt;codeOrigin.bytecodeIndex);
</span><span class="cx">     
</span><span class="cx">     out.print(&quot;)&quot;);
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/WTF/ChangeLog (152958 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/WTF/ChangeLog        2013-07-22 03:57:32 UTC (rev 152958)
+++ branches/dfgFourthTier/Source/WTF/ChangeLog        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2013-07-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        fourthTier: DFG Nodes should be able to abstractly tell you what they read and what they write
+        https://bugs.webkit.org/show_bug.cgi?id=118910
+
+        Reviewed by Sam Weinig.
+        
+        Fix compile goof in sortedListDump().
+
+        * wtf/ListDump.h:
+        (WTF::sortedListDump):
+
</ins><span class="cx"> 2013-07-16  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         fourthTier: NaturalLoops should be able to quickly answer questions like &quot;what loops own this basic block&quot;
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceWTFwtfListDumph"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/WTF/wtf/ListDump.h (152958 => 152959)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/WTF/wtf/ListDump.h        2013-07-22 03:57:32 UTC (rev 152958)
+++ branches/dfgFourthTier/Source/WTF/wtf/ListDump.h        2013-07-22 04:04:41 UTC (rev 152959)
</span><span class="lines">@@ -102,7 +102,7 @@
</span><span class="cx"> template&lt;typename T&gt;
</span><span class="cx"> CString sortedListDump(const T&amp; list, const char* comma = &quot;, &quot;)
</span><span class="cx"> {
</span><del>-    return sortedListDump(list, lessThan&lt;T::ValueType&gt;, comma);
</del><ins>+    return sortedListDump(list, lessThan&lt;typename T::ValueType&gt;, comma);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename T&gt;
</span></span></pre>
</div>
</div>

</body>
</html>