2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "CodeBlock.h"
33 namespace JSC { namespace DFG {
37 // Creates an array of stringized names.
38 static const char* dfgOpNames[] = {
39 #define STRINGIZE_DFG_OP_ENUM(opcode, flags) #opcode ,
40 FOR_EACH_DFG_OP(STRINGIZE_DFG_OP_ENUM)
41 #undef STRINGIZE_DFG_OP_ENUM
44 const char *Graph::opName(NodeType op)
46 return dfgOpNames[op & NodeIdMask];
49 void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock)
51 Node& node = at(nodeIndex);
52 NodeType op = node.op;
54 unsigned refCount = node.refCount();
55 bool skipped = !refCount;
56 bool mustGenerate = node.mustGenerate();
62 // Example/explanation of dataflow dump output
64 // 14: <!2:7> GetByVal(@3, @13)
67 // (1) The nodeIndex of this operation.
68 // (2) The reference count. The number printed is the 'real' count,
69 // not including the 'mustGenerate' ref. If the node is
70 // 'mustGenerate' then the count it prefixed with '!'.
71 // (3) The virtual register slot assigned to this node.
72 // (4) The name of the operation.
73 // (5) The arguments to the operation. The may be of the form:
74 // @# - a NodeIndex referencing a prior node in the graph.
75 // arg# - an argument number.
76 // $# - the index in the CodeBlock of a constant { for numeric constants the value is displayed | for integers, in both decimal and hex }.
77 // id# - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }.
78 // var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations.
79 printf("% 4d:%s<%c%u:", (int)nodeIndex, skipped ? " skipped " : " ", mustGenerate ? '!' : ' ', refCount);
80 if (node.hasResult() && !skipped)
81 printf("%u", node.virtualRegister());
84 printf(">\t%s(", opName(op));
85 bool hasPrinted = false;
86 if (op & NodeHasVarArgs) {
87 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) {
92 printf("@%u", m_varArgChildren[childIdx]);
95 if (node.child1() != NoNode)
96 printf("@%u", node.child1());
97 if (node.child2() != NoNode)
98 printf(", @%u", node.child2());
99 if (node.child3() != NoNode)
100 printf(", @%u", node.child3());
101 hasPrinted = node.child1() != NoNode;
104 if (node.hasVarNumber()) {
105 printf("%svar%u", hasPrinted ? ", " : "", node.varNumber());
108 if (node.hasIdentifier()) {
110 printf("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), codeBlock->identifier(node.identifierNumber()).ustring().utf8().data());
112 printf("%sid%u", hasPrinted ? ", " : "", node.identifierNumber());
115 if (node.hasLocal()) {
116 int local = node.local();
117 if (operandIsArgument(local))
118 printf("%sarg%u", hasPrinted ? ", " : "", local - codeBlock->thisRegister());
120 printf("%sr%u", hasPrinted ? ", " : "", local);
123 if (op == JSConstant) {
124 printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber());
126 JSValue value = node.valueOfJSConstant(codeBlock);
127 printf(" = %s", value.description());
131 if (node.isBranch() || node.isJump()) {
132 printf("%sT:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.takenBytecodeOffset()));
135 if (node.isBranch()) {
136 printf("%sF:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.notTakenBytecodeOffset()));
145 printf(" predicting %s", predictionToString(getPrediction(node.local())));
146 if (node.hasVarNumber())
147 printf(" predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber())));
148 if (node.hasPrediction())
149 printf(" predicting %s", predictionToString(node.getPrediction()));
155 void Graph::dump(CodeBlock* codeBlock)
157 for (size_t b = 0; b < m_blocks.size(); ++b) {
158 printf("Block #%u (bc#%u): %s\n", (int)b, m_blocks[b]->bytecodeBegin, m_blocks[b]->isOSRTarget ? " (OSR target)" : "");
159 for (size_t i = m_blocks[b]->begin; i < m_blocks[b]->end; ++i)
162 printf("Phi Nodes:\n");
163 for (size_t i = m_blocks.last()->end; i < size(); ++i)
169 // FIXME: Convert this method to be iterative, not recursive.
170 void Graph::refChildren(NodeIndex op)
174 if (node.op & NodeHasVarArgs) {
175 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
176 ref(m_varArgChildren[childIdx]);
178 if (node.child1() == NoNode) {
179 ASSERT(node.child2() == NoNode && node.child3() == NoNode);
184 if (node.child2() == NoNode) {
185 ASSERT(node.child3() == NoNode);
190 if (node.child3() == NoNode)
196 void Graph::predictArgumentTypes(ExecState* exec, CodeBlock* codeBlock)
199 size_t numberOfArguments = std::min(exec->argumentCountIncludingThis(), m_predictions.numberOfArguments());
201 for (size_t arg = 1; arg < numberOfArguments; ++arg) {
202 JSValue argumentValue = exec->argument(arg - 1);
203 if (argumentValue.isInt32())
204 m_predictions.predictArgument(arg, PredictInt32, WeakPrediction);
205 else if (argumentValue.isDouble())
206 m_predictions.predictArgument(arg, PredictDouble, WeakPrediction);
210 #if ENABLE(DYNAMIC_OPTIMIZATION)
212 ASSERT(codeBlock->alternative);
214 CodeBlock* profiledCodeBlock = codeBlock->alternative();
215 ASSERT(codeBlock->m_numParameters >= 1);
216 for (size_t arg = 1; arg < static_cast<size_t>(codeBlock->m_numParameters); ++arg) {
217 ValueProfile* profile = profiledCodeBlock->valueProfileForArgument(arg);
221 m_predictions.predictArgument(arg, profile->computeUpdatedPrediction() & ~PredictionTagMask, StrongPrediction);
223 #if ENABLE(DFG_DEBUG_VERBOSE)
224 printf("Argument [%lu] prediction: %s\n", arg, predictionToString(m_predictions.getArgumentPrediction(arg)));
228 UNUSED_PARAM(codeBlock);
232 } } // namespace JSC::DFG