X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4be4e30906bcb8ee30b4d189205cb70bad6707ce..81345200c95645a1b0d2635520f96ad55dfde63f:/dfg/DFGValidate.cpp diff --git a/dfg/DFGValidate.cpp b/dfg/DFGValidate.cpp index 6720451..ecd4d87 100644 --- a/dfg/DFGValidate.cpp +++ b/dfg/DFGValidate.cpp @@ -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 #include @@ -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(i), 0), static_cast(0), root->variablesAtHead.local(i)); + V_EQUAL((virtualRegisterForLocal(i), root), static_cast(0), root->variablesAtHead.local(i)); // Validate ref counts and uses. - HashMap 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 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 m_myRefCounts; + HashSet m_acceptableNodes; + + void validateCPS() + { + for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { + BasicBlock* block = m_graph.block(blockIndex); + if (!block) continue; HashSet 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(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(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(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(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& getLocalPositions, - Operands& setLocalPositions, int operand) + BasicBlock* block, Operands& getLocalPositions, + Operands& 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()