DFG should only have two mechanisms for describing effectfulness of nodes; previously there were three
https://bugs.webkit.org/show_bug.cgi?id=141369

Reviewed by Michael Saboff.

We previously used the NodeMightClobber and NodeClobbersWorld NodeFlags to describe
effectfulness.  Starting over a year ago, we introduced a more powerful mechanism - the
DFG::clobberize() function.  Now we only have one remaining client of the old NodeFlags,
and everyone else uses DFG::clobberize().  We should get rid of those NodeFlags and
finally switch everyone over to DFG::clobberize().
        
Unfortunately there is still another place where effectfulness of nodes is described: the
AbstractInterpreter. This is because the AbstractInterpreter has special tuning both for
compile time performance and there are places where the AI is more precise than
clobberize() because of its flow-sensitivity.
        
This means that after this change there will be only two places, rather than three, where
the effectfulness of a node has to be described:

- DFG::clobberize()
- DFG::AbstractInterpreter

* dfg/DFGClobberize.cpp:
(JSC::DFG::clobbersWorld):
* dfg/DFGClobberize.h:
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::attemptToMakeGetTypedArrayByteLength):
(JSC::DFG::FixupPhase::convertToGetArrayLength):
(JSC::DFG::FixupPhase::attemptToMakeGetTypedArrayByteOffset):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::isPredictedNumerical): Deleted.
(JSC::DFG::Graph::byValIsPure): Deleted.
(JSC::DFG::Graph::clobbersWorld): Deleted.
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToConstant):
(JSC::DFG::Node::convertToGetLocalUnlinked):
(JSC::DFG::Node::convertToGetByOffset):
(JSC::DFG::Node::convertToMultiGetByOffset):
(JSC::DFG::Node::convertToPutByOffset):
(JSC::DFG::Node::convertToMultiPutByOffset):
* dfg/DFGNodeFlags.cpp:
(JSC::DFG::dumpNodeFlags):
* dfg/DFGNodeFlags.h:
* dfg/DFGNodeType.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@179840 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index cecc0a8..d3f9c63 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,53 @@
+2015-02-08  Filip Pizlo  <fpizlo@apple.com>
+
+        DFG should only have two mechanisms for describing effectfulness of nodes; previously there were three
+        https://bugs.webkit.org/show_bug.cgi?id=141369
+
+        Reviewed by Michael Saboff.
+
+        We previously used the NodeMightClobber and NodeClobbersWorld NodeFlags to describe
+        effectfulness.  Starting over a year ago, we introduced a more powerful mechanism - the
+        DFG::clobberize() function.  Now we only have one remaining client of the old NodeFlags,
+        and everyone else uses DFG::clobberize().  We should get rid of those NodeFlags and
+        finally switch everyone over to DFG::clobberize().
+        
+        Unfortunately there is still another place where effectfulness of nodes is described: the
+        AbstractInterpreter. This is because the AbstractInterpreter has special tuning both for
+        compile time performance and there are places where the AI is more precise than
+        clobberize() because of its flow-sensitivity.
+        
+        This means that after this change there will be only two places, rather than three, where
+        the effectfulness of a node has to be described:
+
+        - DFG::clobberize()
+        - DFG::AbstractInterpreter
+
+        * dfg/DFGClobberize.cpp:
+        (JSC::DFG::clobbersWorld):
+        * dfg/DFGClobberize.h:
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::attemptToMakeGetTypedArrayByteLength):
+        (JSC::DFG::FixupPhase::convertToGetArrayLength):
+        (JSC::DFG::FixupPhase::attemptToMakeGetTypedArrayByteOffset):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::isPredictedNumerical): Deleted.
+        (JSC::DFG::Graph::byValIsPure): Deleted.
+        (JSC::DFG::Graph::clobbersWorld): Deleted.
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToConstant):
+        (JSC::DFG::Node::convertToGetLocalUnlinked):
+        (JSC::DFG::Node::convertToGetByOffset):
+        (JSC::DFG::Node::convertToMultiGetByOffset):
+        (JSC::DFG::Node::convertToPutByOffset):
+        (JSC::DFG::Node::convertToMultiPutByOffset):
+        * dfg/DFGNodeFlags.cpp:
+        (JSC::DFG::dumpNodeFlags):
+        * dfg/DFGNodeFlags.h:
+        * dfg/DFGNodeType.h:
+
 2015-02-09  Csaba Osztrogonác  <ossy@webkit.org>
 
         Fix the !ENABLE(DFG_JIT) build
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.cpp b/Source/JavaScriptCore/dfg/DFGClobberize.cpp
index ade3bb4..2d2f852 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.cpp
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.cpp
@@ -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
@@ -56,6 +56,19 @@
     return addWrite.result();
 }
 
