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

Quelle  JitcodeMap.h   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/. */


#ifndef jit_JitcodeMap_h
#define jit_JitcodeMap_h

#include "mozilla/Assertions.h"  // MOZ_ASSERT, MOZ_ASSERT_IF, MOZ_CRASH

#include <stddef.h>  // size_t
#include <stdint.h>  // uint8_t, uint32_t, uint64_t

#include "ds/AvlTree.h"         // AvlTree
#include "jit/CompactBuffer.h"  // CompactBufferReader, CompactBufferWriter
#include "jit/shared/Assembler-shared.h"  // CodeOffset
#include "js/AllocPolicy.h"               // SystemAllocPolicy
#include "js/TypeDecls.h"                 // jsbytecode
#include "js/Vector.h"                    // Vector
#include "vm/BytecodeLocation.h"          // BytecodeLocation

class JSScript;
class JSTracer;
struct JSRuntime;

namespace JS {
class Zone;
}  // namespace JS

namespace js {

class GCMarker;

namespace jit {

class InlineScriptTree;

/*
 * The jitcode map implements tables to allow mapping from addresses in jitcode
 * to the list of (JSScript*, jsbytecode*) pairs that are implicitly active in
 * the frame at that point in the native code.
 *
 * To represent this information efficiently, a multi-level table is used.
 *
 * At the top level, a global AVL-tree of JitcodeGlobalEntry describing the
 * mapping for each individual JitCode generated by compiles.  The entries are
 * ordered by their nativeStartAddr.
 *
 * Every entry in the table is of fixed size, but there are different entry
 * types, distinguished by the kind field.
 */


class JitcodeGlobalTable;
class JitcodeIonTable;
class JitcodeRegionEntry;

struct NativeToBytecode {
  CodeOffset nativeOffset;
  InlineScriptTree* tree;
  jsbytecode* pc;
};

// Describes range [start, end) of JIT-generated code.
class JitCodeRange {
 protected:
  voidconst nativeStartAddr_;
  voidconst nativeEndAddr_;

 public:
  JitCodeRange(void* start, void* end)
      : nativeStartAddr_(start), nativeEndAddr_(end) {
    MOZ_ASSERT(start < end);
  }

  // Comparator used by the AvlTree.
  static int compare(const JitCodeRange* r1, const JitCodeRange* r2) {
    // JitCodeRange includes 'start' but excludes 'end'.
    if (r1->nativeEndAddr_ <= r2->nativeStartAddr_) {
      return -1;
    }
    if (r1->nativeStartAddr_ >= r2->nativeEndAddr_) {
      return 1;
    }
    return 0;
  }

  void* nativeStartAddr() const { return nativeStartAddr_; }
  void* nativeEndAddr() const { return nativeEndAddr_; }

  bool containsPointer(void* ptr) const {
    return nativeStartAddr() <= ptr && ptr < nativeEndAddr();
  }
};

using BytecodeLocationVector = Vector<BytecodeLocation, 0, SystemAllocPolicy>;

class IonEntry;
class IonICEntry;
class BaselineEntry;
class BaselineInterpreterEntry;
class DummyEntry;

// Base class for all entries.
class JitcodeGlobalEntry : public JitCodeRange {
 protected:
  JitCode* jitcode_;
  // If this entry is referenced from the profiler buffer, this is the
  // position where the most recent sample that references it starts.
  // Otherwise set to kNoSampleInBuffer.
  static const uint64_t kNoSampleInBuffer = UINT64_MAX;
  uint64_t samplePositionInBuffer_ = kNoSampleInBuffer;

 public:
  enum class Kind : uint8_t {
    Ion,
    IonIC,
    Baseline,
    BaselineInterpreter,
    Dummy
  };

 protected:
  Kind kind_;

  JitcodeGlobalEntry(Kind kind, JitCode* code, void* nativeStartAddr,
                     void* nativeEndAddr)
      : JitCodeRange(nativeStartAddr, nativeEndAddr),
        jitcode_(code),
        kind_(kind) {
    MOZ_ASSERT(code);
    MOZ_ASSERT(nativeStartAddr);
    MOZ_ASSERT(nativeEndAddr);
  }

  // Protected destructor to ensure this is called through DestroyPolicy.
  ~JitcodeGlobalEntry() = default;

