1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
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/. */
9 # include "jit/JSONSpewer.h"
11 # include "jit/BacktrackingAllocator.h"
14 # include "jit/MIRGraph.h"
15 # include "jit/RangeAnalysis.h"
18 using namespace js::jit
;
20 void JSONSpewer::beginFunction(JSScript
* script
) {
22 formatProperty("name", "%s:%u", script
->filename(), script
->lineno());
23 beginListProperty("passes");
26 void JSONSpewer::beginWasmFunction(unsigned funcIndex
) {
28 formatProperty("name", "wasm-func%u", funcIndex
);
29 beginListProperty("passes");
32 void JSONSpewer::beginPass(const char* pass
) {
34 property("name", pass
);
37 void JSONSpewer::spewMResumePoint(MResumePoint
* rp
) {
42 beginObjectProperty("resumePoint");
45 property("caller", rp
->caller()->block()->id());
48 property("mode", ResumeModeToString(rp
->mode()));
50 beginListProperty("operands");
51 for (MResumePoint
* iter
= rp
; iter
; iter
= iter
->caller()) {
52 for (int i
= iter
->numOperands() - 1; i
>= 0; i
--) {
53 value(iter
->getOperand(i
)->id());
64 void JSONSpewer::spewMDef(MDefinition
* def
) {
67 property("id", def
->id());
69 propertyName("opcode");
71 def
->printOpcode(out_
);
74 beginListProperty("attributes");
75 # define OUTPUT_ATTRIBUTE(X) \
77 if (def->is##X()) value(#X); \
79 MIR_FLAG_LIST(OUTPUT_ATTRIBUTE
);
80 # undef OUTPUT_ATTRIBUTE
83 beginListProperty("inputs");
84 for (size_t i
= 0, e
= def
->numOperands(); i
< e
; i
++) {
85 value(def
->getOperand(i
)->id());
89 beginListProperty("uses");
90 for (MUseDefIterator
use(def
); use
; use
++) {
91 value(use
.def()->id());
95 if (!def
->isLowered()) {
96 beginListProperty("memInputs");
97 if (def
->dependency()) {
98 value(def
->dependency()->id());
103 bool isTruncated
= false;
104 if (def
->isAdd() || def
->isSub() || def
->isMod() || def
->isMul() ||
106 isTruncated
= static_cast<MBinaryArithInstruction
*>(def
)->isTruncated();
109 if (def
->type() != MIRType::None
&& def
->range()) {
110 beginStringProperty("type");
111 def
->range()->dump(out_
);
112 out_
.printf(" : %s%s", StringFromMIRType(def
->type()),
113 (isTruncated
? " (t)" : ""));
116 formatProperty("type", "%s%s", StringFromMIRType(def
->type()),
117 (isTruncated
? " (t)" : ""));
120 if (def
->isInstruction()) {
121 if (MResumePoint
* rp
= def
->toInstruction()->resumePoint()) {
122 spewMResumePoint(rp
);
129 void JSONSpewer::spewMIR(MIRGraph
* mir
) {
130 beginObjectProperty("mir");
131 beginListProperty("blocks");
133 for (MBasicBlockIterator
block(mir
->begin()); block
!= mir
->end(); block
++) {
136 property("number", block
->id());
138 beginListProperty("attributes");
139 if (block
->hasLastIns()) {
140 if (block
->isLoopBackedge()) {
143 if (block
->isLoopHeader()) {
146 if (block
->isSplitEdge()) {
152 beginListProperty("predecessors");
153 for (size_t i
= 0; i
< block
->numPredecessors(); i
++) {
154 value(block
->getPredecessor(i
)->id());
158 beginListProperty("successors");
159 if (block
->hasLastIns()) {
160 for (size_t i
= 0; i
< block
->numSuccessors(); i
++) {
161 value(block
->getSuccessor(i
)->id());
166 beginListProperty("instructions");
167 for (MPhiIterator
phi(block
->phisBegin()); phi
!= block
->phisEnd(); phi
++) {
170 for (MInstructionIterator
i(block
->begin()); i
!= block
->end(); i
++) {
175 spewMResumePoint(block
->entryResumePoint());
184 void JSONSpewer::spewLIns(LNode
* ins
) {
187 property("id", ins
->id());
189 propertyName("opcode");
194 beginListProperty("defs");
195 for (size_t i
= 0; i
< ins
->numDefs(); i
++) {
197 value(ins
->toPhi()->getDef(i
)->virtualRegister());
199 value(ins
->toInstruction()->getDef(i
)->virtualRegister());
207 void JSONSpewer::spewLIR(MIRGraph
* mir
) {
208 beginObjectProperty("lir");
209 beginListProperty("blocks");
211 for (MBasicBlockIterator
i(mir
->begin()); i
!= mir
->end(); i
++) {
212 LBlock
* block
= i
->lir();
218 property("number", i
->id());
220 beginListProperty("instructions");
221 for (size_t p
= 0; p
< block
->numPhis(); p
++) {
222 spewLIns(block
->getPhi(p
));
224 for (LInstructionIterator
ins(block
->begin()); ins
!= block
->end(); ins
++) {
236 void JSONSpewer::spewRanges(BacktrackingAllocator
* regalloc
) {
237 beginObjectProperty("ranges");
238 beginListProperty("blocks");
240 for (size_t bno
= 0; bno
< regalloc
->graph
.numBlocks(); bno
++) {
242 property("number", bno
);
243 beginListProperty("vregs");
245 LBlock
* lir
= regalloc
->graph
.getBlock(bno
);
246 for (LInstructionIterator ins
= lir
->begin(); ins
!= lir
->end(); ins
++) {
247 for (size_t k
= 0; k
< ins
->numDefs(); k
++) {
248 uint32_t id
= ins
->getDef(k
)->virtualRegister();
249 VirtualRegister
* vreg
= ®alloc
->vregs
[id
];
252 property("vreg", id
);
253 beginListProperty("ranges");
255 for (LiveRange::RegisterLinkIterator iter
= vreg
->rangesBegin(); iter
;
257 LiveRange
* range
= LiveRange::get(*iter
);
260 property("allocation",
261 range
->bundle()->allocation().toString().get());
262 property("start", range
->from().bits());
263 property("end", range
->to().bits());
280 void JSONSpewer::endPass() { endObject(); }
282 void JSONSpewer::endFunction() {
287 #endif /* JS_JITSPEW */