Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/js/src/jit/shared/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 6 kB image not shown  

Quelle  Disassembler-shared.cpp   Sprache: C

 
/* -*- 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/. */


#include "jit/shared/Disassembler-shared.h"

#include "jit/JitSpewer.h"
#include "jit/Label.h"
#include "js/Printer.h"

using namespace js::jit;

using js::Sprinter;

#ifdef JS_DISASM_SUPPORTED
// Concurrent assemblers are disambiguated by prefixing every disassembly with a
// tag that is quasi-unique, and certainly unique enough in realistic cases
// where we are debugging and looking at disassembler output.  The tag is a
// letter or digit between brackets prefixing the disassembly, eg, [X]. This
// wraps around every 62 assemblers.
//
// When running with --no-threads we can still have concurrent assemblers in the
// form of nested assemblers, as when an IC stub is created by one assembler
// while a JS compilation is going on and producing output in another assembler.
//
// We generate the tag for an assembler by incrementing a global mod-2^32
// counter every time a new disassembler is created.

mozilla::Atomic<uint32_t> DisassemblerSpew::counter_(0);
#endif

DisassemblerSpew::DisassemblerSpew()
    : printer_(nullptr)
#ifdef JS_DISASM_SUPPORTED
      ,
      labelIndent_(""),
      targetIndent_(""),
      spewNext_(1000),
      nodes_(nullptr),
      tag_(0)
#endif
{
#ifdef JS_DISASM_SUPPORTED
  tag_ = counter_++;
#endif
}

DisassemblerSpew::~DisassemblerSpew() {
#ifdef JS_DISASM_SUPPORTED
  Node* p = nodes_;
  while (p) {
    Node* victim = p;
    p = p->next;
    js_free(victim);
  }
#endif
}

void DisassemblerSpew::setPrinter(Sprinter* printer) { printer_ = printer; }

bool DisassemblerSpew::isDisabled() {
  return !(JitSpewEnabled(JitSpew_Codegen) || printer_);
}

void DisassemblerSpew::spew(const char* fmt, ...) {
#ifdef JS_DISASM_SUPPORTED
  static const char prefix_chars[] =
      "0123456789"
      "abcdefghijklmnopqrstuvwxyz"
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  static const char prefix_fmt[] = "[%c] ";

  char fmt2[1024];
  if (sizeof(fmt2) >= strlen(fmt) + sizeof(prefix_fmt)) {
    snprintf(fmt2, sizeof(prefix_fmt), prefix_fmt,
             prefix_chars[tag_ % (sizeof(prefix_chars) - 1)]);
    strcat(fmt2, fmt);
    fmt = fmt2;
  }
#endif

  va_list args;
  va_start(args, fmt);
  spewVA(fmt, args);
  va_end(args);
}

void DisassemblerSpew::spewVA(const char* fmt, va_list va) {
  if (printer_) {
    printer_->vprintf(fmt, va);
    printer_->put("\n");
  }
  js::jit::JitSpewVA(js::jit::JitSpew_Codegen, fmt, va);
}

#ifdef JS_DISASM_SUPPORTED

void DisassemblerSpew::setLabelIndent(const char* s) { labelIndent_ = s; }

void DisassemblerSpew::setTargetIndent(const char* s) { targetIndent_ = s; }

DisassemblerSpew::LabelDoc DisassemblerSpew::refLabel(const Label* l) {
  return l ? LabelDoc(internalResolve(l), l->bound()) : LabelDoc();
}

void DisassemblerSpew::spewRef(const LabelDoc& target) {
  if (isDisabled()) {
    return;
  }
  if (!target.valid) {
    return;
  }
  spew("%s-> %d%s", targetIndent_, target.doc, !target.bound ? "f" : "");
}

void DisassemblerSpew::spewBind(const Label* label) {
  if (isDisabled()) {
    return;
  }
  uint32_t v = internalResolve(label);
  Node* probe = lookup(label);
  if (probe) {
    probe->bound = true;
  }
  spew("%s%d:", labelIndent_, v);
}

