tor-browser

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

JitCode.h (6163B)


      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 #ifndef jit_JitCode_h
      8 #define jit_JitCode_h
      9 
     10 #include "mozilla/MemoryReporting.h"  // MallocSizeOf
     11 
     12 #include <stddef.h>  // size_t
     13 #include <stdint.h>  // uint8_t, uint32_t
     14 
     15 #include "jstypes.h"
     16 
     17 #include "gc/Cell.h"       // gc::TenuredCellWithNonGCPointer
     18 #include "gc/GCEnum.h"     // AllowGC
     19 #include "js/TraceKind.h"  // JS::TraceKind
     20 #include "js/UbiNode.h"    // ubi::{TracerConcrete, Size, CourseType}
     21 
     22 namespace js {
     23 namespace jit {
     24 
     25 class ExecutablePool;
     26 class JitCode;
     27 class MacroAssembler;
     28 
     29 enum class CodeKind : uint8_t;
     30 
     31 // Header at start of raw code buffer
     32 struct JitCodeHeader {
     33  // Link back to corresponding gcthing
     34  JitCode* jitCode_;
     35 
     36  void init(JitCode* jitCode);
     37 
     38  static JitCodeHeader* FromExecutable(uint8_t* buffer) {
     39    return (JitCodeHeader*)(buffer - sizeof(JitCodeHeader));
     40  }
     41 };
     42 
     43 class JitCode : public gc::TenuredCellWithNonGCPointer<uint8_t> {
     44  friend class gc::CellAllocator;
     45 
     46 public:
     47  // Raw code pointer, stored in the cell header.
     48  uint8_t* raw() const { return headerPtr(); }
     49 
     50  // Raw pointer to the allocated memory to be able to modify the JitCodePointer
     51  // which is stored above the code.
     52  uint8_t* allocatedMemory() const { return headerPtr() - headerSize_; }
     53 
     54 protected:
     55  ExecutablePool* pool_;
     56  uint32_t bufferSize_;  // Total buffer size. Does not include headerSize_.
     57  uint32_t insnSize_;    // Instruction stream size.
     58  uint32_t dataSize_;    // Size of the read-only data area.
     59  uint32_t jumpRelocTableBytes_;  // Size of the jump relocation table.
     60  uint32_t dataRelocTableBytes_;  // Size of the data relocation table.
     61  uint8_t headerSize_ : 5;        // Number of bytes allocated before codeStart.
     62  uint8_t kind_ : 3;              // jit::CodeKind, for the memory reporters.
     63  bool invalidated_ : 1;     // Whether the code object has been invalidated.
     64                             // This is necessary to prevent GC tracing.
     65  bool hasBytecodeMap_ : 1;  // Whether the code object has been registered with
     66                             // native=>bytecode mapping tables.
     67  uint8_t localTracingSlots_;
     68 
     69  JitCode() = delete;
     70  JitCode(uint8_t* code, uint32_t bufferSize, uint32_t headerSize,
     71          ExecutablePool* pool, CodeKind kind)
     72      : TenuredCellWithNonGCPointer(code),
     73        pool_(pool),
     74        bufferSize_(bufferSize),
     75        insnSize_(0),
     76        dataSize_(0),
     77        jumpRelocTableBytes_(0),
     78        dataRelocTableBytes_(0),
     79        headerSize_(headerSize),
     80        kind_(uint8_t(kind)),
     81        invalidated_(false),
     82        hasBytecodeMap_(false),
     83        localTracingSlots_(0) {
     84    MOZ_ASSERT(CodeKind(kind_) == kind);
     85    MOZ_ASSERT(headerSize_ == headerSize);
     86  }
     87 
     88  uint32_t dataOffset() const { return insnSize_; }
     89  uint32_t jumpRelocTableOffset() const { return dataOffset() + dataSize_; }
     90  uint32_t dataRelocTableOffset() const {
     91    return jumpRelocTableOffset() + jumpRelocTableBytes_;
     92  }
     93 
     94 public:
     95  uint8_t* rawEnd() const { return raw() + insnSize_; }
     96  bool containsNativePC(const void* addr) const {
     97    const uint8_t* addr_u8 = (const uint8_t*)addr;
     98    return raw() <= addr_u8 && addr_u8 < rawEnd();
     99  }
    100  size_t instructionsSize() const { return insnSize_; }
    101  size_t bufferSize() const { return bufferSize_; }
    102  size_t headerSize() const { return headerSize_; }
    103  size_t allocatedSize() const { return bufferSize_ + headerSize_; }
    104 
    105  void traceChildren(JSTracer* trc);
    106  void finalize(JS::GCContext* gcx);
    107  void setInvalidated() { invalidated_ = true; }
    108 
    109  void setHasBytecodeMap() { hasBytecodeMap_ = true; }
    110 
    111  void setLocalTracingSlots(uint8_t localTracingSlots) {
    112    localTracingSlots_ = localTracingSlots;
    113  }
    114 
    115  uint8_t localTracingSlots() { return localTracingSlots_; }
    116 
    117  // If this JitCode object has been, effectively, corrupted due to
    118  // invalidation patching, then we have to remember this so we don't try and
    119  // trace relocation entries that may now be corrupt.
    120  bool invalidated() const { return !!invalidated_; }
    121 
    122  template <typename T>
    123  T as() const {
    124    return JS_DATA_TO_FUNC_PTR(T, raw());
    125  }
    126 
    127  void copyFrom(MacroAssembler& masm);
    128 
    129  static JitCode* FromExecutable(uint8_t* buffer) {
    130    JitCode* code = JitCodeHeader::FromExecutable(buffer)->jitCode_;
    131    MOZ_ASSERT(code->raw() == buffer);
    132    return code;
    133  }
    134 
    135  static size_t offsetOfCode() { return offsetOfHeaderPtr(); }
    136 
    137  uint8_t* jumpRelocTable() { return raw() + jumpRelocTableOffset(); }
    138 
    139  // Allocates a new JitCode object which will be managed by the GC. If no
    140  // object can be allocated, nullptr is returned. On failure, |pool| is
    141  // automatically released, so the code may be freed.
    142  template <AllowGC allowGC>
    143  static JitCode* New(JSContext* cx, uint8_t* code, uint32_t totalSize,
    144                      uint32_t headerSize, ExecutablePool* pool, CodeKind kind);
    145 
    146 public:
    147  static const JS::TraceKind TraceKind = JS::TraceKind::JitCode;
    148 };
    149 
    150 }  // namespace jit
    151 }  // namespace js
    152 
    153 // JS::ubi::Nodes can point to js::jit::JitCode instances; they're js::gc::Cell
    154 // instances with no associated compartment.
    155 namespace JS {
    156 namespace ubi {
    157 template <>
    158 class Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> {
    159 protected:
    160  explicit Concrete(js::jit::JitCode* ptr)
    161      : TracerConcrete<js::jit::JitCode>(ptr) {}
    162 
    163 public:
    164  static void construct(void* storage, js::jit::JitCode* ptr) {
    165    new (storage) Concrete(ptr);
    166  }
    167 
    168  CoarseType coarseType() const final { return CoarseType::Script; }
    169 
    170  Size size(mozilla::MallocSizeOf mallocSizeOf) const override {
    171    Size size = js::gc::Arena::thingSize(get().asTenured().getAllocKind());
    172    size += get().bufferSize();
    173    size += get().headerSize();
    174    return size;
    175  }
    176 
    177  const char16_t* typeName() const override { return concreteTypeName; }
    178  static const char16_t concreteTypeName[];
    179 };
    180 
    181 }  // namespace ubi
    182 }  // namespace JS
    183 
    184 #endif /* jit_JitCode_h */