]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGCPSRethreadingPhase.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGCPSRethreadingPhase.cpp
index 076ba250e47356d6c4e6fd4ce416d44ecd8a5f99..09dbf328bda4c80a47ecc1a854bc6f62e3102455 100644 (file)
@@ -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
@@ -53,6 +53,7 @@ public:
         freeUnnecessaryNodes();
         m_graph.clearReplacements();
         canonicalizeLocalsInBlocks();
+        specialCaseArguments();
         propagatePhis<LocalOperand>();
         propagatePhis<ArgumentOperand>();
         computeIsFlushed();
@@ -90,13 +91,15 @@ private:
                     node->children.setChild1(Edge());
                     break;
                 case Phantom:
-                    if (!node->child1())
+                    if (!node->child1()) {
+                        m_graph.m_allocator.free(node);
                         continue;
+                    }
                     switch (node->child1()->op()) {
                     case Phi:
                     case SetArgument:
                     case SetLocal:
-                        node->convertToPhantomLocal();
+                        node->convertPhantomToPhantomLocal();
                         break;
                     default:
                         ASSERT(node->child1()->hasResult());
@@ -117,15 +120,15 @@ private:
     }
     
     template<OperandKind operandKind>
-    void clearVariablesAtHeadAndTail()
+    void clearVariables()
     {
         ASSERT(
             m_block->variablesAtHead.sizeFor<operandKind>()
             == m_block->variablesAtTail.sizeFor<operandKind>());
         
         for (unsigned i = m_block->variablesAtHead.sizeFor<operandKind>(); i--;) {
-            m_block->variablesAtHead.atFor<operandKind>(i) = 0;
-            m_block->variablesAtTail.atFor<operandKind>(i) = 0;
+            m_block->variablesAtHead.atFor<operandKind>(i) = nullptr;
+            m_block->variablesAtTail.atFor<operandKind>(i) = nullptr;
         }
     }
     
@@ -184,29 +187,14 @@ private:
                 return;
             }
             
-            if (variable->isCaptured()) {
-                variable->setIsLoadedFrom(true);
-                if (otherNode->op() == GetLocal)
-                    otherNode = otherNode->child1().node();
-                else
-                    ASSERT(otherNode->op() == SetLocal || otherNode->op() == SetArgument);
-                
-                ASSERT(otherNode->op() == Phi || otherNode->op() == SetLocal || otherNode->op() == SetArgument);
-                
-                // Keep this GetLocal but link it to the prior ones.
-                node->children.setChild1(Edge(otherNode));
-                m_block->variablesAtTail.atFor<operandKind>(idx) = node;
-                return;
-            }
-            
             if (otherNode->op() == GetLocal) {
                 // Replace all references to this GetLocal with otherNode.
-                node->misc.replacement = otherNode;
+                node->replaceWith(otherNode);
                 return;
             }
             
             ASSERT(otherNode->op() == SetLocal);
-            node->misc.replacement = otherNode->child1().node();
+            node->replaceWith(otherNode->child1().node());
             return;
         }
         
@@ -226,11 +214,6 @@ private:
             canonicalizeGetLocalFor<LocalOperand>(node, variable, variable->local().toLocal());
     }
     
-    void canonicalizeSetLocal(Node* node)
-    {
-        m_block->variablesAtTail.setOperand(node->local(), node);
-    }
-    
     template<NodeType nodeType, OperandKind operandKind>
     void canonicalizeFlushOrPhantomLocalFor(Node* node, VariableAccessData* variable, size_t idx)
     {
@@ -257,13 +240,9 @@ private:
                 // for the purpose of OSR. PhantomLocal(SetLocal) means: at this point I
                 // know that I would have read the value written by that SetLocal. This is
                 // redundant and inefficient, since really it just means that we want to
-                // be keeping the operand to the SetLocal alive. The SetLocal may die, and
-                // we'll be fine because OSR tracks dead SetLocals.
-                
-                // So we turn this into a Phantom on the child of the SetLocal.
+                // keep the last MovHinted value of that local alive.
                 
-                node->convertToPhantom();
-                node->children.setChild1(otherNode->child1());
+                node->remove();
                 return;
             }
             