  JitcodeGlobalEntry(const JitcodeGlobalEntry& other) = delete;
  void operator=(const JitcodeGlobalEntry& other) = delete;

 public:
  struct DestroyPolicy {
    void operator()(JitcodeGlobalEntry* entry);
  };

  void setSamplePositionInBuffer(uint64_t bufferWritePos) {
    samplePositionInBuffer_ = bufferWritePos;
  }
  void setAsExpired() { samplePositionInBuffer_ = kNoSampleInBuffer; }
  bool isSampled(uint64_t bufferRangeStart) {
    if (samplePositionInBuffer_ == kNoSampleInBuffer) {
      return false;
    }
    return bufferRangeStart <= samplePositionInBuffer_;
  }

  Kind kind() const { return kind_; }
  bool isIon() const { return kind() == Kind::Ion; }
  bool isIonIC() const { return kind() == Kind::IonIC; }
  bool isBaseline() const { return kind() == Kind::Baseline; }
  bool isBaselineInterpreter() const {
    return kind() == Kind::BaselineInterpreter;
  }
  bool isDummy() const { return kind() == Kind::Dummy; }

  inline const IonEntry& asIon() const;
  inline const IonICEntry& asIonIC() const;
  inline const BaselineEntry& asBaseline() const;
  inline const BaselineInterpreterEntry& asBaselineInterpreter() const;
  inline const DummyEntry& asDummy() const;

  inline IonEntry& asIon();
  inline IonICEntry& asIonIC();
  inline BaselineEntry& asBaseline();
  inline BaselineInterpreterEntry& asBaselineInterpreter();
  inline DummyEntry& asDummy();

  JitCode* jitcode() const { return jitcode_; }
  JitCode** jitcodePtr() { return &jitcode_; }
  Zone* zone() const { return jitcode()->zone(); }

  bool traceJitcode(JSTracer* trc);
  bool isJitcodeMarkedFromAnyThread(JSRuntime* rt);

  bool trace(JSTracer* trc);
  void traceWeak(JSTracer* trc);
  uint64_t lookupRealmID(JSRuntime* rt, void* ptr) const;
  void* canonicalNativeAddrFor(JSRuntime* rt, void* ptr) const;

  // Read the inline call stack at a given point in the native code and append
  // into the given vector.  Innermost (script,pc) pair will be appended first,
  // and outermost appended last.
  //
  // Returns false on memory failure.
  [[nodiscard]] bool callStackAtAddr(JSRuntime* rt, void* ptr,
                                     BytecodeLocationVector& results,
                                     uint32_t* depth) const;
  uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** results,
                           uint32_t maxResults) const;
};

using UniqueJitcodeGlobalEntry =
    UniquePtr<JitcodeGlobalEntry, JitcodeGlobalEntry::DestroyPolicy>;

template <typename T, typename... Args>
inline UniqueJitcodeGlobalEntry MakeJitcodeGlobalEntry(JSContext* cx,
                                                       Args&&... args) {
  UniqueJitcodeGlobalEntry res(js_new<T>(std::forward<Args>(args)...));
  if (!res) {
    ReportOutOfMemory(cx);
  }
  return res;
}

class IonEntry : public JitcodeGlobalEntry {
 public:
  struct ScriptNamePair {
    JSScript* script;
    UniqueChars str;
    ScriptNamePair(JSScript* script, UniqueChars str)
        : script(script), str(std::move(str)) {}
  };
  using ScriptList = Vector<ScriptNamePair, 2, SystemAllocPolicy>;

 private:
  ScriptList scriptList_;

  // regionTable_ points to the start of the region table within the
  // packed map for compile represented by this entry.  Since the
  // region table occurs at the tail of the memory region, this pointer
  // points somewhere inside the region memory space, and not to the start
  // of the memory space.
  const JitcodeIonTable* regionTable_;

 public:
  IonEntry(JitCode* code, void* nativeStartAddr, void* nativeEndAddr,
           ScriptList&& scriptList, JitcodeIonTable* regionTable)
      : JitcodeGlobalEntry(Kind::Ion, code, nativeStartAddr, nativeEndAddr),
        scriptList_(std::move(scriptList)),
        regionTable_(regionTable) {
    MOZ_ASSERT(regionTable);
  }

  ~IonEntry();

  ScriptList& scriptList() { return scriptList_; }

