]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGValidate.cpp
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / dfg / DFGValidate.cpp
index 6720451a1dd5aa397a25285af9668d150a04f4b6..ecd4d870858cc0065bd5d7588cf36927387fb55b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +29,7 @@
 #if ENABLE(DFG_JIT)
 
 #include "CodeBlockWithJITType.h"
+#include "JSCInlines.h"
 #include <wtf/Assertions.h>
 #include <wtf/BitVector.h>
 
@@ -44,6 +45,7 @@ public:
     
     #define VALIDATE(context, assertion) do { \
         if (!(assertion)) { \
+            startCrashing(); \
             dataLogF("\n\n\nAt "); \
             reportValidationContext context; \
             dataLogF(": validation %s (%s:%d) failed.\n", #assertion, __FILE__, __LINE__); \
@@ -55,6 +57,7 @@ public:
     
     #define V_EQUAL(context, left, right) do { \
         if (left != right) { \
+            startCrashing(); \
             dataLogF("\n\n\nAt "); \
             reportValidationContext context; \
             dataLogF(": validation (%s = ", #left); \
@@ -74,31 +77,35 @@ public:
     {
         // NB. This code is not written for performance, since it is not intended to run
         // in release builds.
-        
+
         // Validate that all local variables at the head of the root block are dead.
-        BasicBlock* root = m_graph.m_blocks[0].get();
+        BasicBlock* root = m_graph.block(0);
         for (unsigned i = 0; i < root->variablesAtHead.numberOfLocals(); ++i)
-            V_EQUAL((static_cast<VirtualRegister>(i), 0), static_cast<Node*>(0), root->variablesAtHead.local(i));
+            V_EQUAL((virtualRegisterForLocal(i), root), static_cast<Node*>(0), root->variablesAtHead.local(i));
         
         // Validate ref counts and uses.
-        HashMap<Node*, unsigned> myRefCounts;
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
-            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
-            if (!block || !block->isReachable)
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
                 continue;
+            VALIDATE((block), block->isReachable);
             for (size_t i = 0; i < block->numNodes(); ++i)
-                myRefCounts.add(block->node(i), 0);
+                m_myRefCounts.add(block->node(i), 0);
         }
-        HashSet<Node*> acceptableNodes;
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
-            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
-            if (!block || !block->isReachable)
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
                 continue;
             for (size_t i = 0; i < block->numNodes(); ++i) {
                 Node* node = block->node(i);
-                acceptableNodes.add(node);
+                m_acceptableNodes.add(node);
                 if (!node->shouldGenerate())
                     continue;
+                if (node->op() == Upsilon) {
+                    VALIDATE((node), m_graph.m_form == SSA);
+                    if (node->phi()->shouldGenerate())
+                        m_myRefCounts.find(node)->value++;
+                }
                 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
                     // Phi children in LoadStore form are invalid.
                     if (m_graph.m_form == LoadStore && block->isPhiIndex(i))
@@ -108,22 +115,31 @@ public:
                     if (!edge)
                         continue;
                     
-                    myRefCounts.find(edge.node())->value++;
+                    m_myRefCounts.find(edge.node())->value++;
+                    
+                    VALIDATE((node, edge), edge->hasDoubleResult() == (edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse || edge.useKind() == DoubleRepMachineIntUse));
+                    VALIDATE((node, edge), edge->hasInt52Result() == (edge.useKind() == Int52RepUse));
+                    
+                    if (m_graph.m_form == SSA) {
+                        // In SSA, all edges must hasResult().
+                        VALIDATE((node, edge), edge->hasResult());
+                        continue;
+                    }
                     
                     // Unless I'm a Flush, Phantom, GetLocal, or Phi, my children should hasResult().
                     switch (node->op()) {
                     case Flush:
                     case GetLocal:
-                        VALIDATE((node, edge), edge->hasVariableAccessData());
+                        VALIDATE((node, edge), edge->hasVariableAccessData(m_graph));
                         VALIDATE((node, edge), edge->variableAccessData() == node->variableAccessData());
                         break;
                     case PhantomLocal:
-                        VALIDATE((node, edge), edge->hasVariableAccessData());
+                        VALIDATE((node, edge), edge->hasVariableAccessData(m_graph));
                         VALIDATE((node, edge), edge->variableAccessData() == node->variableAccessData());
                         VALIDATE((node, edge), edge->op() != SetLocal);
                         break;
                     case Phi:
-                        VALIDATE((node, edge), edge->hasVariableAccessData());
+                        VALIDATE((node, edge), edge->hasVariableAccessData(m_graph));
                         if (m_graph.m_unificationState == LocallyUnified)
                             break;
                         VALIDATE((node, edge), edge->variableAccessData() == node->variableAccessData());
@@ -148,6 +164,9 @@ public:
                         case ThreadedCPS:
                             VALIDATE((node, edge), edge->hasResult());
                             break;
+                        case SSA:
+                            RELEASE_ASSERT_NOT_REACHED();
+                            break;
                         }
                         break;
                     default:
@@ -157,9 +176,64 @@ public:
                 }
             }
         }
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
-            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
-            if (!block || !block->isReachable)
+        
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            for (size_t i = 0; i < block->numNodes(); ++i) {
+                Node* node = block->node(i);
+                if (m_graph.m_refCountState == ExactRefCount)
+                    V_EQUAL((node), m_myRefCounts.get(node), node->adjustedRefCount());
+                else
+                    V_EQUAL((node), node->refCount(), 1);
+            }
+            
+            for (size_t i = 0 ; i < block->size() - 1; ++i) {
+                Node* node = block->at(i);
+                VALIDATE((node), !node->isTerminal());
+            }
+            
+            for (size_t i = 0; i < block->size(); ++i) {
+                Node* node = block->at(i);
+                
+                if (node->hasStructure())
+                    VALIDATE((node), !!node->structure());
+                
+                switch (node->op()) {
+                case Identity:
+                    VALIDATE((node), canonicalResultRepresentation(node->result()) == canonicalResultRepresentation(node->child1()->result()));
+                    break;
+                default:
+                    break;
+                }
+            }
+        }
+        
+        switch (m_graph.m_form) {
+        case LoadStore:
+        case ThreadedCPS:
+            validateCPS();
+            break;
+            
+        case SSA:
+            validateSSA();
+            break;
+        }
+    }
+    
+private:
+    Graph& m_graph;
+    GraphDumpMode m_graphDumpMode;
+    
+    HashMap<Node*, unsigned> m_myRefCounts;
+    HashSet<Node*> m_acceptableNodes;
+    
+    void validateCPS()
+    {
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
                 continue;
             
             HashSet<Node*> phisInThisBlock;
@@ -170,15 +244,11 @@ public:
                 nodesInThisBlock.add(node);
                 if (block->isPhiIndex(i))
                     phisInThisBlock.add(node);
-                if (m_graph.m_refCountState == ExactRefCount)
-                    V_EQUAL((node), myRefCounts.get(node), node->adjustedRefCount());
-                else
-                    V_EQUAL((node), node->refCount(), 1);
                 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
                     Edge edge = m_graph.child(node, j);
                     if (!edge)
                         continue;
-                    VALIDATE((node, edge), acceptableNodes.contains(edge.node()));
+                    VALIDATE((node, edge), m_acceptableNodes.contains(edge.node()));
                 }
             }
             
