|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifdef DEBUG |
|
8 |
|
9 #include "jit/C1Spewer.h" |
|
10 |
|
11 #include <time.h> |
|
12 |
|
13 #include "jit/LinearScan.h" |
|
14 #include "jit/LIR.h" |
|
15 #include "jit/MIRGraph.h" |
|
16 |
|
17 using namespace js; |
|
18 using namespace js::jit; |
|
19 |
|
20 bool |
|
21 C1Spewer::init(const char *path) |
|
22 { |
|
23 spewout_ = fopen(path, "w"); |
|
24 return spewout_ != nullptr; |
|
25 } |
|
26 |
|
27 void |
|
28 C1Spewer::beginFunction(MIRGraph *graph, HandleScript script) |
|
29 { |
|
30 if (!spewout_) |
|
31 return; |
|
32 |
|
33 this->graph = graph; |
|
34 this->script.repoint(script); |
|
35 |
|
36 fprintf(spewout_, "begin_compilation\n"); |
|
37 if (script) { |
|
38 fprintf(spewout_, " name \"%s:%d\"\n", script->filename(), (int)script->lineno()); |
|
39 fprintf(spewout_, " method \"%s:%d\"\n", script->filename(), (int)script->lineno()); |
|
40 } else { |
|
41 fprintf(spewout_, " name \"asm.js compilation\"\n"); |
|
42 fprintf(spewout_, " method \"asm.js compilation\"\n"); |
|
43 } |
|
44 fprintf(spewout_, " date %d\n", (int)time(nullptr)); |
|
45 fprintf(spewout_, "end_compilation\n"); |
|
46 } |
|
47 |
|
48 void |
|
49 C1Spewer::spewPass(const char *pass) |
|
50 { |
|
51 if (!spewout_) |
|
52 return; |
|
53 |
|
54 fprintf(spewout_, "begin_cfg\n"); |
|
55 fprintf(spewout_, " name \"%s\"\n", pass); |
|
56 |
|
57 for (MBasicBlockIterator block(graph->begin()); block != graph->end(); block++) |
|
58 spewPass(spewout_, *block); |
|
59 |
|
60 fprintf(spewout_, "end_cfg\n"); |
|
61 fflush(spewout_); |
|
62 } |
|
63 |
|
64 void |
|
65 C1Spewer::spewIntervals(const char *pass, LinearScanAllocator *regalloc) |
|
66 { |
|
67 if (!spewout_) |
|
68 return; |
|
69 |
|
70 fprintf(spewout_, "begin_intervals\n"); |
|
71 fprintf(spewout_, " name \"%s\"\n", pass); |
|
72 |
|
73 size_t nextId = 0x4000; |
|
74 for (MBasicBlockIterator block(graph->begin()); block != graph->end(); block++) |
|
75 spewIntervals(spewout_, *block, regalloc, nextId); |
|
76 |
|
77 fprintf(spewout_, "end_intervals\n"); |
|
78 fflush(spewout_); |
|
79 } |
|
80 |
|
81 void |
|
82 C1Spewer::endFunction() |
|
83 { |
|
84 } |
|
85 |
|
86 void |
|
87 C1Spewer::finish() |
|
88 { |
|
89 if (spewout_) |
|
90 fclose(spewout_); |
|
91 } |
|
92 |
|
93 static void |
|
94 DumpDefinition(FILE *fp, MDefinition *def) |
|
95 { |
|
96 fprintf(fp, " "); |
|
97 fprintf(fp, "%u %u ", def->id(), unsigned(def->useCount())); |
|
98 def->printName(fp); |
|
99 fprintf(fp, " "); |
|
100 def->printOpcode(fp); |
|
101 fprintf(fp, " <|@\n"); |
|
102 } |
|
103 |
|
104 static void |
|
105 DumpLIR(FILE *fp, LInstruction *ins) |
|
106 { |
|
107 fprintf(fp, " "); |
|
108 fprintf(fp, "%d ", ins->id()); |
|
109 ins->dump(fp); |
|
110 fprintf(fp, " <|@\n"); |
|
111 } |
|
112 |
|
113 void |
|
114 C1Spewer::spewIntervals(FILE *fp, LinearScanAllocator *regalloc, LInstruction *ins, size_t &nextId) |
|
115 { |
|
116 for (size_t k = 0; k < ins->numDefs(); k++) { |
|
117 uint32_t id = ins->getDef(k)->virtualRegister(); |
|
118 VirtualRegister *vreg = ®alloc->vregs[id]; |
|
119 |
|
120 for (size_t i = 0; i < vreg->numIntervals(); i++) { |
|
121 LiveInterval *live = vreg->getInterval(i); |
|
122 if (live->numRanges()) { |
|
123 fprintf(fp, "%d object \"", (i == 0) ? id : int32_t(nextId++)); |
|
124 fprintf(fp, "%s", live->getAllocation()->toString()); |
|
125 fprintf(fp, "\" %d -1", id); |
|
126 for (size_t j = 0; j < live->numRanges(); j++) { |
|
127 fprintf(fp, " [%d, %d[", live->getRange(j)->from.pos(), |
|
128 live->getRange(j)->to.pos()); |
|
129 } |
|
130 for (UsePositionIterator usePos(live->usesBegin()); usePos != live->usesEnd(); usePos++) |
|
131 fprintf(fp, " %d M", usePos->pos.pos()); |
|
132 fprintf(fp, " \"\"\n"); |
|
133 } |
|
134 } |
|
135 } |
|
136 } |
|
137 |
|
138 void |
|
139 C1Spewer::spewIntervals(FILE *fp, MBasicBlock *block, LinearScanAllocator *regalloc, size_t &nextId) |
|
140 { |
|
141 LBlock *lir = block->lir(); |
|
142 if (!lir) |
|
143 return; |
|
144 |
|
145 for (size_t i = 0; i < lir->numPhis(); i++) |
|
146 spewIntervals(fp, regalloc, lir->getPhi(i), nextId); |
|
147 |
|
148 for (LInstructionIterator ins = lir->begin(); ins != lir->end(); ins++) |
|
149 spewIntervals(fp, regalloc, *ins, nextId); |
|
150 } |
|
151 |
|
152 void |
|
153 C1Spewer::spewPass(FILE *fp, MBasicBlock *block) |
|
154 { |
|
155 fprintf(fp, " begin_block\n"); |
|
156 fprintf(fp, " name \"B%d\"\n", block->id()); |
|
157 fprintf(fp, " from_bci -1\n"); |
|
158 fprintf(fp, " to_bci -1\n"); |
|
159 |
|
160 fprintf(fp, " predecessors"); |
|
161 for (uint32_t i = 0; i < block->numPredecessors(); i++) { |
|
162 MBasicBlock *pred = block->getPredecessor(i); |
|
163 fprintf(fp, " \"B%d\"", pred->id()); |
|
164 } |
|
165 fprintf(fp, "\n"); |
|
166 |
|
167 fprintf(fp, " successors"); |
|
168 for (uint32_t i = 0; i < block->numSuccessors(); i++) { |
|
169 MBasicBlock *successor = block->getSuccessor(i); |
|
170 fprintf(fp, " \"B%d\"", successor->id()); |
|
171 } |
|
172 fprintf(fp, "\n"); |
|
173 |
|
174 fprintf(fp, " xhandlers\n"); |
|
175 fprintf(fp, " flags\n"); |
|
176 |
|
177 if (block->lir() && block->lir()->begin() != block->lir()->end()) { |
|
178 fprintf(fp, " first_lir_id %d\n", block->lir()->firstId()); |
|
179 fprintf(fp, " last_lir_id %d\n", block->lir()->lastId()); |
|
180 } |
|
181 |
|
182 fprintf(fp, " begin_states\n"); |
|
183 |
|
184 if (block->entryResumePoint()) { |
|
185 fprintf(fp, " begin_locals\n"); |
|
186 fprintf(fp, " size %d\n", (int)block->numEntrySlots()); |
|
187 fprintf(fp, " method \"None\"\n"); |
|
188 for (uint32_t i = 0; i < block->numEntrySlots(); i++) { |
|
189 MDefinition *ins = block->getEntrySlot(i); |
|
190 fprintf(fp, " "); |
|
191 fprintf(fp, "%d ", i); |
|
192 if (ins->isUnused()) |
|
193 fprintf(fp, "unused"); |
|
194 else |
|
195 ins->printName(fp); |
|
196 fprintf(fp, "\n"); |
|
197 } |
|
198 fprintf(fp, " end_locals\n"); |
|
199 } |
|
200 fprintf(fp, " end_states\n"); |
|
201 |
|
202 fprintf(fp, " begin_HIR\n"); |
|
203 for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) |
|
204 DumpDefinition(fp, *phi); |
|
205 for (MInstructionIterator i(block->begin()); i != block->end(); i++) |
|
206 DumpDefinition(fp, *i); |
|
207 fprintf(fp, " end_HIR\n"); |
|
208 |
|
209 if (block->lir()) { |
|
210 fprintf(fp, " begin_LIR\n"); |
|
211 for (size_t i = 0; i < block->lir()->numPhis(); i++) |
|
212 DumpLIR(fp, block->lir()->getPhi(i)); |
|
213 for (LInstructionIterator i(block->lir()->begin()); i != block->lir()->end(); i++) |
|
214 DumpLIR(fp, *i); |
|
215 fprintf(fp, " end_LIR\n"); |
|
216 } |
|
217 |
|
218 fprintf(fp, " end_block\n"); |
|
219 } |
|
220 |
|
221 #endif /* DEBUG */ |
|
222 |