  size_t numScripts() const { return scriptList_.length(); }

  JSScript* getScript(unsigned idx) const {
    MOZ_ASSERT(idx < numScripts());
    return scriptList_[idx].script;
  }

  const char* getStr(unsigned idx) const {
    MOZ_ASSERT(idx < numScripts());
    return scriptList_[idx].str.get();
  }

  const JitcodeIonTable* regionTable() const { return regionTable_; }

  void* canonicalNativeAddrFor(void* ptr) const;

  [[nodiscard]] bool callStackAtAddr(void* ptr, BytecodeLocationVector& results,
                                     uint32_t* depth) const;

  uint32_t callStackAtAddr(void* ptr, const char** results,
                           uint32_t maxResults) const;

  uint64_t lookupRealmID(void* ptr) const;

  bool trace(JSTracer* trc);
  void traceWeak(JSTracer* trc);
};

class IonICEntry : public JitcodeGlobalEntry {
  // Address for this IC in the IonScript code. Most operations on IonICEntry
  // use this to forward to the IonEntry.
  void* rejoinAddr_;

 public:
  IonICEntry(JitCode* code, void* nativeStartAddr, void* nativeEndAddr,
             void* rejoinAddr)
      : JitcodeGlobalEntry(Kind::IonIC, code, nativeStartAddr, nativeEndAddr),
        rejoinAddr_(rejoinAddr) {
    MOZ_ASSERT(rejoinAddr_);
  }

  void* rejoinAddr() const { return rejoinAddr_; }

  void* canonicalNativeAddrFor(void* ptr) const;

  [[nodiscard]] bool callStackAtAddr(JSRuntime* rt, void* ptr,
                                     BytecodeLocationVector& results,
                                     uint32_t* depth) const;

  uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** results,
                           uint32_t maxResults) const;

  uint64_t lookupRealmID(JSRuntime* rt, void* ptr) const;

  bool trace(JSTracer* trc);
  void traceWeak(JSTracer* trc);
};

class BaselineEntry : public JitcodeGlobalEntry {
  JSScript* script_;
  UniqueChars str_;

 public:
  BaselineEntry(JitCode* code, void* nativeStartAddr, void* nativeEndAddr,
                JSScript* script, UniqueChars str)
      : JitcodeGlobalEntry(Kind::Baseline, code, nativeStartAddr,
                           nativeEndAddr),
        script_(script),
        str_(std::move(str)) {
    MOZ_ASSERT(script_);
    MOZ_ASSERT(str_);
  }

  JSScript* script() const { return script_; }

  const char* str() const { return str_.get(); }

  void* canonicalNativeAddrFor(void* ptr) const;

  [[nodiscard]] bool callStackAtAddr(void* ptr, BytecodeLocationVector& results,
                                     uint32_t* depth) const;

  uint32_t callStackAtAddr(void* ptr, const char** results,
                           uint32_t maxResults) const;

  uint64_t lookupRealmID() const;

  bool trace(JSTracer* trc);
  void traceWeak(JSTracer* trc);
};

class BaselineInterpreterEntry : public JitcodeGlobalEntry {
 public:
  BaselineInterpreterEntry(JitCode* code, void* nativeStartAddr,
                           void* nativeEndAddr)
      : JitcodeGlobalEntry(Kind::BaselineInterpreter, code, nativeStartAddr,
                           nativeEndAddr) {}

  void* canonicalNativeAddrFor(void* ptr) const;

  [[nodiscard]] bool callStackAtAddr(void* ptr, BytecodeLocationVector& results,
                                     uint32_t* depth) const;

  uint32_t callStackAtAddr(void* ptr, const char** results,
                           uint32_t maxResults) const;

  uint64_t lookupRealmID() const;
};

// Dummy entries are created for jitcode generated when profiling is not
// turned on, so that they have representation in the global table if they are
// on the stack when profiling is enabled.
class DummyEntry : public JitcodeGlobalEntry {
 public:
  DummyEntry(JitCode* code, void* nativeStartAddr, void* nativeEndAddr)
      : JitcodeGlobalEntry(Kind::Dummy, code, nativeStartAddr, nativeEndAddr) {}

  void* canonicalNativeAddrFor(JSRuntime* rt, void* ptr) const {
    return nullptr;
  }

