GraphSpewer.cpp (7965B)
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/. */ 6 7 #ifdef JS_JITSPEW 8 9 # include "jit/GraphSpewer.h" 10 11 # include "jit/BacktrackingAllocator.h" 12 # include "jit/LIR.h" 13 # include "jit/MIR.h" 14 # include "jit/MIRGraph.h" 15 # include "jit/RangeAnalysis.h" 16 # include "wasm/WasmMetadata.h" 17 18 using namespace js; 19 using namespace js::jit; 20 21 static constexpr uint32_t IonGraphVersion = 1; 22 23 // Hash pointers to make them smaller, while still (probably) unique. 24 static uint32_t HashedPointer(const void* pointer) { 25 return mozilla::HashGeneric((uintptr_t)pointer); 26 } 27 28 void GraphSpewer::begin() { 29 beginObject(); 30 property("version", IonGraphVersion); 31 beginListProperty("functions"); 32 } 33 34 void GraphSpewer::beginFunction(JSScript* script) { 35 beginObject(); 36 formatProperty("name", "%s:%u", script->filename(), script->lineno()); 37 beginListProperty("passes"); 38 } 39 40 void GraphSpewer::beginWasmFunction(unsigned funcIndex) { 41 beginObject(); 42 formatProperty("name", "wasm-func%u", funcIndex); 43 beginListProperty("passes"); 44 } 45 46 void GraphSpewer::beginAnonFunction() { 47 beginObject(); 48 property("name", "unknown"); 49 beginListProperty("passes"); 50 } 51 52 void GraphSpewer::spewPass(const char* pass, MIRGraph* graph, 53 BacktrackingAllocator* ra) { 54 beginPass(pass); 55 spewMIR(graph); 56 spewLIR(graph); 57 if (ra) { 58 spewRanges(ra); 59 } 60 endPass(); 61 } 62 63 void GraphSpewer::beginPass(const char* pass) { 64 beginObject(); 65 property("name", pass); 66 } 67 68 void GraphSpewer::spewMResumePoint(MResumePoint* rp) { 69 if (!rp) { 70 return; 71 } 72 73 beginObjectProperty("resumePoint"); 74 75 if (rp->caller()) { 76 property("caller", rp->caller()->block()->id()); 77 } 78 79 property("mode", ResumeModeToString(rp->mode())); 80 81 beginListProperty("operands"); 82 for (MResumePoint* iter = rp; iter; iter = iter->caller()) { 83 for (int i = iter->numOperands() - 1; i >= 0; i--) { 84 value(iter->getOperand(i)->id()); 85 } 86 if (iter->caller()) { 87 value("|"); 88 } 89 } 90 endList(); 91 92 endObject(); 93 } 94 95 void GraphSpewer::spewMDef(MDefinition* def) { 96 beginObject(); 97 98 property("ptr", HashedPointer(def)); 99 property("id", def->id()); 100 101 propertyName("opcode"); 102 out_.printf("\""); 103 def->printOpcode(out_); 104 out_.printf("\""); 105 106 beginListProperty("attributes"); 107 # define OUTPUT_ATTRIBUTE(X) \ 108 do { \ 109 if (def->is##X()) value(#X); \ 110 } while (0); 111 MIR_FLAG_LIST(OUTPUT_ATTRIBUTE); 112 # undef OUTPUT_ATTRIBUTE 113 endList(); 114 115 beginListProperty("inputs"); 116 for (size_t i = 0, e = def->numOperands(); i < e; i++) { 117 value(def->getOperand(i)->id()); 118 } 119 endList(); 120 121 beginListProperty("uses"); 122 for (MUseDefIterator use(def); use; use++) { 123 value(use.def()->id()); 124 } 125 endList(); 126 127 if (!def->isLowered()) { 128 beginListProperty("memInputs"); 129 if (def->dependency()) { 130 value(def->dependency()->id()); 131 } 132 endList(); 133 } 134 135 bool isTruncated = false; 136 if (def->isAdd() || def->isSub() || def->isMod() || def->isMul() || 137 def->isDiv()) { 138 isTruncated = static_cast<MBinaryArithInstruction*>(def)->isTruncated(); 139 } 140 141 beginStringProperty("type"); 142 if (def->type() != MIRType::None && def->range()) { 143 def->range()->dump(out_); 144 out_.printf(": "); 145 } 146 if (def->wasmRefType().isSome()) { 147 out_.printf("%s: ", 148 wasm::ToString(def->wasmRefType(), wasmCodeMeta_->types).get()); 149 } 150 out_.printf("%s", StringFromMIRType(def->type())); 151 if (isTruncated) { 152 out_.printf(" (t)"); 153 } 154 endStringProperty(); 155 156 if (def->isInstruction()) { 157 if (MResumePoint* rp = def->toInstruction()->resumePoint()) { 158 spewMResumePoint(rp); 159 } 160 } 161 162 endObject(); 163 } 164 165 void GraphSpewer::spewMIR(MIRGraph* mir) { 166 beginObjectProperty("mir"); 167 beginListProperty("blocks"); 168 169 for (MBasicBlockIterator block(mir->begin()); block != mir->end(); block++) { 170 beginObject(); 171 172 property("ptr", HashedPointer(*block)); 173 property("id", block->id()); 174 property("loopDepth", block->loopDepth()); 175 176 beginListProperty("attributes"); 177 if (block->hasLastIns()) { 178 if (block->isLoopBackedge()) { 179 value("backedge"); 180 } 181 if (block->isLoopHeader()) { 182 value("loopheader"); 183 } 184 if (block->isSplitEdge()) { 185 value("splitedge"); 186 } 187 if (*block == mir->osrBlock()) { 188 value("osr"); 189 } 190 } 191 endList(); 192 193 beginListProperty("predecessors"); 194 for (size_t i = 0; i < block->numPredecessors(); i++) { 195 value(block->getPredecessor(i)->id()); 196 } 197 endList(); 198 199 beginListProperty("successors"); 200 if (block->hasLastIns()) { 201 for (size_t i = 0; i < block->numSuccessors(); i++) { 202 value(block->getSuccessor(i)->id()); 203 } 204 } 205 endList(); 206 207 beginListProperty("instructions"); 208 for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) { 209 spewMDef(*phi); 210 } 211 for (MInstructionIterator i(block->begin()); i != block->end(); i++) { 212 spewMDef(*i); 213 } 214 endList(); 215 216 spewMResumePoint(block->entryResumePoint()); 217 218 endObject(); 219 } 220 221 endList(); 222 endObject(); 223 } 224 225 void GraphSpewer::spewLIns(LNode* ins) { 226 beginObject(); 227 228 property("ptr", HashedPointer(ins)); 229 property("id", ins->id()); 230 if (ins->mirRaw()) { 231 property("mirPtr", HashedPointer(ins->mirRaw())); 232 } else { 233 nullProperty("mirPtr"); 234 } 235 236 propertyName("opcode"); 237 out_.printf("\""); 238 ins->dump(out_); 239 out_.printf("\""); 240 241 beginListProperty("defs"); 242 for (size_t i = 0; i < ins->numDefs(); i++) { 243 if (ins->isPhi()) { 244 value(ins->toPhi()->getDef(i)->virtualRegister()); 245 } else { 246 value(ins->toInstruction()->getDef(i)->virtualRegister()); 247 } 248 } 249 endList(); 250 251 endObject(); 252 } 253 254 void GraphSpewer::spewLIR(MIRGraph* mir) { 255 beginObjectProperty("lir"); 256 beginListProperty("blocks"); 257 258 for (MBasicBlockIterator i(mir->begin()); i != mir->end(); i++) { 259 LBlock* block = i->lir(); 260 if (!block) { 261 continue; 262 } 263 264 beginObject(); 265 property("id", i->id()); 266 property("ptr", HashedPointer(*i)); 267 268 beginListProperty("instructions"); 269 for (size_t p = 0; p < block->numPhis(); p++) { 270 spewLIns(block->getPhi(p)); 271 } 272 for (LInstructionIterator ins(block->begin()); ins != block->end(); ins++) { 273 spewLIns(*ins); 274 } 275 endList(); 276 277 endObject(); 278 } 279 280 endList(); 281 endObject(); 282 } 283 284 void GraphSpewer::spewRanges(BacktrackingAllocator* regalloc) { 285 beginObjectProperty("ranges"); 286 beginListProperty("blocks"); 287 288 for (size_t bno = 0; bno < regalloc->graph.numBlocks(); bno++) { 289 beginObject(); 290 property("number", bno); 291 beginListProperty("vregs"); 292 293 LBlock* lir = regalloc->graph.getBlock(bno); 294 for (LInstructionIterator ins = lir->begin(); ins != lir->end(); ins++) { 295 for (size_t k = 0; k < ins->numDefs(); k++) { 296 uint32_t id = ins->getDef(k)->virtualRegister(); 297 VirtualRegister* vreg = ®alloc->vregs[id]; 298 299 beginObject(); 300 property("vreg", id); 301 beginListProperty("ranges"); 302 303 for (VirtualRegister::RangeIterator iter(*vreg); iter; iter++) { 304 LiveRange* range = *iter; 305 306 beginObject(); 307 property("allocation", 308 range->bundle()->allocation().toString().get()); 309 property("start", range->from().bits()); 310 property("end", range->to().bits()); 311 endObject(); 312 } 313 314 endList(); 315 endObject(); 316 } 317 } 318 319 endList(); 320 endObject(); 321 } 322 323 endList(); 324 endObject(); 325 } 326 327 void GraphSpewer::endPass() { endObject(); } 328 329 void GraphSpewer::endFunction() { 330 endList(); 331 endObject(); 332 } 333 334 void GraphSpewer::end() { 335 endList(); 336 endObject(); 337 } 338 339 #endif /* JS_JITSPEW */