+bool clobbersWorld(Graph& graph, Node* node)
+{
+    bool result = false;
+    clobberize(
+        graph, node, NoOpClobberize(),
+        [&] (AbstractHeap heap) {
+            if (heap == AbstractHeap(World))
+                result = true;
+        },
+        NoOpClobberize());
+    return result;
+}
+
 } } // namespace JSC::DFG
 
 #endif // ENABLE(DFG_JIT)
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index 3b4d48e..ac6b8f7 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -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
@@ -934,6 +934,8 @@
 bool accessesOverlap(Graph&, Node*, AbstractHeap);
 bool writesOverlap(Graph&, Node*, AbstractHeap);
 
+bool clobbersWorld(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.
 
diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
index 7c6090a..c6feafd 100644
--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 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
@@ -28,6 +28,7 @@
 
 #if ENABLE(DFG_JIT)
 
+#include "DFGClobberize.h"
 #include "DFGGraph.h"
 #include "DFGNode.h"
 #include "Operations.h"
@@ -36,7 +37,7 @@
 
 bool doesGC(Graph& graph, Node* node)
 {
-    if (graph.clobbersWorld(node))
+    if (clobbersWorld(graph, node))
         return true;
     
     // Now consider nodes that don't clobber the world but that still may GC. This includes all
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index b245fb9..e31a54d 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-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
@@ -161,14 +161,14 @@
         case ValueAdd: {
             if (attemptToMakeIntegerAdd(node)) {
                 node->setOp(ArithAdd);
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             if (Node::shouldSpeculateNumberOrBooleanExpectingDefined(node->child1().node(), node->child2().node())) {
                 fixDoubleOrBooleanEdge(node->child1());
                 fixDoubleOrBooleanEdge(node->child2());
                 node->setOp(ArithAdd);
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 node->setResult(NodeResultDouble);
                 break;
             }
@@ -382,26 +382,26 @@
                 && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
                 fixEdge<BooleanUse>(node->child1());
                 fixEdge<BooleanUse>(node->child2());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
                 fixIntOrBooleanEdge(node->child1());
                 fixIntOrBooleanEdge(node->child2());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             if (enableInt52()
                 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
                 fixEdge<Int52RepUse>(node->child1());
                 fixEdge<Int52RepUse>(node->child2());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
                 fixDoubleOrBooleanEdge(node->child1());
                 fixDoubleOrBooleanEdge(node->child2());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             if (node->op() != CompareEq)
@@ -409,31 +409,31 @@
             if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
                 fixEdge<StringIdentUse>(node->child1());
                 fixEdge<StringIdentUse>(node->child2());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
                 fixEdge<StringUse>(node->child1());
                 fixEdge<StringUse>(node->child2());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
                 fixEdge<ObjectUse>(node->child1());
                 fixEdge<ObjectUse>(node->child2());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
                 fixEdge<ObjectUse>(node->child1());
                 fixEdge<ObjectOrOtherUse>(node->child2());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
                 fixEdge<ObjectOrOtherUse>(node->child1());
                 fixEdge<ObjectUse>(node->child2());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             break;
@@ -829,7 +829,7 @@
         case NewTypedArray: {
             if (node->child1()->shouldSpeculateInt32()) {
                 fixEdge<Int32Use>(node->child1());
-                node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->clearFlags(NodeMustGenerate);
                 break;
             }
             break;
@@ -1947,7 +1947,7 @@
         // We can use a BitLShift here because typed arrays will never have a byteLength
         // that overflows int32.
         node->setOp(BitLShift);
-        node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+        node->clearFlags(NodeMustGenerate);
         observeUseKindOnNode(length, Int32Use);
         observeUseKindOnNode(shiftAmount, Int32Use);
         node->child1() = Edge(length, Int32Use);
@@ -1958,7 +1958,7 @@
     void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
     {
         node->setOp(GetArrayLength);
-        node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+        node->clearFlags(NodeMustGenerate);
         fixEdge<KnownCellUse>(node->child1());
         node->setArrayMode(arrayMode);
             
@@ -1991,7 +1991,7 @@
             0, neverNeedsStorage);
         
         node->setOp(GetTypedArrayByteOffset);
-        node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+        node->clearFlags(NodeMustGenerate);
         fixEdge<KnownCellUse>(node->child1());
         return true;
     }
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index e584a19..8c473f8 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -545,72 +545,6 @@
     
     void killUnreachableBlocks();
     
-    bool isPredictedNumerical(Node* node)
-    {
-        return isNumerical(node->child1().useKind()) && isNumerical(node->child2().useKind());
-    }
-    
-    // Note that a 'true' return does not actually mean that the ByVal access clobbers nothing.
-    // It really means that it will not clobber the entire world. It's still up to you to
-    // carefully consider things like:
-    // - PutByVal definitely changes the array it stores to, and may even change its length.
-    // - PutByOffset definitely changes the object it stores to.
-    // - and so on.
-    bool byValIsPure(Node* node)
-    {
-        switch (node->arrayMode().type()) {
-        case Array::Generic:
-            return false;
-        case Array::Int32:
-        case Array::Double:
-        case Array::Contiguous:
-        case Array::ArrayStorage:
-            return !node->arrayMode().isOutOfBounds();
-        case Array::SlowPutArrayStorage:
-            return !node->arrayMode().mayStoreToHole();
-        case Array::String:
-            return node->op() == GetByVal && node->arrayMode().isInBounds();
-#if USE(JSVALUE32_64)
-        case Array::Arguments:
-            if (node->op() == GetByVal)
-                return true;
-            return false;
-#endif // USE(JSVALUE32_64)
-        default:
-            return true;
-        }
-    }
-    
-    bool clobbersWorld(Node* node)
-    {
-        if (node->flags() & NodeClobbersWorld)
-            return true;
-        if (!(node->flags() & NodeMightClobber))
-            return false;
-        switch (node->op()) {
-        case GetByVal:
-        case PutByValDirect:
-        case PutByVal:
-        case PutByValAlias:
-            return !byValIsPure(node);
-        case ToString:
-            switch (node->child1().useKind()) {
-            case StringObjectUse:
-            case StringOrStringObjectUse:
-                return false;
-            case CellUse:
-            case UntypedUse:
-                return true;
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-                return true;
-            }
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            return true; // If by some oddity we hit this case in release build it's safer to have CSE assume the worst.
-        }
-    }
-    
     void determineReachability();
     void resetReachability();
     
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index c63d341..bffb866 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -448,7 +448,7 @@
             m_op = Int52Constant;
         else
             m_op = JSConstant;
-        m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld);
+        m_flags &= ~NodeMustGenerate;
         m_opInfo = bitwise_cast<uintptr_t>(value);
         children.reset();
     }
@@ -464,7 +464,7 @@
     void convertToGetLocalUnlinked(VirtualRegister local)
     {
         m_op = GetLocalUnlinked;
-        m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld);
+        m_flags &= ~NodeMustGenerate;
         m_opInfo = local.offset();
         m_opInfo2 = VirtualRegister().offset();
         children.reset();
@@ -478,7 +478,7 @@
         children.child2().setUseKind(KnownCellUse);
         children.setChild1(storage);
         m_op = GetByOffset;
-        m_flags &= ~(NodeClobbersWorld | NodeMustGenerate);
+        m_flags &= ~NodeMustGenerate;
     }
     
     void convertToMultiGetByOffset(MultiGetByOffsetData* data)
@@ -487,7 +487,6 @@
         m_opInfo = bitwise_cast<intptr_t>(data);
         child1().setUseKind(CellUse);
         m_op = MultiGetByOffset;
-        m_flags &= ~NodeClobbersWorld;
         ASSERT(m_flags & NodeMustGenerate);
     }
     
@@ -499,7 +498,6 @@
         children.setChild2(children.child1());
         children.setChild1(storage);
         m_op = PutByOffset;
-        m_flags &= ~NodeClobbersWorld;
     }
     
     void convertToMultiPutByOffset(MultiPutByOffsetData* data)