  [[nodiscard]] bool callStackAtAddr(JSRuntime* rt, void* ptr,
                                     BytecodeLocationVector& results,
                                     uint32_t* depth) const {
    return true;
  }

  uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** results,
                           uint32_t maxResults) const {
    return 0;
  }

  uint64_t lookupRealmID() const { return 0; }
};

inline const IonEntry& JitcodeGlobalEntry::asIon() const {
  MOZ_ASSERT(isIon());
  return *static_cast<const IonEntry*>(this);
}

inline const IonICEntry& JitcodeGlobalEntry::asIonIC() const {
  MOZ_ASSERT(isIonIC());
  return *static_cast<const IonICEntry*>(this);
}

inline const BaselineEntry& JitcodeGlobalEntry::asBaseline() const {
  MOZ_ASSERT(isBaseline());
  return *static_cast<const BaselineEntry*>(this);
}

inline const BaselineInterpreterEntry&
JitcodeGlobalEntry::asBaselineInterpreter() const {
  MOZ_ASSERT(isBaselineInterpreter());
  return *static_cast<const BaselineInterpreterEntry*>(this);
}

inline const DummyEntry& JitcodeGlobalEntry::asDummy() const {
  MOZ_ASSERT(isDummy());
  return *static_cast<const DummyEntry*>(this);
}

inline IonEntry& JitcodeGlobalEntry::asIon() {
  MOZ_ASSERT(isIon());
  return *static_cast<IonEntry*>(this);
}

inline IonICEntry& JitcodeGlobalEntry::asIonIC() {
  MOZ_ASSERT(isIonIC());
  return *static_cast<IonICEntry*>(this);
}

inline BaselineEntry& JitcodeGlobalEntry::asBaseline() {
  MOZ_ASSERT(isBaseline());
  return *static_cast<BaselineEntry*>(this);
}

inline BaselineInterpreterEntry& JitcodeGlobalEntry::asBaselineInterpreter() {
  MOZ_ASSERT(isBaselineInterpreter());
  return *static_cast<BaselineInterpreterEntry*>(this);
}

inline DummyEntry& JitcodeGlobalEntry::asDummy() {
  MOZ_ASSERT(isDummy());
  return *static_cast<DummyEntry*>(this);
}

// Global table of JitcodeGlobalEntry entries.
class JitcodeGlobalTable {
 private:
  // Vector containing (and owning) all entries. This is unsorted and used for
  // iterating over all entries, because the AvlTree currently doesn't support
  // modifications while iterating.
  using EntryVector = Vector<UniqueJitcodeGlobalEntry, 0, SystemAllocPolicy>;
  EntryVector entries_;

  // AVL tree containing all entries in the Vector above. This is used to
  // efficiently look up the entry corresponding to a native code address.
  using EntryTree = AvlTree<JitCodeRange*, JitCodeRange>;
  static const size_t LIFO_CHUNK_SIZE = 16 * 1024;
  LifoAlloc alloc_;
  EntryTree tree_;

 public:
  JitcodeGlobalTable()
      : alloc_(LIFO_CHUNK_SIZE, js::BackgroundMallocArena), tree_(&alloc_) {}

  bool empty() const {
    MOZ_ASSERT(entries_.empty() == tree_.empty());
    return entries_.empty();
  }

  JitcodeGlobalEntry* lookup(void* ptr) { return lookupInternal(ptr); }

  const JitcodeGlobalEntry* lookupForSampler(void* ptr, JSRuntime* rt,
                                             uint64_t samplePosInBuffer);

  [[nodiscard]] bool addEntry(UniqueJitcodeGlobalEntry entry);

  void setAllEntriesAsExpired();
  [[nodiscard]] bool markIteratively(GCMarker* marker);
  void traceWeak(JSRuntime* rt, JSTracer* trc);

 private:
  JitcodeGlobalEntry* lookupInternal(void* ptr);
};