@@ -201,10 +271,7 @@ public:
                         edge->op() == SetLocal
                         || edge->op() == SetArgument
                         || edge->op() == Flush
-                        || edge->op() == Phi
-                        || edge->op() == ZombieHint
-                        || edge->op() == MovHint
-                        || edge->op() == MovHintAndCheck);
+                        || edge->op() == Phi);
                     
                     if (phisInThisBlock.contains(edge.node()))
                         continue;
@@ -213,9 +280,6 @@ public:
                         VALIDATE(
                             (node, edge),
                             edge->op() == SetLocal
-                            || edge->op() == ZombieHint
-                            || edge->op() == MovHint
-                            || edge->op() == MovHintAndCheck
                             || edge->op() == SetArgument
                             || edge->op() == Flush);
                         
@@ -225,14 +289,13 @@ public:
                     // There must exist a predecessor block that has this node index in
                     // its tail variables.
                     bool found = false;
-                    for (unsigned k = 0; k < block->m_predecessors.size(); ++k) {
-                        BasicBlock* prevBlock = m_graph.m_blocks[block->m_predecessors[k]].get();
-                        VALIDATE((Block, block->m_predecessors[k]), prevBlock);
-                        VALIDATE((Block, block->m_predecessors[k]), prevBlock->isReachable);
+                    for (unsigned k = 0; k < block->predecessors.size(); ++k) {
+                        BasicBlock* prevBlock = block->predecessors[k];
+                        VALIDATE((block->predecessors[k]), prevBlock);
                         Node* prevNode = prevBlock->variablesAtTail.operand(local);
                         // If we have a Phi that is not referring to *this* block then all predecessors
                         // must have that local available.
-                        VALIDATE((local, blockIndex, Block, block->m_predecessors[k]), prevNode);
+                        VALIDATE((local, block, block->predecessors[k]), prevNode);
                         switch (prevNode->op()) {
                         case GetLocal:
                         case Flush:
@@ -243,15 +306,12 @@ public:
                             break;
                         }
                         if (node->shouldGenerate()) {
-                            VALIDATE((local, block->m_predecessors[k], prevNode),
+                            VALIDATE((local, block->predecessors[k], prevNode),
                                      prevNode->shouldGenerate());
                         }
                         VALIDATE(
-                            (local, block->m_predecessors[k], prevNode),
+                            (local, block->predecessors[k], prevNode),
                             prevNode->op() == SetLocal
-                            || prevNode->op() == MovHint
-                            || prevNode->op() == MovHintAndCheck
-                            || prevNode->op() == ZombieHint
                             || prevNode->op() == SetArgument
                             || prevNode->op() == Phi);
                         if (prevNode == edge.node()) {
@@ -259,7 +319,7 @@ public:
                             break;
                         }
                         // At this point it cannot refer into this block.
-                        VALIDATE((local, block->m_predecessors[k], prevNode), !prevBlock->isInBlock(edge.node()));
+                        VALIDATE((local, block->predecessors[k], prevNode), !prevBlock->isInBlock(edge.node()));
                     }
                     
                     VALIDATE((node, edge), found);
@@ -274,17 +334,17 @@ public:
                 block->variablesAtHead.numberOfLocals());
             
             for (size_t i = 0; i < block->variablesAtHead.numberOfArguments(); ++i) {
-                VALIDATE((static_cast<VirtualRegister>(argumentToOperand(i)), blockIndex), !block->variablesAtHead.argument(i) || block->variablesAtHead.argument(i)->hasVariableAccessData());
+                VALIDATE((virtualRegisterForArgument(i), block), !block->variablesAtHead.argument(i) || block->variablesAtHead.argument(i)->hasVariableAccessData(m_graph));
                 if (m_graph.m_form == ThreadedCPS)
-                    VALIDATE((static_cast<VirtualRegister>(argumentToOperand(i)), blockIndex), !block->variablesAtTail.argument(i) || block->variablesAtTail.argument(i)->hasVariableAccessData());
+                    VALIDATE((virtualRegisterForArgument(i), block), !block->variablesAtTail.argument(i) || block->variablesAtTail.argument(i)->hasVariableAccessData(m_graph));
                 
                 getLocalPositions.argument(i) = notSet;
                 setLocalPositions.argument(i) = notSet;
             }
             for (size_t i = 0; i < block->variablesAtHead.numberOfLocals(); ++i) {
-                VALIDATE((static_cast<VirtualRegister>(i), blockIndex), !block->variablesAtHead.local(i) || block->variablesAtHead.local(i)->hasVariableAccessData());
+                VALIDATE((virtualRegisterForLocal(i), block), !block->variablesAtHead.local(i) || block->variablesAtHead.local(i)->hasVariableAccessData(m_graph));
                 if (m_graph.m_form == ThreadedCPS)
-                    VALIDATE((static_cast<VirtualRegister>(i), blockIndex), !block->variablesAtTail.local(i) || block->variablesAtTail.local(i)->hasVariableAccessData());
+                    VALIDATE((virtualRegisterForLocal(i), block), !block->variablesAtTail.local(i) || block->variablesAtTail.local(i)->hasVariableAccessData(m_graph));
 
                 getLocalPositions.local(i) = notSet;
                 setLocalPositions.local(i) = notSet;
@@ -307,6 +367,7 @@ public:
                     case Phantom:
                         if (m_graph.m_form == LoadStore && !j)
                             break;
+                        FALLTHROUGH;
                     default:
                         VALIDATE((node, edge), !phisInThisBlock.contains(edge.node()));
                         break;
@@ -321,10 +382,10 @@ public:
                         break;
                     // Ignore GetLocal's that we know to be dead, but that the graph
                     // doesn't yet know to be dead.
-                    if (!myRefCounts.get(node))
+                    if (!m_myRefCounts.get(node))
                         break;
                     if (m_graph.m_form == ThreadedCPS)
-                        VALIDATE((node, blockIndex), getLocalPositions.operand(node->local()) == notSet);
+                        VALIDATE((node, block), getLocalPositions.operand(node->local()) == notSet);
                     getLocalPositions.operand(node->local()) = i;
                     break;
                 case SetLocal:
@@ -346,34 +407,62 @@ public:
             
             for (size_t i = 0; i < block->variablesAtHead.numberOfArguments(); ++i) {
                 checkOperand(
-                    blockIndex, getLocalPositions, setLocalPositions, argumentToOperand(i));
+                    block, getLocalPositions, setLocalPositions, virtualRegisterForArgument(i));
             }
             for (size_t i = 0; i < block->variablesAtHead.numberOfLocals(); ++i) {
                 checkOperand(
-                    blockIndex, getLocalPositions, setLocalPositions, i);
+                    block, getLocalPositions, setLocalPositions, virtualRegisterForLocal(i));
             }
         }
     }
     
