tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 = &regalloc->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 */