// clang-format off
/*
 * Container class for main jitcode table.
 * The Region table's memory is structured as follows:
 *
 *      +------------------------------------------------+   |
 *      |  Region 1 Run                                  |   |
 *      |------------------------------------------------|   |
 *      |  Region 2 Run                                  |   |
 *      |                                                |   |
 *      |                                                |   |
 *      |------------------------------------------------|   |
 *      |  Region 3 Run                                  |   |
 *      |                                                |   |
 *      |------------------------------------------------|   |-- Payload
 *      |                                                |   |
 *      |               ...                              |   |
 *      |                                                |   |
 *      |------------------------------------------------|   |
 *      |  Region M Run                                  |   |
 *      |                                                |   |
 *      +================================================+ <- RegionTable pointer points here
 *      | uint23_t numRegions = M                        |   |
 *      +------------------------------------------------+   |
 *      | Region 1                                       |   |
 *      |   uint32_t entryOffset = size(Payload)         |   |
 *      +------------------------------------------------+   |
 *      |                                                |   |-- Table
 *      |   ...                                          |   |
 *      |                                                |   |
 *      +------------------------------------------------+   |
 *      | Region M                                       |   |
 *      |   uint32_t entryOffset                         |   |
 *      +------------------------------------------------+   |
 *
 * The region table is composed of two sections: a tail section that contains a table of
 * fixed-size entries containing offsets into the the head section, and a head section that
 * holds a sequence of variable-sized runs.  The table in the tail section serves to
 * locate the variable-length encoded structures in the head section.
 *
 * The entryOffsets in the table indicate the bytes offset to subtract from the regionTable
 * pointer to arrive at the encoded region in the payload.
 *
 *
 * Variable-length entries in payload
 * ----------------------------------
 * The entryOffsets in the region table's fixed-sized entries refer to a location within the
 * variable-length payload section.  This location contains a compactly encoded "run" of
 * mappings.
 *
 * Each run starts by describing the offset within the native code it starts at, and the
 * sequence of (JSScript*, jsbytecode*) pairs active at that site.  Following that, there
 * are a number of variable-length entries encoding (nativeOffsetDelta, bytecodeOffsetDelta)
 * pairs for the run.
 *
 *      VarUint32 nativeOffset;
 *          - The offset from nativeStartAddr in the global table entry at which
 *            the jitcode for this region starts.
 *
 *      Uint8_t scriptDepth;
 *          - The depth of inlined scripts for this region.
 *
 *      List<VarUint32> inlineScriptPcStack;
 *          - We encode (2 * scriptDepth) VarUint32s here.  Each pair of uint32s are taken
 *            as an index into the scriptList in the global table entry, and a pcOffset
 *            respectively.
 *
 *      List<NativeAndBytecodeDelta> deltaRun;
 *          - The rest of the entry is a deltaRun that stores a series of variable-length
 *            encoded NativeAndBytecodeDelta datums.
 */

// clang-format on
class JitcodeRegionEntry {
 private:
  static const unsigned MAX_RUN_LENGTH = 100;

 public:
  static void WriteHead(CompactBufferWriter& writer, uint32_t nativeOffset,
                        uint8_t scriptDepth);
  static void ReadHead(CompactBufferReader& reader, uint32_t* nativeOffset,
                       uint8_t* scriptDepth);

  static void WriteScriptPc(CompactBufferWriter& writer, uint32_t scriptIdx,
                            uint32_t pcOffset);
  static void ReadScriptPc(CompactBufferReader& reader, uint32_t* scriptIdx,
                           uint32_t* pcOffset);

  static void WriteDelta(CompactBufferWriter& writer, uint32_t nativeDelta,
                         int32_t pcDelta);
  static void ReadDelta(CompactBufferReader& reader, uint32_t* nativeDelta,
                        int32_t* pcDelta);

  // Given a pointer into an array of NativeToBytecode (and a pointer to the end
  // of the array), compute the number of entries that would be consume by
  // outputting a run starting at this one.
  static uint32_t ExpectedRunLength(const NativeToBytecode* entry,
                                    const NativeToBytecode* end);

  // Write a run, starting at the given NativeToBytecode entry, into the given
  // buffer writer.
  [[nodiscard]] static bool WriteRun(CompactBufferWriter& writer,
                                     const IonEntry::ScriptList& scriptList,
                                     uint32_t runLength,
                                     const NativeToBytecode* entry);

  // Delta Run entry formats are encoded little-endian:
  //
  //  byte 0
  //  NNNN-BBB0
  //      Single byte format.  nativeDelta in [0, 15], pcDelta in [0, 7]
  //
  static const uint32_t ENC1_MASK = 0x1;
  static const uint32_t ENC1_MASK_VAL = 0x0;