@@ -507,7 +505,6 @@
         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
         m_opInfo = bitwise_cast<intptr_t>(data);
         m_op = MultiPutByOffset;
-        m_flags &= ~NodeClobbersWorld;
     }
     
     void convertToPutByOffsetHint()
diff --git a/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp b/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
index 6beb771..366fbec 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
+++ b/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
@@ -74,12 +74,6 @@
     if (flags & NodeHasVarArgs)
         out.print(comma, "VarArgs");
     
-    if (flags & NodeClobbersWorld)
-        out.print(comma, "Clobbers");
-    
-    if (flags & NodeMightClobber)
-        out.print(comma, "MightClobber");
-    
     if (flags & NodeResultMask) {
         if (!(flags & NodeBytecodeUsesAsNumber) && !(flags & NodeBytecodeNeedsNegZero))
             out.print(comma, "PureInt");
diff --git a/Source/JavaScriptCore/dfg/DFGNodeFlags.h b/Source/JavaScriptCore/dfg/DFGNodeFlags.h
index 547075d..07e3a4e 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeFlags.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeFlags.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-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
@@ -46,8 +46,7 @@
                                 
 #define NodeMustGenerate                 0x0008 // set on nodes that have side effects, and may not trivially be removed by DCE.
 #define NodeHasVarArgs                   0x0010
-#define NodeClobbersWorld                0x0020
-#define NodeMightClobber                 0x0040
+// 0x0020 and 0x0040 are free.
                                 
 #define NodeBehaviorMask                 0x0780
 #define NodeMayOverflowInBaseline        0x0080
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 09b6284..65cb399 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-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
@@ -139,22 +139,22 @@
     macro(ArithCos, NodeResultNumber) \
     \
     /* Add of values may either be arithmetic, or result in string concatenation. */\
-    macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(ValueAdd, NodeResultJS | NodeMustGenerate) \
     \
     /* Property access. */\
     /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
     /* Since a put to 'length' may invalidate optimizations here, */\
     /* this must be the directly subsequent property put. Note that PutByVal */\
     /* opcodes use VarArgs beause they may have up to 4 children. */\
-    macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
-    macro(PutByValDirect, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
-    macro(PutByVal, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
-    macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
-    macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
-    macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
-    macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
-    macro(PutByIdFlush, NodeMustGenerate | NodeMustGenerate | NodeClobbersWorld) \
-    macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
+    macro(GetByVal, NodeResultJS | NodeMustGenerate) \
+    macro(PutByValDirect, NodeMustGenerate | NodeHasVarArgs) \
+    macro(PutByVal, NodeMustGenerate | NodeHasVarArgs) \
+    macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs) \
+    macro(GetById, NodeResultJS | NodeMustGenerate) \
+    macro(GetByIdFlush, NodeResultJS | NodeMustGenerate) \
+    macro(PutById, NodeMustGenerate) \
+    macro(PutByIdFlush, NodeMustGenerate | NodeMustGenerate) \
+    macro(PutByIdDirect, NodeMustGenerate) \
     macro(CheckStructure, NodeMustGenerate) \
     macro(GetExecutable, NodeResultJS) \
     macro(PutStructure, NodeMustGenerate) \
@@ -193,8 +193,8 @@
     macro(CheckInBounds, NodeMustGenerate) \
     \
     /* Optimizations for array mutation. */\
-    macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
-    macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(ArrayPush, NodeResultJS | NodeMustGenerate) \
+    macro(ArrayPop, NodeResultJS | NodeMustGenerate) \
     \
     /* Optimizations for regular expression matching. */\
     macro(RegExpExec, NodeResultJS | NodeMustGenerate) \
@@ -206,26 +206,26 @@
     macro(StringFromCharCode, NodeResultJS) \
     \
     /* Nodes for comparison operations. */\
-    macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
-    macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
-    macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
-    macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
-    macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
+    macro(CompareLess, NodeResultBoolean | NodeMustGenerate) \
+    macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate) \
+    macro(CompareGreater, NodeResultBoolean | NodeMustGenerate) \
+    macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate) \
+    macro(CompareEq, NodeResultBoolean | NodeMustGenerate) \
     macro(CompareEqConstant, NodeResultBoolean) \
     macro(CompareStrictEq, NodeResultBoolean) \
     \
     /* Calls. */\