void DisassemblerSpew::spewRetarget(const Label* label, const Label* target) {
  if (isDisabled()) {
    return;
  }
  LabelDoc labelDoc = LabelDoc(internalResolve(label), label->bound());
  LabelDoc targetDoc = LabelDoc(internalResolve(target), target->bound());
  Node* probe = lookup(label);
  if (probe) {
    probe->bound = true;
  }
  spew("%s%d: .retarget -> %d%s", labelIndent_, labelDoc.doc, targetDoc.doc,
       !targetDoc.bound ? "f" : "");
}

void DisassemblerSpew::formatLiteral(const LiteralDoc& doc, char* buffer,
                                     size_t bufsize) {
  switch (doc.type) {
    case LiteralDoc::Type::Patchable:
      snprintf(buffer, bufsize, "patchable");
      break;
    case LiteralDoc::Type::I32:
      snprintf(buffer, bufsize, "%d", doc.value.i32);
      break;
    case LiteralDoc::Type::U32:
      snprintf(buffer, bufsize, "%u", doc.value.u32);
      break;
    case LiteralDoc::Type::I64:
      snprintf(buffer, bufsize, "%" PRIi64, doc.value.i64);
      break;
    case LiteralDoc::Type::U64:
      snprintf(buffer, bufsize, "%" PRIu64, doc.value.u64);
      break;
    case LiteralDoc::Type::F32:
      snprintf(buffer, bufsize, "%g", doc.value.f32);
      break;
    case LiteralDoc::Type::F64:
      snprintf(buffer, bufsize, "%g", doc.value.f64);
      break;
    default:
      MOZ_CRASH();
  }
}

void DisassemblerSpew::spewOrphans() {
  for (Node* p = nodes_; p; p = p->next) {
    if (!p->bound) {
      spew("%s%d: ; .orphan", labelIndent_, p->value);
    }
  }
}

uint32_t DisassemblerSpew::internalResolve(const Label* l) {
  // Note, internalResolve will sometimes return 0 when it is triggered by the
  // profiler and not by a full disassembly, since in that case a label can be
  // used or bound but not previously have been defined.  In that case,
  // internalResolve(l) will not necessarily create a binding for l!
  // Consequently a subsequent lookup(l) may still return null.
  return l->used() || l->bound() ? probe(l) : define(l);
}

uint32_t DisassemblerSpew::probe(const Label* l) {
  Node* n = lookup(l);
  return n ? n->value : 0;
}

uint32_t DisassemblerSpew::define(const Label* l) {
  remove(l);
  uint32_t value = spewNext_++;
  if (!add(l, value)) {
    return 0;
  }
  return value;
}

DisassemblerSpew::Node* DisassemblerSpew::lookup(const Label* key) {
  Node* p;
  for (p = nodes_; p && p->key != key; p = p->next) {
    ;
  }
  return p;
}

DisassemblerSpew::Node* DisassemblerSpew::add(const Label* key,
                                              uint32_t value) {
  MOZ_ASSERT(!lookup(key));
  Node* node = js_new<Node>();
  if (node) {
    node->key = key;
    node->value = value;
    node->bound = false;
    node->next = nodes_;
    nodes_ = node;
  }
  return node;
}

bool DisassemblerSpew::remove(const Label* key) {
  // We do not require that there is a node matching the key.
  for (Node *p = nodes_, *pp = nullptr; p; pp = p, p = p->next) {
    if (p->key == key) {
      if (pp) {
        pp->next = p->next;
      } else {
        nodes_ = p->next;
      }
      js_free(p);
      return true;
    }
  }
  return false;
}

#else

DisassemblerSpew::LabelDoc DisassemblerSpew::refLabel(const Label* l) {
  return LabelDoc();
}

#endif

Messung V0.5
C=93 H=93 G=92

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.