  static const uint32_t ENC1_NATIVE_DELTA_MAX = 0xf;
  static const unsigned ENC1_NATIVE_DELTA_SHIFT = 4;

  static const uint32_t ENC1_PC_DELTA_MASK = 0x0e;
  static const int32_t ENC1_PC_DELTA_MAX = 0x7;
  static const unsigned ENC1_PC_DELTA_SHIFT = 1;

  //  byte 1    byte 0
  //  NNNN-NNNN BBBB-BB01
  //      Two-byte format.  nativeDelta in [0, 255], pcDelta in [0, 63]
  //
  static const uint32_t ENC2_MASK = 0x3;
  static const uint32_t ENC2_MASK_VAL = 0x1;

  static const uint32_t ENC2_NATIVE_DELTA_MAX = 0xff;
  static const unsigned ENC2_NATIVE_DELTA_SHIFT = 8;

  static const uint32_t ENC2_PC_DELTA_MASK = 0x00fc;
  static const int32_t ENC2_PC_DELTA_MAX = 0x3f;
  static const unsigned ENC2_PC_DELTA_SHIFT = 2;

  //  byte 2    byte 1    byte 0
  //  NNNN-NNNN NNNB-BBBB BBBB-B011
  //      Three-byte format.  nativeDelta in [0, 2047], pcDelta in [-512, 511]
  //
  static const uint32_t ENC3_MASK = 0x7;
  static const uint32_t ENC3_MASK_VAL = 0x3;

  static const uint32_t ENC3_NATIVE_DELTA_MAX = 0x7ff;
  static const unsigned ENC3_NATIVE_DELTA_SHIFT = 13;

  static const uint32_t ENC3_PC_DELTA_MASK = 0x001ff8;
  static const int32_t ENC3_PC_DELTA_MAX = 0x1ff;
  static const int32_t ENC3_PC_DELTA_MIN = -ENC3_PC_DELTA_MAX - 1;
  static const unsigned ENC3_PC_DELTA_SHIFT = 3;

  //  byte 3    byte 2    byte 1    byte 0
  //  NNNN-NNNN NNNN-NNNN BBBB-BBBB BBBB-B111
  //      Three-byte format.  nativeDelta in [0, 65535],
  //                          pcDelta in [-4096, 4095]
  static const uint32_t ENC4_MASK = 0x7;
  static const uint32_t ENC4_MASK_VAL = 0x7;

  static const uint32_t ENC4_NATIVE_DELTA_MAX = 0xffff;
  static const unsigned ENC4_NATIVE_DELTA_SHIFT = 16;

  static const uint32_t ENC4_PC_DELTA_MASK = 0x0000fff8;
  static const int32_t ENC4_PC_DELTA_MAX = 0xfff;
  static const int32_t ENC4_PC_DELTA_MIN = -ENC4_PC_DELTA_MAX - 1;
  static const unsigned ENC4_PC_DELTA_SHIFT = 3;

  static bool IsDeltaEncodeable(uint32_t nativeDelta, int32_t pcDelta) {
    return (nativeDelta <= ENC4_NATIVE_DELTA_MAX) &&
           (pcDelta >= ENC4_PC_DELTA_MIN) && (pcDelta <= ENC4_PC_DELTA_MAX);
  }

 private:
  const uint8_t* data_;
  const uint8_t* end_;

  // Unpacked state from jitcode entry.
  uint32_t nativeOffset_;
  uint8_t scriptDepth_;
  const uint8_t* scriptPcStack_;
  const uint8_t* deltaRun_;

  void unpack();

 public:
  JitcodeRegionEntry(const uint8_t* data, const uint8_t* end)
      : data_(data),
        end_(end),
        nativeOffset_(0),
        scriptDepth_(0),
        scriptPcStack_(nullptr),
        deltaRun_(nullptr) {
    MOZ_ASSERT(data_ < end_);
    unpack();
    MOZ_ASSERT(scriptPcStack_ < end_);
    MOZ_ASSERT(deltaRun_ <= end_);
  }

  uint32_t nativeOffset() const { return nativeOffset_; }
  uint32_t scriptDepth() const { return scriptDepth_; }

  class ScriptPcIterator {
   private:
    const uint8_t* start_;
    const uint8_t* end_;
#ifdef DEBUG
    uint32_t count_;
#endif
    uint32_t idx_;
    const uint8_t* cur_;

