Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.cpp (180655 => 180656)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.cpp 2015-02-26 04:18:47 UTC (rev 180655)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.cpp 2015-02-26 04:29:26 UTC (rev 180656)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -43,7 +43,7 @@
void AbstractHeap::dump(PrintStream& out) const
{
out.print(kind());
- if (kind() == InvalidAbstractHeap || kind() == World || payload().isTop())
+ if (kind() == InvalidAbstractHeap || kind() == World || kind() == Heap || payload().isTop())
return;
out.print("(", payload(), ")");
}
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.h (180655 => 180656)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.h 2015-02-26 04:18:47 UTC (rev 180655)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.h 2015-02-26 04:29:26 UTC (rev 180656)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,14 +34,19 @@
namespace JSC { namespace DFG {
-// Implements a three-level type hierarchy:
+// Implements a four-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.
+// - 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.
#define FOR_EACH_ABSTRACT_HEAP_KIND(macro) \
macro(InvalidAbstractHeap) \
macro(World) \
+ macro(Stack) \
+ macro(Heap) \
macro(Arguments_registers) \
macro(Butterfly_publicLength) \
macro(Butterfly_vectorLength) \
@@ -204,32 +209,48 @@
return payloadImpl();
}
- bool isDisjoint(const AbstractHeap& other) const
+ AbstractHeap supertype() const
{
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());
+ switch (kind()) {
+ case World:
+ return AbstractHeap();
+ case Heap:
+ return World;
+ default:
+ if (payload().isTop()) {
+ if (kind() == Stack)
+ return World;
+ return Heap;
+ }
+ return AbstractHeap(kind());
+ }
}
+ 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);
+ }
+
bool overlaps(const AbstractHeap& other) const
{
- return !isDisjoint(other);
+ return *this == other || isStrictSubtypeOf(other) || other.isStrictSubtypeOf(*this);
}
- AbstractHeap supertype() const
+ bool isDisjoint(const AbstractHeap& other) const
{
- ASSERT(kind() != InvalidAbstractHeap);
- if (kind() == World)
- return AbstractHeap();
- if (payload().isTop())
- return World;
- return AbstractHeap(kind());
+ return !overlaps(other);
}
unsigned hash() const
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (180655 => 180656)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-02-26 04:18:47 UTC (rev 180655)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-02-26 04:29:26 UTC (rev 180656)
@@ -41,6 +41,12 @@
{
// Some notes:
//
+ // - 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.
+ //
// - 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.
@@ -53,9 +59,9 @@
// 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_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.
+ // - 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.
//
// - 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
@@ -157,16 +163,16 @@
case GetEnumerableLength:
case GetStructurePropertyEnumerator:
case GetGenericPropertyEnumerator: {
- read(World);
+ read(Heap);
write(SideState);
return;
}
case GetDirectPname: {
- // This reads and writes world because it can end up calling a generic getByVal
+ // This reads and writes heap because it can end up calling a generic getByVal
// if the Structure changed, which could in turn end up calling a getter.
read(World);
- write(World);
+ write(Heap);
return;
}
@@ -187,7 +193,7 @@
def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
return;
}
- read(World);
+ read(Heap);
return;
}
@@ -198,7 +204,7 @@
def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
return;
}
- read(World);
+ read(Heap);
return;
}
@@ -209,7 +215,7 @@
def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node);
return;
}
- read(World);
+ read(Heap);
return;
}
@@ -219,13 +225,13 @@
read(IndexedArrayStorageProperties);
return;
}
- read(World);
+ read(Heap);
return;
}
default: {
read(World);
- write(World);
+ write(Heap);
return;
}
}
@@ -376,7 +382,7 @@
case GetMyArgumentByValSafe:
case ValueAdd:
read(World);
- write(World);
+ write(Heap);
return;
case GetGetter:
@@ -425,7 +431,7 @@
case Array::Undecided:
// Assume the worst since we don't have profiling yet.
read(World);
- write(World);
+ write(Heap);
return;
case Array::ForceExit:
@@ -434,13 +440,13 @@
case Array::Generic:
read(World);
- write(World);
+ write(Heap);
return;
case Array::String:
if (mode.isOutOfBounds()) {
read(World);
- write(World);
+ write(Heap);
return;
}
// This appears to read nothing because it's only reading immutable data.
@@ -461,7 +467,7 @@
return;
}
read(World);
- write(World);
+ write(Heap);
return;
case Array::Double:
@@ -472,7 +478,7 @@
return;
}
read(World);
- write(World);
+ write(Heap);
return;
case Array::Contiguous:
@@ -483,7 +489,7 @@
return;
}
read(World);
- write(World);
+ write(Heap);
return;
case Array::ArrayStorage:
@@ -494,7 +500,7 @@
return;
}
read(World);
- write(World);
+ write(Heap);
return;
case Array::Int8Array:
@@ -529,7 +535,7 @@
case Array::String:
// Assume the worst since we don't have profiling yet.
read(World);
- write(World);
+ write(Heap);
return;
case Array::ForceExit:
@@ -538,7 +544,7 @@
case Array::Generic:
read(World);
- write(World);
+ write(Heap);
return;
case Array::Arguments:
@@ -551,7 +557,7 @@
case Array::Int32:
if (node->arrayMode().isOutOfBounds()) {
read(World);
- write(World);
+ write(Heap);
return;
}
read(Butterfly_publicLength);
@@ -566,7 +572,7 @@
case Array::Double:
if (node->arrayMode().isOutOfBounds()) {
read(World);
- write(World);
+ write(Heap);
return;
}
read(Butterfly_publicLength);
@@ -581,7 +587,7 @@
case Array::Contiguous:
if (node->arrayMode().isOutOfBounds()) {
read(World);
- write(World);
+ write(Heap);
return;
}
read(Butterfly_publicLength);
@@ -597,7 +603,7 @@
case Array::SlowPutArrayStorage:
// Give up on life for now.
read(World);
- write(World);
+ write(Heap);
return;
case Array::Int8Array:
@@ -813,7 +819,7 @@
case StringCharAt:
if (node->arrayMode().isOutOfBounds()) {
read(World);
- write(World);
+ write(Heap);
return;
}
def(PureValue(node));
@@ -829,7 +835,7 @@
return;
}
read(World);
- write(World);
+ write(Heap);
return;
case ToString:
@@ -843,7 +849,7 @@
case CellUse:
case UntypedUse:
read(World);
- write(World);
+ write(Heap);
return;
default:
@@ -945,7 +951,7 @@
bool accessesOverlap(Graph&, Node*, AbstractHeap);
bool writesOverlap(Graph&, Node*, AbstractHeap);
-bool clobbersWorld(Graph&, Node*);
+bool clobbersHeap(Graph&, Node*);
// We would have used bind() for these, but because of the overlaoding that we are doing,
// it's quite a bit of clearer to just write this out the traditional way.