-private:
-    Graph& m_graph;
-    GraphDumpMode m_graphDumpMode;
+    void validateSSA()
+    {
+        // FIXME: Add more things here.
+        // https://bugs.webkit.org/show_bug.cgi?id=123471
+        
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            
+            unsigned nodeIndex = 0;
+            for (; nodeIndex < block->size() && !block->at(nodeIndex)->origin.isSet(); nodeIndex++) { }
+            
+            VALIDATE((block), nodeIndex < block->size());
+            
+            for (; nodeIndex < block->size(); nodeIndex++)
+                VALIDATE((block->at(nodeIndex)), block->at(nodeIndex)->origin.isSet());
+            
+            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
+                Node* node = block->at(nodeIndex);
+                switch (node->op()) {
+                case Phi:
+                    VALIDATE((node), !node->origin.isSet());
+                    break;
+                    
+                default:
+                    // FIXME: Add more things here.
+                    // https://bugs.webkit.org/show_bug.cgi?id=123471
+                    break;
+                }
+            }
+        }
+    }
     
     void checkOperand(
-        BlockIndex blockIndex, Operands<size_t>& getLocalPositions,
-        Operands<size_t>& setLocalPositions, int operand)
+        BasicBlock* block, Operands<size_t>& getLocalPositions,
+        Operands<size_t>& setLocalPositions, VirtualRegister operand)
     {
         if (getLocalPositions.operand(operand) == notSet)
             return;
         if (setLocalPositions.operand(operand) == notSet)
             return;
         
-        BasicBlock* block = m_graph.m_blocks[blockIndex].get();
-        
         VALIDATE(
             (block->at(getLocalPositions.operand(operand)),
              block->at(setLocalPositions.operand(operand)),
-             blockIndex),
+             block),
             getLocalPositions.operand(operand) < setLocalPositions.operand(operand));
     }
     
