diff options
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGGraph.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGGraph.cpp | 190 |
1 files changed, 115 insertions, 75 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp index be3beec..84e2d4d 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.cpp +++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp @@ -33,88 +33,108 @@ namespace JSC { namespace DFG { #ifndef NDEBUG -void Graph::dump(CodeBlock* codeBlock) -{ - // Creates an array of stringized names. + +// Creates an array of stringized names. +static const char* dfgOpNames[] = { #define STRINGIZE_DFG_OP_ENUM(opcode, flags) #opcode , - const char* dfgOpNames[] = { - FOR_EACH_DFG_OP(STRINGIZE_DFG_OP_ENUM) - }; + FOR_EACH_DFG_OP(STRINGIZE_DFG_OP_ENUM) #undef STRINGIZE_DFG_OP_ENUM +}; + +void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock) +{ + Node& node = at(nodeIndex); + NodeType op = node.op; + + unsigned refCount = node.refCount; + if (!refCount) + return; + bool mustGenerate = node.mustGenerate(); + if (mustGenerate) + --refCount; + + // Example/explanation of dataflow dump output + // + // 14: <!2:7> GetByVal(@3, @13) + // ^1 ^2 ^3 ^4 ^5 + // + // (1) The nodeIndex of this operation. + // (2) The reference count. The number printed is the 'real' count, + // not including the 'mustGenerate' ref. If the node is + // 'mustGenerate' then the count it prefixed with '!'. + // (3) The virtual register slot assigned to this node. + // (4) The name of the operation. + // (5) The arguments to the operation. The may be of the form: + // @# - a NodeIndex referencing a prior node in the graph. + // arg# - an argument number. + // $# - the index in the CodeBlock of a constant { for numeric constants the value is displayed | for integers, in both decimal and hex }. + // id# - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }. + // var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations. + printf("% 4d:\t<%c%u:%u>\t%s(", (int)nodeIndex, mustGenerate ? '!' : ' ', refCount, node.virtualRegister, dfgOpNames[op & NodeIdMask]); + if (node.child1 != NoNode) + printf("@%u", node.child1); + if (node.child2 != NoNode) + printf(", @%u", node.child2); + if (node.child3 != NoNode) + printf(", @%u", node.child3); + bool hasPrinted = node.child1 != NoNode; + + if (node.hasVarNumber()) { + printf("%svar%u", hasPrinted ? ", " : "", node.varNumber()); + hasPrinted = true; + } + if (node.hasIdentifier()) { + if (codeBlock) + printf("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), codeBlock->identifier(node.identifierNumber()).ustring().utf8().data()); + else + printf("%sid%u", hasPrinted ? ", " : "", node.identifierNumber()); + hasPrinted = true; + } + if (node.hasLocal()) { + int local = node.local(); + if (local < 0) + printf("%sarg%u", hasPrinted ? ", " : "", local - codeBlock->thisRegister()); + else + printf("%sr%u", hasPrinted ? ", " : "", local); + hasPrinted = true; + } + if (op == Int32Constant) { + printf("%s$%u{%d|0x%08x}", hasPrinted ? ", " : "", node.constantNumber(), node.int32Constant(), node.int32Constant()); + hasPrinted = true; + } + if (op == DoubleConstant) { + printf("%s$%u{%f})", hasPrinted ? ", " : "", node.constantNumber(), node.numericConstant()); + hasPrinted = true; + } + if (op == JSConstant) { + printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber()); + hasPrinted = true; + } + if (node.isBranch() || node.isJump()) { + printf("%sT:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.takenBytecodeOffset())); + hasPrinted = true; + } + if (node.isBranch()) { + printf("%sF:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.notTakenBytecodeOffset())); + hasPrinted = true; + } + + printf(")\n"); +} - Node* nodes = this->begin(); - - for (size_t i = 0; i < size(); ++i) { - Node& node = nodes[i]; - NodeType op = node.op; - - unsigned refCount = node.refCount; - if (!refCount) - continue; - bool mustGenerate = node.mustGenerate(); - if (mustGenerate) - --refCount; - - // Example/explanation of dataflow dump output - // - // 14: <!2:7> GetByVal(@3, @13) - // ^1 ^2 ^3 ^4 ^5 - // - // (1) The nodeIndex of this operation. - // (2) The reference count. The number printed is the 'real' count, - // not including the 'mustGenerate' ref. If the node is - // 'mustGenerate' then the count it prefixed with '!'. - // (3) The virtual register slot assigned to this node. - // (4) The name of the operation. - // (5) The arguments to the operation. The may be of the form: - // @# - a NodeIndex referencing a prior node in the graph. - // arg# - an argument number. - // $# - the index in the CodeBlock of a constant { for numeric constants the value is displayed | for integers, in both decimal and hex }. - // id# - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }. - // var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations. - printf("% 4d:\t<%c%u:%u>\t%s(", (int)i, mustGenerate ? '!' : ' ', refCount, node.virtualRegister, dfgOpNames[op & NodeIdMask]); - if (node.child1 != NoNode) - printf("@%u", node.child1); - if (node.child2 != NoNode) - printf(", @%u", node.child2); - if (node.child3 != NoNode) - printf(", @%u", node.child3); - bool hasPrinted = node.child1 != NoNode; - - if (node.hasVarNumber()) { - printf("%svar%u", hasPrinted ? ", " : "", node.varNumber()); - hasPrinted = true; - } - if (node.hasIdentifier()) { - if (codeBlock) - printf("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), codeBlock->identifier(node.identifierNumber()).ustring().utf8().data()); - else - printf("%sid%u", hasPrinted ? ", " : "", node.identifierNumber()); - hasPrinted = true; - } - if (node.isArgument()) { - printf("%sarg%u", hasPrinted ? ", " : "", node.argumentNumber()); - hasPrinted = true; - } - if (op == Int32Constant) { - printf("%s$%u{%d|0x%08x}", hasPrinted ? ", " : "", node.constantNumber(), node.int32Constant(), node.int32Constant()); - hasPrinted = true; - } - if (op == DoubleConstant) { - printf("%s$%u{%f})", hasPrinted ? ", " : "", node.constantNumber(), node.numericConstant()); - hasPrinted = true; - } - if (op == JSConstant) { - printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber()); - hasPrinted = true; - } - - printf(")\n"); +void Graph::dump(CodeBlock* codeBlock) +{ + for (size_t b = 0; b < m_blocks.size(); ++b) { + printf("Block #%u:\n", (int)b); + BasicBlock& block = m_blocks[b]; + for (size_t i = block.begin; i < block.end; ++i) + dump(i, codeBlock); } } + #endif -// FIXME: Convert this method to be iterative, not recursive. +// FIXME: Convert these methods to be iterative, not recursive. void Graph::refChildren(NodeIndex op) { Node& node = at(op); @@ -135,6 +155,26 @@ void Graph::refChildren(NodeIndex op) return; ref(node.child3); } +void Graph::derefChildren(NodeIndex op) +{ + Node& node = at(op); + + if (node.child1 == NoNode) { + ASSERT(node.child2 == NoNode && node.child3 == NoNode); + return; + } + deref(node.child1); + + if (node.child2 == NoNode) { + ASSERT(node.child3 == NoNode); + return; + } + deref(node.child2); + + if (node.child3 == NoNode) + return; + deref(node.child3); +} } } // namespace JSC::DFG |