@@ -294,13 +273,9 @@ private:
             canonicalizeFlushOrPhantomLocalFor<nodeType, LocalOperand>(node, variable, variable->local().toLocal());
     }
     
-    void canonicalizeSetArgument(Node* node)
+    void canonicalizeSet(Node* node)
     {
-        VirtualRegister local = node->local();
-        ASSERT(local.isArgument());
-        int argument = local.toArgument();
-        m_block->variablesAtHead.setArgumentFirstTime(argument, node);
-        m_block->variablesAtTail.setArgumentFirstTime(argument, node);
+        m_block->variablesAtTail.setOperand(node->local(), node);
     }
     
     void canonicalizeLocalsInBlock()
@@ -309,8 +284,8 @@ private:
             return;
         ASSERT(m_block->isReachable);
         
-        clearVariablesAtHeadAndTail<ArgumentOperand>();
-        clearVariablesAtHeadAndTail<LocalOperand>();
+        clearVariables<ArgumentOperand>();
+        clearVariables<LocalOperand>();
         
         // Assumes that all phi references have been removed. Assumes that things that
         // should be live have a non-zero ref count, but doesn't assume that the ref
@@ -339,10 +314,8 @@ private:
             // there ever was a SetLocal and it was followed by Flushes, then the tail
             // variable will be a SetLocal and not those subsequent Flushes.
             //
-            // Child of GetLocal: the operation that the GetLocal keeps alive. For
-            // uncaptured locals, it may be a Phi from the current block. For arguments,
-            // it may be a SetArgument. For captured locals and arguments it may also be
-            // a SetLocal.
+            // Child of GetLocal: the operation that the GetLocal keeps alive. It may be
+            // a Phi from the current block. For arguments, it may be a SetArgument.
             //
             // Child of SetLocal: must be a value producing node.
             //
@@ -365,7 +338,7 @@ private:
                 break;
                 
             case SetLocal:
-                canonicalizeSetLocal(node);
+                canonicalizeSet(node);
                 break;
                 
             case Flush:
@@ -377,7 +350,7 @@ private:
                 break;
                 
             case SetArgument:
-                canonicalizeSetArgument(node);
+                canonicalizeSet(node);
                 break;
                 
             default:
@@ -396,6 +369,16 @@ private:
         }
     }
     
+    void specialCaseArguments()
+    {
+        // Normally, a SetArgument denotes the start of a live range for a local's value on the stack.
+        // But those SetArguments used for the actual arguments to the machine CodeBlock get
+        // special-cased. We could have instead used two different node types - one for the arguments
+        // at the prologue case, and another for the other uses. But this seemed like IR overkill.
+        for (unsigned i = m_graph.m_arguments.size(); i--;)
+            m_graph.block(0)->variablesAtHead.setArgumentFirstTime(i, m_graph.m_arguments[i]);
+    }
+    
     template<OperandKind operandKind>
     void propagatePhis()
     {
@@ -500,8 +483,21 @@ private:
         }
         while (!m_flushedLocalOpWorklist.isEmpty()) {
             Node* node = m_flushedLocalOpWorklist.takeLast();
-            ASSERT(node->flags() & NodeIsFlushed);
-            DFG_NODE_DO_TO_CHILDREN(m_graph, node, addFlushedLocalEdge);
+            switch (node->op()) {
+            case SetLocal:
+            case SetArgument:
+                break;
+                
+            case Flush:
+            case Phi:
+                ASSERT(node->flags() & NodeIsFlushed);
+                DFG_NODE_DO_TO_CHILDREN(m_graph, node, addFlushedLocalEdge);
+                break;
+
+            default:
+                DFG_CRASH(m_graph, node, "Invalid node in flush graph");
+                break;
+            }
         }
     }