Line data Source code
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 JS_JITSPEW
8 :
9 : #include "jit/JSONSpewer.h"
10 :
11 : #include "mozilla/SizePrintfMacros.h"
12 :
13 : #include <stdarg.h>
14 :
15 : #include "jit/BacktrackingAllocator.h"
16 : #include "jit/LIR.h"
17 : #include "jit/MIR.h"
18 : #include "jit/MIRGraph.h"
19 : #include "jit/RangeAnalysis.h"
20 :
21 : using namespace js;
22 : using namespace js::jit;
23 :
24 : void
25 0 : JSONSpewer::beginFunction(JSScript* script)
26 : {
27 0 : beginObject();
28 0 : if (script)
29 0 : formatProperty("name", "%s:%" PRIuSIZE, script->filename(), script->lineno());
30 : else
31 0 : property("name", "wasm compilation");
32 0 : beginListProperty("passes");
33 0 : }
34 :
35 : void
36 0 : JSONSpewer::beginPass(const char* pass)
37 : {
38 0 : beginObject();
39 0 : property("name", pass);
40 0 : }
41 :
42 : void
43 0 : JSONSpewer::spewMResumePoint(MResumePoint* rp)
44 : {
45 0 : if (!rp)
46 0 : return;
47 :
48 0 : beginObjectProperty("resumePoint");
49 :
50 0 : if (rp->caller())
51 0 : property("caller", rp->caller()->block()->id());
52 :
53 0 : switch (rp->mode()) {
54 : case MResumePoint::ResumeAt:
55 0 : property("mode", "At");
56 0 : break;
57 : case MResumePoint::ResumeAfter:
58 0 : property("mode", "After");
59 0 : break;
60 : case MResumePoint::Outer:
61 0 : property("mode", "Outer");
62 0 : break;
63 : }
64 :
65 0 : beginListProperty("operands");
66 0 : for (MResumePoint* iter = rp; iter; iter = iter->caller()) {
67 0 : for (int i = iter->numOperands() - 1; i >= 0; i--)
68 0 : value(iter->getOperand(i)->id());
69 0 : if (iter->caller())
70 0 : value("|");
71 : }
72 0 : endList();
73 :
74 0 : endObject();
75 : }
76 :
77 : void
78 0 : JSONSpewer::spewMDef(MDefinition* def)
79 : {
80 0 : beginObject();
81 :
82 0 : property("id", def->id());
83 :
84 0 : propertyName("opcode");
85 0 : out_.printf("\"");
86 0 : def->printOpcode(out_);
87 0 : out_.printf("\"");
88 :
89 0 : beginListProperty("attributes");
90 : #define OUTPUT_ATTRIBUTE(X) do{ if(def->is##X()) value(#X); } while(0);
91 0 : MIR_FLAG_LIST(OUTPUT_ATTRIBUTE);
92 : #undef OUTPUT_ATTRIBUTE
93 0 : endList();
94 :
95 0 : beginListProperty("inputs");
96 0 : for (size_t i = 0, e = def->numOperands(); i < e; i++)
97 0 : value(def->getOperand(i)->id());
98 0 : endList();
99 :
100 0 : beginListProperty("uses");
101 0 : for (MUseDefIterator use(def); use; use++)
102 0 : value(use.def()->id());
103 0 : endList();
104 :
105 0 : if (!def->isLowered()) {
106 0 : beginListProperty("memInputs");
107 0 : if (def->dependency())
108 0 : value(def->dependency()->id());
109 0 : endList();
110 : }
111 :
112 0 : bool isTruncated = false;
113 0 : if (def->isAdd() || def->isSub() || def->isMod() || def->isMul() || def->isDiv())
114 0 : isTruncated = static_cast<MBinaryArithInstruction*>(def)->isTruncated();
115 :
116 0 : if (def->type() != MIRType::None && def->range()) {
117 0 : beginStringProperty("type");
118 0 : def->range()->dump(out_);
119 0 : out_.printf(" : %s%s", StringFromMIRType(def->type()), (isTruncated ? " (t)" : ""));
120 0 : endStringProperty();
121 : } else {
122 0 : formatProperty("type", "%s%s", StringFromMIRType(def->type()), (isTruncated ? " (t)" : ""));
123 : }
124 :
125 0 : if (def->isInstruction()) {
126 0 : if (MResumePoint* rp = def->toInstruction()->resumePoint())
127 0 : spewMResumePoint(rp);
128 : }
129 :
130 0 : endObject();
131 0 : }
132 :
133 : void
134 0 : JSONSpewer::spewMIR(MIRGraph* mir)
135 : {
136 0 : beginObjectProperty("mir");
137 0 : beginListProperty("blocks");
138 :
139 0 : for (MBasicBlockIterator block(mir->begin()); block != mir->end(); block++) {
140 0 : beginObject();
141 :
142 0 : property("number", block->id());
143 0 : if (block->getHitState() == MBasicBlock::HitState::Count)
144 0 : property("count", block->getHitCount());
145 :
146 0 : beginListProperty("attributes");
147 0 : if (block->hasLastIns()) {
148 0 : if (block->isLoopBackedge())
149 0 : value("backedge");
150 0 : if (block->isLoopHeader())
151 0 : value("loopheader");
152 0 : if (block->isSplitEdge())
153 0 : value("splitedge");
154 : }
155 0 : endList();
156 :
157 0 : beginListProperty("predecessors");
158 0 : for (size_t i = 0; i < block->numPredecessors(); i++)
159 0 : value(block->getPredecessor(i)->id());
160 0 : endList();
161 :
162 0 : beginListProperty("successors");
163 0 : if (block->hasLastIns()) {
164 0 : for (size_t i = 0; i < block->numSuccessors(); i++)
165 0 : value(block->getSuccessor(i)->id());
166 : }
167 0 : endList();
168 :
169 0 : beginListProperty("instructions");
170 0 : for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++)
171 0 : spewMDef(*phi);
172 0 : for (MInstructionIterator i(block->begin()); i != block->end(); i++)
173 0 : spewMDef(*i);
174 0 : endList();
175 :
176 0 : spewMResumePoint(block->entryResumePoint());
177 :
178 0 : endObject();
179 : }
180 :
181 0 : endList();
182 0 : endObject();
183 0 : }
184 :
185 : void
186 0 : JSONSpewer::spewLIns(LNode* ins)
187 : {
188 0 : beginObject();
189 :
190 0 : property("id", ins->id());
191 :
192 0 : propertyName("opcode");
193 0 : out_.printf("\"");
194 0 : ins->dump(out_);
195 0 : out_.printf("\"");
196 :
197 0 : beginListProperty("defs");
198 0 : for (size_t i = 0; i < ins->numDefs(); i++)
199 0 : value(ins->getDef(i)->virtualRegister());
200 0 : endList();
201 :
202 0 : endObject();
203 0 : }
204 :
205 : void
206 0 : JSONSpewer::spewLIR(MIRGraph* mir)
207 : {
208 0 : beginObjectProperty("lir");
209 0 : beginListProperty("blocks");
210 :
211 0 : for (MBasicBlockIterator i(mir->begin()); i != mir->end(); i++) {
212 0 : LBlock* block = i->lir();
213 0 : if (!block)
214 0 : continue;
215 :
216 0 : beginObject();
217 0 : property("number", i->id());
218 :
219 0 : beginListProperty("instructions");
220 0 : for (size_t p = 0; p < block->numPhis(); p++)
221 0 : spewLIns(block->getPhi(p));
222 0 : for (LInstructionIterator ins(block->begin()); ins != block->end(); ins++)
223 0 : spewLIns(*ins);
224 0 : endList();
225 :
226 0 : endObject();
227 : }
228 :
229 0 : endList();
230 0 : endObject();
231 0 : }
232 :
233 : void
234 0 : JSONSpewer::spewRanges(BacktrackingAllocator* regalloc)
235 : {
236 0 : beginObjectProperty("ranges");
237 0 : beginListProperty("blocks");
238 :
239 0 : for (size_t bno = 0; bno < regalloc->graph.numBlocks(); bno++) {
240 0 : beginObject();
241 0 : property("number", bno);
242 0 : beginListProperty("vregs");
243 :
244 0 : LBlock* lir = regalloc->graph.getBlock(bno);
245 0 : for (LInstructionIterator ins = lir->begin(); ins != lir->end(); ins++) {
246 0 : for (size_t k = 0; k < ins->numDefs(); k++) {
247 0 : uint32_t id = ins->getDef(k)->virtualRegister();
248 0 : VirtualRegister* vreg = ®alloc->vregs[id];
249 :
250 0 : beginObject();
251 0 : property("vreg", id);
252 0 : beginListProperty("ranges");
253 :
254 0 : for (LiveRange::RegisterLinkIterator iter = vreg->rangesBegin(); iter; iter++) {
255 0 : LiveRange* range = LiveRange::get(*iter);
256 :
257 0 : beginObject();
258 0 : property("allocation", range->bundle()->allocation().toString().get());
259 0 : property("start", range->from().bits());
260 0 : property("end", range->to().bits());
261 0 : endObject();
262 : }
263 :
264 0 : endList();
265 0 : endObject();
266 : }
267 : }
268 :
269 0 : endList();
270 0 : endObject();
271 : }
272 :
273 0 : endList();
274 0 : endObject();
275 0 : }
276 :
277 : void
278 0 : JSONSpewer::endPass()
279 : {
280 0 : endObject();
281 0 : }
282 :
283 : void
284 0 : JSONSpewer::endFunction()
285 : {
286 0 : endList();
287 0 : endObject();
288 0 : }
289 :
290 : #endif /* JS_JITSPEW */
|