   public:
    ScriptPcIterator(const uint8_t* start, const uint8_t* end, uint32_t count)
        : start_(start),
          end_(end),
#ifdef DEBUG
          count_(count),
#endif
          idx_(0),
          cur_(start_) {
    }

    bool hasMore() const {
      MOZ_ASSERT((idx_ == count_) == (cur_ == end_));
      MOZ_ASSERT((idx_ < count_) == (cur_ < end_));
      return cur_ < end_;
    }

    void readNext(uint32_t* scriptIdxOut, uint32_t* pcOffsetOut) {
      MOZ_ASSERT(scriptIdxOut);
      MOZ_ASSERT(pcOffsetOut);
      MOZ_ASSERT(hasMore());

      CompactBufferReader reader(cur_, end_);
      ReadScriptPc(reader, scriptIdxOut, pcOffsetOut);

      cur_ = reader.currentPosition();
      MOZ_ASSERT(cur_ <= end_);

      idx_++;
      MOZ_ASSERT_IF(idx_ == count_, cur_ == end_);
    }

    void reset() {
      idx_ = 0;
      cur_ = start_;
    }
  };

  ScriptPcIterator scriptPcIterator() const {
    // End of script+pc sequence is the start of the delta run.
    return ScriptPcIterator(scriptPcStack_, deltaRun_, scriptDepth_);
  }

  class DeltaIterator {
   private:
    const uint8_t* start_;
    const uint8_t* end_;
    const uint8_t* cur_;

   public:
    DeltaIterator(const uint8_t* start, const uint8_t* end)
        : start_(start), end_(end), cur_(start) {}

    bool hasMore() const {
      MOZ_ASSERT(cur_ <= end_);
      return cur_ < end_;
    }

    void readNext(uint32_t* nativeDeltaOut, int32_t* pcDeltaOut) {
      MOZ_ASSERT(nativeDeltaOut != nullptr);
      MOZ_ASSERT(pcDeltaOut != nullptr);

      MOZ_ASSERT(hasMore());

      CompactBufferReader reader(cur_, end_);
      ReadDelta(reader, nativeDeltaOut, pcDeltaOut);

      cur_ = reader.currentPosition();
      MOZ_ASSERT(cur_ <= end_);
    }

    void reset() { cur_ = start_; }
  };
  DeltaIterator deltaIterator() const { return DeltaIterator(deltaRun_, end_); }

  uint32_t findPcOffset(uint32_t queryNativeOffset,
                        uint32_t startPcOffset) const;
};

class JitcodeIonTable {
 private:
  /* Variable length payload section "below" here. */
  uint32_t numRegions_;
  uint32_t regionOffsets_[1];

  const uint8_t* payloadEnd() const {
    return reinterpret_cast<const uint8_t*>(this);
  }

 public:
  JitcodeIonTable() = delete;

  uint32_t numRegions() const { return numRegions_; }

  uint32_t regionOffset(uint32_t regionIndex) const {
    MOZ_ASSERT(regionIndex < numRegions());
    return regionOffsets_[regionIndex];
  }

  JitcodeRegionEntry regionEntry(uint32_t regionIndex) const {
    const uint8_t* regionStart = payloadEnd() - regionOffset(regionIndex);
    const uint8_t* regionEnd = payloadEnd();
    if (regionIndex < numRegions_ - 1) {
      regionEnd -= regionOffset(regionIndex + 1);
    }
    return JitcodeRegionEntry(regionStart, regionEnd);
  }

  uint32_t findRegionEntry(uint32_t offset) const;

  const uint8_t* payloadStart() const {
    // The beginning of the payload the beginning of the first region are the
    // same.
    return payloadEnd() - regionOffset(0);
  }

  [[nodiscard]] static bool WriteIonTable(
      CompactBufferWriter& writer, const IonEntry::ScriptList& scriptList,
      const NativeToBytecode* start, const NativeToBytecode* end,
      uint32_t* tableOffsetOut, uint32_t* numRegionsOut);
};

}  // namespace jit
}  // namespace js

#endif /* jit_JitcodeMap_h */

Messung V0.5
C=88 H=97 G=92

¤ Dauer der Verarbeitung: 0.14 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.