diff options
Diffstat (limited to 'js/src/jit/JSONSpewer.cpp')
-rw-r--r-- | js/src/jit/JSONSpewer.cpp | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/js/src/jit/JSONSpewer.cpp b/js/src/jit/JSONSpewer.cpp new file mode 100644 index 0000000000..81ce1a2859 --- /dev/null +++ b/js/src/jit/JSONSpewer.cpp @@ -0,0 +1,287 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifdef JS_JITSPEW + +# include "jit/JSONSpewer.h" + +# include "jit/BacktrackingAllocator.h" +# include "jit/LIR.h" +# include "jit/MIR.h" +# include "jit/MIRGraph.h" +# include "jit/RangeAnalysis.h" + +using namespace js; +using namespace js::jit; + +void JSONSpewer::beginFunction(JSScript* script) { + beginObject(); + formatProperty("name", "%s:%u", script->filename(), script->lineno()); + beginListProperty("passes"); +} + +void JSONSpewer::beginWasmFunction(unsigned funcIndex) { + beginObject(); + formatProperty("name", "wasm-func%u", funcIndex); + beginListProperty("passes"); +} + +void JSONSpewer::beginPass(const char* pass) { + beginObject(); + property("name", pass); +} + +void JSONSpewer::spewMResumePoint(MResumePoint* rp) { + if (!rp) { + return; + } + + beginObjectProperty("resumePoint"); + + if (rp->caller()) { + property("caller", rp->caller()->block()->id()); + } + + property("mode", ResumeModeToString(rp->mode())); + + beginListProperty("operands"); + for (MResumePoint* iter = rp; iter; iter = iter->caller()) { + for (int i = iter->numOperands() - 1; i >= 0; i--) { + value(iter->getOperand(i)->id()); + } + if (iter->caller()) { + value("|"); + } + } + endList(); + + endObject(); +} + +void JSONSpewer::spewMDef(MDefinition* def) { + beginObject(); + + property("id", def->id()); + + propertyName("opcode"); + out_.printf("\""); + def->printOpcode(out_); + out_.printf("\""); + + beginListProperty("attributes"); +# define OUTPUT_ATTRIBUTE(X) \ + do { \ + if (def->is##X()) value(#X); \ + } while (0); + MIR_FLAG_LIST(OUTPUT_ATTRIBUTE); +# undef OUTPUT_ATTRIBUTE + endList(); + + beginListProperty("inputs"); + for (size_t i = 0, e = def->numOperands(); i < e; i++) { + value(def->getOperand(i)->id()); + } + endList(); + + beginListProperty("uses"); + for (MUseDefIterator use(def); use; use++) { + value(use.def()->id()); + } + endList(); + + if (!def->isLowered()) { + beginListProperty("memInputs"); + if (def->dependency()) { + value(def->dependency()->id()); + } + endList(); + } + + bool isTruncated = false; + if (def->isAdd() || def->isSub() || def->isMod() || def->isMul() || + def->isDiv()) { + isTruncated = static_cast<MBinaryArithInstruction*>(def)->isTruncated(); + } + + if (def->type() != MIRType::None && def->range()) { + beginStringProperty("type"); + def->range()->dump(out_); + out_.printf(" : %s%s", StringFromMIRType(def->type()), + (isTruncated ? " (t)" : "")); + endStringProperty(); + } else { + formatProperty("type", "%s%s", StringFromMIRType(def->type()), + (isTruncated ? " (t)" : "")); + } + + if (def->isInstruction()) { + if (MResumePoint* rp = def->toInstruction()->resumePoint()) { + spewMResumePoint(rp); + } + } + + endObject(); +} + +void JSONSpewer::spewMIR(MIRGraph* mir) { + beginObjectProperty("mir"); + beginListProperty("blocks"); + + for (MBasicBlockIterator block(mir->begin()); block != mir->end(); block++) { + beginObject(); + + property("number", block->id()); + + beginListProperty("attributes"); + if (block->hasLastIns()) { + if (block->isLoopBackedge()) { + value("backedge"); + } + if (block->isLoopHeader()) { + value("loopheader"); + } + if (block->isSplitEdge()) { + value("splitedge"); + } + } + endList(); + + beginListProperty("predecessors"); + for (size_t i = 0; i < block->numPredecessors(); i++) { + value(block->getPredecessor(i)->id()); + } + endList(); + + beginListProperty("successors"); + if (block->hasLastIns()) { + for (size_t i = 0; i < block->numSuccessors(); i++) { + value(block->getSuccessor(i)->id()); + } + } + endList(); + + beginListProperty("instructions"); + for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) { + spewMDef(*phi); + } + for (MInstructionIterator i(block->begin()); i != block->end(); i++) { + spewMDef(*i); + } + endList(); + + spewMResumePoint(block->entryResumePoint()); + + endObject(); + } + + endList(); + endObject(); +} + +void JSONSpewer::spewLIns(LNode* ins) { + beginObject(); + + property("id", ins->id()); + + propertyName("opcode"); + out_.printf("\""); + ins->dump(out_); + out_.printf("\""); + + beginListProperty("defs"); + for (size_t i = 0; i < ins->numDefs(); i++) { + if (ins->isPhi()) { + value(ins->toPhi()->getDef(i)->virtualRegister()); + } else { + value(ins->toInstruction()->getDef(i)->virtualRegister()); + } + } + endList(); + + endObject(); +} + +void JSONSpewer::spewLIR(MIRGraph* mir) { + beginObjectProperty("lir"); + beginListProperty("blocks"); + + for (MBasicBlockIterator i(mir->begin()); i != mir->end(); i++) { + LBlock* block = i->lir(); + if (!block) { + continue; + } + + beginObject(); + property("number", i->id()); + + beginListProperty("instructions"); + for (size_t p = 0; p < block->numPhis(); p++) { + spewLIns(block->getPhi(p)); + } + for (LInstructionIterator ins(block->begin()); ins != block->end(); ins++) { + spewLIns(*ins); + } + endList(); + + endObject(); + } + + endList(); + endObject(); +} + +void JSONSpewer::spewRanges(BacktrackingAllocator* regalloc) { + beginObjectProperty("ranges"); + beginListProperty("blocks"); + + for (size_t bno = 0; bno < regalloc->graph.numBlocks(); bno++) { + beginObject(); + property("number", bno); + beginListProperty("vregs"); + + LBlock* lir = regalloc->graph.getBlock(bno); + for (LInstructionIterator ins = lir->begin(); ins != lir->end(); ins++) { + for (size_t k = 0; k < ins->numDefs(); k++) { + uint32_t id = ins->getDef(k)->virtualRegister(); + VirtualRegister* vreg = ®alloc->vregs[id]; + + beginObject(); + property("vreg", id); + beginListProperty("ranges"); + + for (LiveRange::RegisterLinkIterator iter = vreg->rangesBegin(); iter; + iter++) { + LiveRange* range = LiveRange::get(*iter); + + beginObject(); + property("allocation", + range->bundle()->allocation().toString().get()); + property("start", range->from().bits()); + property("end", range->to().bits()); + endObject(); + } + + endList(); + endObject(); + } + } + + endList(); + endObject(); + } + + endList(); + endObject(); +} + +void JSONSpewer::endPass() { endObject(); } + +void JSONSpewer::endFunction() { + endList(); + endObject(); +} + +#endif /* JS_JITSPEW */ |