-    macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
-    macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
-    macro(NativeCall, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
-    macro(NativeConstruct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
+    macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
+    macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
+    macro(NativeCall, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
+    macro(NativeConstruct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
     \
     /* Allocations. */\
     macro(NewObject, NodeResultJS) \
     macro(NewArray, NodeResultJS | NodeHasVarArgs) \
     macro(NewArrayWithSize, NodeResultJS | NodeMustGenerate) \
     macro(NewArrayBuffer, NodeResultJS) \
-    macro(NewTypedArray, NodeResultJS | NodeClobbersWorld | NodeMustGenerate) \
+    macro(NewTypedArray, NodeResultJS | NodeMustGenerate) \
     macro(NewRegexp, NodeResultJS) \
     \
     /* Support for allocation sinking. */\
@@ -249,11 +249,11 @@
     macro(IsFunction, NodeResultBoolean) \
     macro(TypeOf, NodeResultJS) \
     macro(LogicalNot, NodeResultBoolean) \
-    macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
-    macro(ToString, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
+    macro(ToPrimitive, NodeResultJS | NodeMustGenerate) \
+    macro(ToString, NodeResultJS | NodeMustGenerate) \
     macro(NewStringObject, NodeResultJS) \
     macro(MakeRope, NodeResultJS) \
-    macro(In, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
+    macro(In, NodeResultBoolean | NodeMustGenerate) \
     macro(ProfileType, NodeMustGenerate) \
     macro(ProfileControlFlow, NodeMustGenerate) \
     \
@@ -269,8 +269,8 @@
     macro(TearOffArguments, NodeMustGenerate) \
     macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate) \
     macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \
-    macro(GetMyArgumentsLengthSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
-    macro(GetMyArgumentByValSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(GetMyArgumentsLengthSafe, NodeResultJS | NodeMustGenerate) \
+    macro(GetMyArgumentByValSafe, NodeResultJS | NodeMustGenerate) \
     macro(CheckArgumentsNotCreated, NodeMustGenerate) \
     \
     /* Nodes for creating functions. */\