<!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>[180656] trunk/Source/JavaScriptCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/180656">180656</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-02-25 20:29:26 -0800 (Wed, 25 Feb 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>DFG abstract heaps should respect the difference between heap and stack
https://bugs.webkit.org/show_bug.cgi?id=142022
Reviewed by Geoffrey Garen.
We will soon (https://bugs.webkit.org/show_bug.cgi?id=141174) be in a world where a "world
clobbering" operation cannot write to our stack, but may be able to read from it. This
means that we need to change the DFG abstract heap hierarchy to have a notion of Heap that
subsumes all that World previously subsumed, and a new notion of Stack that is a subtype
of World and a sibling of Heap.
So, henceforth "clobbering the world" means reading World and writing Heap.
This makes a bunch of changes to make this work, including changing the implementation of
disjointness in AbstractHeap to make it support a more general hierarchy. I was expecting
a slow-down, but I measured the heck out of this and found no perf difference.
* dfg/DFGAbstractHeap.cpp:
(JSC::DFG::AbstractHeap::dump):
* dfg/DFGAbstractHeap.h:
(JSC::DFG::AbstractHeap::supertype):
(JSC::DFG::AbstractHeap::isStrictSubtypeOf):
(JSC::DFG::AbstractHeap::isSubtypeOf):
(JSC::DFG::AbstractHeap::overlaps):
(JSC::DFG::AbstractHeap::isDisjoint):
* dfg/DFGClobberize.cpp:
(JSC::DFG::clobbersHeap):
(JSC::DFG::clobbersWorld): Deleted.
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractHeapcpp">trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractHeaph">trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizecpp">trunk/Source/JavaScriptCore/dfg/DFGClobberize.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (180655 => 180656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-02-26 04:18:47 UTC (rev 180655)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-02-26 04:29:26 UTC (rev 180656)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2015-02-25 Filip Pizlo <fpizlo@apple.com>
+
+ DFG abstract heaps should respect the difference between heap and stack
+ https://bugs.webkit.org/show_bug.cgi?id=142022
+
+ Reviewed by Geoffrey Garen.
+
+ We will soon (https://bugs.webkit.org/show_bug.cgi?id=141174) be in a world where a "world
+ clobbering" operation cannot write to our stack, but may be able to read from it. This
+ means that we need to change the DFG abstract heap hierarchy to have a notion of Heap that
+ subsumes all that World previously subsumed, and a new notion of Stack that is a subtype
+ of World and a sibling of Heap.
+
+ So, henceforth "clobbering the world" means reading World and writing Heap.
+
+ This makes a bunch of changes to make this work, including changing the implementation of
+ disjointness in AbstractHeap to make it support a more general hierarchy. I was expecting
+ a slow-down, but I measured the heck out of this and found no perf difference.
+
+ * dfg/DFGAbstractHeap.cpp:
+ (JSC::DFG::AbstractHeap::dump):
+ * dfg/DFGAbstractHeap.h:
+ (JSC::DFG::AbstractHeap::supertype):
+ (JSC::DFG::AbstractHeap::isStrictSubtypeOf):
+ (JSC::DFG::AbstractHeap::isSubtypeOf):
+ (JSC::DFG::AbstractHeap::overlaps):
+ (JSC::DFG::AbstractHeap::isDisjoint):
+ * dfg/DFGClobberize.cpp:
+ (JSC::DFG::clobbersHeap):
+ (JSC::DFG::clobbersWorld): Deleted.
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+
</ins><span class="cx"> 2015-02-25 Ryosuke Niwa <rniwa@webkit.org>
</span><span class="cx">
</span><span class="cx"> REGRESSION(r180595): construct varargs fails in FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.cpp (180655 => 180656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.cpp        2015-02-26 04:18:47 UTC (rev 180655)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.cpp        2015-02-26 04:29:26 UTC (rev 180656)
</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, 2015 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">@@ -43,7 +43,7 @@
</span><span class="cx"> void AbstractHeap::dump(PrintStream& out) const
</span><span class="cx"> {
</span><span class="cx"> out.print(kind());
</span><del>- if (kind() == InvalidAbstractHeap || kind() == World || payload().isTop())
</del><ins>+ if (kind() == InvalidAbstractHeap || kind() == World || kind() == Heap || payload().isTop())
</ins><span class="cx"> return;
</span><span class="cx"> out.print("(", payload(), ")");
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h (180655 => 180656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h        2015-02-26 04:18:47 UTC (rev 180655)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h        2015-02-26 04:29:26 UTC (rev 180656)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -34,14 +34,19 @@
</span><span class="cx">
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx">
</span><del>-// Implements a three-level type hierarchy:
</del><ins>+// Implements a four-level type hierarchy:
</ins><span class="cx"> // - World is the supertype of all of the things.
</span><del>-// - Kind with TOP payload is the direct subtype of World.
-// - Kind with non-TOP payload is the direct subtype of its corresponding TOP Kind.
</del><ins>+// - Stack with a TOP payload is a direct subtype of World
+// - Stack with a non-TOP payload is a direct subtype of Stack with a TOP payload.
+// - Heap is a direct subtype of World.
+// - Any other kind with TOP payload is the direct subtype of Heap.
+// - Any other kind with non-TOP payload is the direct subtype of the same kind with a TOP payload.
</ins><span class="cx">
</span><span class="cx"> #define FOR_EACH_ABSTRACT_HEAP_KIND(macro) \
</span><span class="cx"> macro(InvalidAbstractHeap) \
</span><span class="cx"> macro(World) \
</span><ins>+ macro(Stack) \
+ macro(Heap) \
</ins><span class="cx"> macro(Arguments_registers) \
</span><span class="cx"> macro(Butterfly_publicLength) \
</span><span class="cx"> macro(Butterfly_vectorLength) \
</span><span class="lines">@@ -204,32 +209,48 @@
</span><span class="cx"> return payloadImpl();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- bool isDisjoint(const AbstractHeap& other) const
</del><ins>+ AbstractHeap supertype() const
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(kind() != InvalidAbstractHeap);
</span><del>- 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());
</del><ins>+ switch (kind()) {
+ case World:
+ return AbstractHeap();
+ case Heap:
+ return World;
+ default:
+ if (payload().isTop()) {
+ if (kind() == Stack)
+ return World;
+ return Heap;
+ }
+ return AbstractHeap(kind());
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+ bool isStrictSubtypeOf(const AbstractHeap& other) const
+ {
+ AbstractHeap current = *this;
+ while (current.kind() != World) {
+ current = current.supertype();
+ if (current == other)
+ return true;
+ }
+ return false;
+ }
+
+ bool isSubtypeOf(const AbstractHeap& other) const
+ {
+ return *this == other || isStrictSubtypeOf(other);
+ }
+
</ins><span class="cx"> bool overlaps(const AbstractHeap& other) const
</span><span class="cx"> {
</span><del>- return !isDisjoint(other);
</del><ins>+ return *this == other || isStrictSubtypeOf(other) || other.isStrictSubtypeOf(*this);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- AbstractHeap supertype() const
</del><ins>+ bool isDisjoint(const AbstractHeap& other) const
</ins><span class="cx"> {
</span><del>- ASSERT(kind() != InvalidAbstractHeap);
- if (kind() == World)
- return AbstractHeap();
- if (payload().isTop())
- return World;
- return AbstractHeap(kind());
</del><ins>+ return !overlaps(other);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> unsigned hash() const
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.cpp (180655 => 180656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.cpp        2015-02-26 04:18:47 UTC (rev 180655)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.cpp        2015-02-26 04:29:26 UTC (rev 180656)
</span><span class="lines">@@ -56,14 +56,20 @@
</span><span class="cx"> return addWrite.result();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool clobbersWorld(Graph& graph, Node* node)
</del><ins>+bool clobbersHeap(Graph& graph, Node* node)
</ins><span class="cx"> {
</span><span class="cx"> bool result = false;
</span><span class="cx"> clobberize(
</span><span class="cx"> graph, node, NoOpClobberize(),
</span><span class="cx"> [&] (AbstractHeap heap) {
</span><del>- if (heap == AbstractHeap(World))
</del><ins>+ switch (heap.kind()) {
+ case World:
+ case Heap:
</ins><span class="cx"> result = true;
</span><ins>+ break;
+ default:
+ break;
+ }
</ins><span class="cx"> },
</span><span class="cx"> NoOpClobberize());
</span><span class="cx"> return result;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (180655 => 180656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-02-26 04:18:47 UTC (rev 180655)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-02-26 04:29:26 UTC (rev 180656)
</span><span class="lines">@@ -41,6 +41,12 @@
</span><span class="cx"> {
</span><span class="cx"> // Some notes:
</span><span class="cx"> //
</span><ins>+ // - The canonical way of clobbering the world is to read world and write
+ // heap. This is because World subsumes Heap and Stack, and Stack can be
+ // read by anyone but only written to by explicit stack writing operations.
+ // Of course, claiming to also write World is not wrong; it'll just
+ // pessimise some important optimizations.
+ //
</ins><span class="cx"> // - We cannot hoist, or sink, anything that has effects. This means that the
</span><span class="cx"> // easiest way of indicating that something cannot be hoisted is to claim
</span><span class="cx"> // that it side-effects some miscellaneous thing.
</span><span class="lines">@@ -53,9 +59,9 @@
</span><span class="cx"> // versions of those nodes that backward-exit instead, but I'm not convinced
</span><span class="cx"> // of the soundness.
</span><span class="cx"> //
</span><del>- // - Some nodes lie, and claim that they do not read the JSCell_structureID, JSCell_typeInfoFlags, etc.
- // These are nodes that use the structure in a way that does not depend on
- // things that change under structure transitions.
</del><ins>+ // - Some nodes lie, and claim that they do not read the JSCell_structureID,
+ // JSCell_typeInfoFlags, etc. These are nodes that use the structure in a way
+ // that does not depend on things that change under structure transitions.
</ins><span class="cx"> //
</span><span class="cx"> // - It's implicitly understood that OSR exits read the world. This is why we
</span><span class="cx"> // generally don't move or eliminate stores. Every node can exit, so the
</span><span class="lines">@@ -157,16 +163,16 @@
</span><span class="cx"> case GetEnumerableLength:
</span><span class="cx"> case GetStructurePropertyEnumerator:
</span><span class="cx"> case GetGenericPropertyEnumerator: {
</span><del>- read(World);
</del><ins>+ read(Heap);
</ins><span class="cx"> write(SideState);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case GetDirectPname: {
</span><del>- // This reads and writes world because it can end up calling a generic getByVal
</del><ins>+ // This reads and writes heap because it can end up calling a generic getByVal
</ins><span class="cx"> // if the Structure changed, which could in turn end up calling a getter.
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -187,7 +193,7 @@
</span><span class="cx"> def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><del>- read(World);
</del><ins>+ read(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -198,7 +204,7 @@
</span><span class="cx"> def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><del>- read(World);
</del><ins>+ read(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -209,7 +215,7 @@
</span><span class="cx"> def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><del>- read(World);
</del><ins>+ read(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -219,13 +225,13 @@
</span><span class="cx"> read(IndexedArrayStorageProperties);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><del>- read(World);
</del><ins>+ read(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> default: {
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -376,7 +382,7 @@
</span><span class="cx"> case GetMyArgumentByValSafe:
</span><span class="cx"> case ValueAdd:
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case GetGetter:
</span><span class="lines">@@ -425,7 +431,7 @@
</span><span class="cx"> case Array::Undecided:
</span><span class="cx"> // Assume the worst since we don't have profiling yet.
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case Array::ForceExit:
</span><span class="lines">@@ -434,13 +440,13 @@
</span><span class="cx">
</span><span class="cx"> case Array::Generic:
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case Array::String:
</span><span class="cx"> if (mode.isOutOfBounds()) {
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> // This appears to read nothing because it's only reading immutable data.
</span><span class="lines">@@ -461,7 +467,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case Array::Double:
</span><span class="lines">@@ -472,7 +478,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case Array::Contiguous:
</span><span class="lines">@@ -483,7 +489,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case Array::ArrayStorage:
</span><span class="lines">@@ -494,7 +500,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case Array::Int8Array:
</span><span class="lines">@@ -529,7 +535,7 @@
</span><span class="cx"> case Array::String:
</span><span class="cx"> // Assume the worst since we don't have profiling yet.
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case Array::ForceExit:
</span><span class="lines">@@ -538,7 +544,7 @@
</span><span class="cx">
</span><span class="cx"> case Array::Generic:
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case Array::Arguments:
</span><span class="lines">@@ -551,7 +557,7 @@
</span><span class="cx"> case Array::Int32:
</span><span class="cx"> if (node->arrayMode().isOutOfBounds()) {
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> read(Butterfly_publicLength);
</span><span class="lines">@@ -566,7 +572,7 @@
</span><span class="cx"> case Array::Double:
</span><span class="cx"> if (node->arrayMode().isOutOfBounds()) {
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> read(Butterfly_publicLength);
</span><span class="lines">@@ -581,7 +587,7 @@
</span><span class="cx"> case Array::Contiguous:
</span><span class="cx"> if (node->arrayMode().isOutOfBounds()) {
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> read(Butterfly_publicLength);
</span><span class="lines">@@ -597,7 +603,7 @@
</span><span class="cx"> case Array::SlowPutArrayStorage:
</span><span class="cx"> // Give up on life for now.
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case Array::Int8Array:
</span><span class="lines">@@ -813,7 +819,7 @@
</span><span class="cx"> case StringCharAt:
</span><span class="cx"> if (node->arrayMode().isOutOfBounds()) {
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> def(PureValue(node));
</span><span class="lines">@@ -829,7 +835,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case ToString:
</span><span class="lines">@@ -843,7 +849,7 @@
</span><span class="cx"> case CellUse:
</span><span class="cx"> case UntypedUse:
</span><span class="cx"> read(World);
</span><del>- write(World);
</del><ins>+ write(Heap);
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> default:
</span><span class="lines">@@ -945,7 +951,7 @@
</span><span class="cx"> bool accessesOverlap(Graph&, Node*, AbstractHeap);
</span><span class="cx"> bool writesOverlap(Graph&, Node*, AbstractHeap);
</span><span class="cx">
</span><del>-bool clobbersWorld(Graph&, Node*);
</del><ins>+bool clobbersHeap(Graph&, Node*);
</ins><span class="cx">
</span><span class="cx"> // We would have used bind() for these, but because of the overlaoding that we are doing,
</span><span class="cx"> // it's quite a bit of clearer to just write this out the traditional way.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (180655 => 180656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-02-26 04:18:47 UTC (rev 180655)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-02-26 04:29:26 UTC (rev 180656)
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx">
</span><span class="cx"> bool doesGC(Graph& graph, Node* node)
</span><span class="cx"> {
</span><del>- if (clobbersWorld(graph, node))
</del><ins>+ if (clobbersHeap(graph, node))
</ins><span class="cx"> return true;
</span><span class="cx">
</span><span class="cx"> // Now consider nodes that don't clobber the world but that still may GC. This includes all
</span></span></pre>
</div>
</div>
</body>
</html>