@@ -382,10 +471,9 @@ private:
         dataLogF("@%u", node->index());
     }
     
-    enum BlockTag { Block };
-    void reportValidationContext(BlockTag, BlockIndex blockIndex)
+    void reportValidationContext(BasicBlock* block)
     {
-        dataLogF("Block #%u", blockIndex);
+        dataLog("Block ", *block);
     }
     
     void reportValidationContext(Node* node, Edge edge)
@@ -393,39 +481,42 @@ private:
         dataLog(node, " -> ", edge);
     }
     
-    void reportValidationContext(VirtualRegister local, BlockIndex blockIndex)
+    void reportValidationContext(VirtualRegister local, BasicBlock* block)
     {
-        dataLogF("r%d in Block #%u", local, blockIndex);
+        if (!block) {
+            dataLog("r", local, " in null Block ");
+            return;
+        }
+
+        dataLog("r", local, " in Block ", *block);
     }
     
     void reportValidationContext(
-        VirtualRegister local, BlockIndex sourceBlockIndex, BlockTag, BlockIndex destinationBlockIndex)
+        VirtualRegister local, BasicBlock* sourceBlock, BasicBlock* destinationBlock)
     {
-        dataLogF("r%d in Block #%u -> #%u", local, sourceBlockIndex, destinationBlockIndex);
+        dataLog("r", local, " in Block ", *sourceBlock, " -> ", *destinationBlock);
     }
     
     void reportValidationContext(
-        VirtualRegister local, BlockIndex sourceBlockIndex, Node* prevNode)
+        VirtualRegister local, BasicBlock* sourceBlock, Node* prevNode)
     {
-        dataLogF("@%u for r%d in Block #%u", prevNode->index(), local, sourceBlockIndex);
+        dataLog(prevNode, " for r", local, " in Block ", *sourceBlock);
     }
     
-    void reportValidationContext(
-        Node* node, BlockIndex blockIndex)
+    void reportValidationContext(Node* node, BasicBlock* block)
     {
-        dataLogF("@%u in Block #%u", node->index(), blockIndex);
+        dataLog(node, " in Block ", *block);
     }
     
-    void reportValidationContext(
-        Node* node, Node* node2, BlockIndex blockIndex)
+    void reportValidationContext(Node* node, Node* node2, BasicBlock* block)
     {
-        dataLogF("@%u and @%u in Block #%u", node->index(), node2->index(), blockIndex);
+        dataLog(node, " and ", node2, " in Block ", *block);
     }
     
     void reportValidationContext(
-        Node* node, BlockIndex blockIndex, Node* expectedNode, Edge incomingEdge)
+        Node* node, BasicBlock* block, Node* expectedNode, Edge incomingEdge)
     {
-        dataLog(node, " in Block #", blockIndex, ", searching for ", expectedNode, " from ", incomingEdge);
+        dataLog(node, " in Block ", *block, ", searching for ", expectedNode, " from ", incomingEdge);
     }
     
     void dumpGraphIfAppropriate()