• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25 
26 #include "config.h"
27 #include "DFGGraph.h"
28 
29 #include "CodeBlock.h"
30 
31 #if ENABLE(DFG_JIT)
32 
33 namespace JSC { namespace DFG {
34 
35 #ifndef NDEBUG
36 
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
42 };
43 
dump(NodeIndex nodeIndex,CodeBlock * codeBlock)44 void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock)
45 {
46     Node& node = at(nodeIndex);
47     NodeType op = node.op;
48 
49     unsigned refCount = node.refCount;
50     if (!refCount)
51         return;
52     bool mustGenerate = node.mustGenerate();
53     if (mustGenerate)
54         --refCount;
55 
56     // Example/explanation of dataflow dump output
57     //
58     //   14:   <!2:7>  GetByVal(@3, @13)
59     //   ^1     ^2 ^3     ^4       ^5
60     //
61     // (1) The nodeIndex of this operation.
62     // (2) The reference count. The number printed is the 'real' count,
63     //     not including the 'mustGenerate' ref. If the node is
64     //     'mustGenerate' then the count it prefixed with '!'.
65     // (3) The virtual register slot assigned to this node.
66     // (4) The name of the operation.
67     // (5) The arguments to the operation. The may be of the form:
68     //         @#   - a NodeIndex referencing a prior node in the graph.
69     //         arg# - an argument number.
70     //         $#   - the index in the CodeBlock of a constant { for numeric constants the value is displayed | for integers, in both decimal and hex }.
71     //         id#  - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }.
72     //         var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations.
73     printf("% 4d:\t<%c%u:%u>\t%s(", (int)nodeIndex, mustGenerate ? '!' : ' ', refCount, node.virtualRegister, dfgOpNames[op & NodeIdMask]);
74     if (node.child1 != NoNode)
75         printf("@%u", node.child1);
76     if (node.child2 != NoNode)
77         printf(", @%u", node.child2);
78     if (node.child3 != NoNode)
79         printf(", @%u", node.child3);
80     bool hasPrinted = node.child1 != NoNode;
81 
82     if (node.hasVarNumber()) {
83         printf("%svar%u", hasPrinted ? ", " : "", node.varNumber());
84         hasPrinted = true;
85     }
86     if (node.hasIdentifier()) {
87         if (codeBlock)
88             printf("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), codeBlock->identifier(node.identifierNumber()).ustring().utf8().data());
89         else
90             printf("%sid%u", hasPrinted ? ", " : "", node.identifierNumber());
91         hasPrinted = true;
92     }
93     if (node.hasLocal()) {
94         int local = node.local();
95         if (local < 0)
96             printf("%sarg%u", hasPrinted ? ", " : "", local - codeBlock->thisRegister());
97         else
98             printf("%sr%u", hasPrinted ? ", " : "", local);
99         hasPrinted = true;
100     }
101     if (op == Int32Constant) {
102         printf("%s$%u{%d|0x%08x}", hasPrinted ? ", " : "", node.constantNumber(), node.int32Constant(), node.int32Constant());
103         hasPrinted = true;
104     }
105     if (op == DoubleConstant) {
106         printf("%s$%u{%f})", hasPrinted ? ", " : "", node.constantNumber(), node.numericConstant());
107         hasPrinted = true;
108     }
109     if (op == JSConstant) {
110         printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber());
111         hasPrinted = true;
112     }
113     if  (node.isBranch() || node.isJump()) {
114         printf("%sT:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.takenBytecodeOffset()));
115         hasPrinted = true;
116     }
117     if  (node.isBranch()) {
118         printf("%sF:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.notTakenBytecodeOffset()));
119         hasPrinted = true;
120     }
121 
122     printf(")\n");
123 }
124 
dump(CodeBlock * codeBlock)125 void Graph::dump(CodeBlock* codeBlock)
126 {
127     for (size_t b = 0; b < m_blocks.size(); ++b) {
128         printf("Block #%u:\n", (int)b);
129         BasicBlock& block = m_blocks[b];
130         for (size_t i = block.begin; i < block.end; ++i)
131             dump(i, codeBlock);
132     }
133 }
134 
135 #endif
136 
137 // FIXME: Convert these methods to be iterative, not recursive.
refChildren(NodeIndex op)138 void Graph::refChildren(NodeIndex op)
139 {
140     Node& node = at(op);
141 
142     if (node.child1 == NoNode) {
143         ASSERT(node.child2 == NoNode && node.child3 == NoNode);
144         return;
145     }
146     ref(node.child1);
147 
148     if (node.child2 == NoNode) {
149         ASSERT(node.child3 == NoNode);
150         return;
151     }
152     ref(node.child2);
153 
154     if (node.child3 == NoNode)
155         return;
156     ref(node.child3);
157 }
derefChildren(NodeIndex op)158 void Graph::derefChildren(NodeIndex op)
159 {
160     Node& node = at(op);
161 
162     if (node.child1 == NoNode) {
163         ASSERT(node.child2 == NoNode && node.child3 == NoNode);
164         return;
165     }
166     deref(node.child1);
167 
168     if (node.child2 == NoNode) {
169         ASSERT(node.child3 == NoNode);
170         return;
171     }
172     deref(node.child2);
173 
174     if (node.child3 == NoNode)
175         return;
176     deref(node.child3);
177 }
178 
179 } } // namespace JSC::DFG
180 
181 #endif
182