tor-browser

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

BaselineJIT.h (21157B)


      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_BaselineJIT_h
      8 #define jit_BaselineJIT_h
      9 
     10 #include "mozilla/Assertions.h"
     11 #include "mozilla/Likely.h"
     12 #include "mozilla/Maybe.h"
     13 #include "mozilla/MemoryReporting.h"
     14 #include "mozilla/Span.h"
     15 
     16 #include <stddef.h>
     17 #include <stdint.h>
     18 
     19 #include "jsfriendapi.h"
     20 
     21 #include "jit/IonTypes.h"
     22 #include "jit/JitCode.h"
     23 #include "jit/JitContext.h"
     24 #include "jit/JitOptions.h"
     25 #include "jit/shared/Assembler-shared.h"
     26 #include "js/Principals.h"
     27 #include "js/TypeDecls.h"
     28 #include "js/Vector.h"
     29 #include "threading/ProtectedData.h"
     30 #include "util/TrailingArray.h"
     31 #include "vm/JSScript.h"
     32 
     33 namespace js {
     34 
     35 class InterpreterFrame;
     36 class RunState;
     37 
     38 namespace jit {
     39 
     40 class BaselineFrame;
     41 class ExceptionBailoutInfo;
     42 class IonCompileTask;
     43 class JitActivation;
     44 class JSJitFrameIter;
     45 
     46 // Base class for entries mapping a pc offset to a native code offset.
     47 class BasePCToNativeEntry {
     48  uint32_t pcOffset_;
     49  uint32_t nativeOffset_;
     50 
     51 public:
     52  BasePCToNativeEntry(uint32_t pcOffset, uint32_t nativeOffset)
     53      : pcOffset_(pcOffset), nativeOffset_(nativeOffset) {}
     54  uint32_t pcOffset() const { return pcOffset_; }
     55  uint32_t nativeOffset() const { return nativeOffset_; }
     56 };
     57 
     58 // Class used during Baseline compilation to store the native code offset for
     59 // resume offset ops.
     60 class ResumeOffsetEntry : public BasePCToNativeEntry {
     61 public:
     62  using BasePCToNativeEntry::BasePCToNativeEntry;
     63 };
     64 
     65 using ResumeOffsetEntryVector =
     66    Vector<ResumeOffsetEntry, 16, SystemAllocPolicy>;
     67 
     68 // Largest script that the baseline compiler will attempt to compile.
     69 #if defined(JS_CODEGEN_ARM)
     70 // ARM branches can only reach 32MB, and the macroassembler doesn't mitigate
     71 // that limitation. Use a stricter limit on the acceptable script size to
     72 // avoid crashing when branches go out of range.
     73 static constexpr uint32_t BaselineMaxScriptLength = 1000000u;
     74 #else
     75 static constexpr uint32_t BaselineMaxScriptLength = 0x0fffffffu;
     76 #endif
     77 
     78 // Limit the locals on a given script so that stack check on baseline frames
     79 // doesn't overflow a uint32_t value.
     80 // (BaselineMaxScriptSlots * sizeof(Value)) must fit within a uint32_t.
     81 //
     82 // This also applies to the Baseline Interpreter: it ensures we don't run out
     83 // of stack space (and throw over-recursion exceptions) for scripts with a huge
     84 // number of locals. The C++ interpreter avoids this by having heap-allocated
     85 // stack frames.
     86 static constexpr uint32_t BaselineMaxScriptSlots = 0xffffu;
     87 
     88 // An entry in the BaselineScript return address table. These entries are used
     89 // to determine the bytecode pc for a return address into Baseline code.
     90 //
     91 // There must be an entry for each location where we can end up calling into
     92 // C++ (directly or via script/trampolines) and C++ can request the current
     93 // bytecode pc (this includes anything that may throw an exception, GC, or walk
     94 // the stack). We currently add entries for each:
     95 //
     96 // * callVM
     97 // * IC
     98 // * DebugTrap (trampoline call)
     99 // * JSOp::Resume (because this is like a scripted call)
    100 //
    101 // Note: see also BaselineFrame::HAS_OVERRIDE_PC.
    102 class RetAddrEntry {
    103  // Offset from the start of the JIT code where call instruction is.
    104  uint32_t returnOffset_;
    105 
    106  // The offset of this bytecode op within the JSScript.
    107  uint32_t pcOffset_ : 28;
    108 
    109 public:
    110  enum class Kind : uint32_t {
    111    // An IC for a JOF_IC op.
    112    IC,
    113 
    114    // A callVM for an op.
    115    CallVM,
    116 
    117    // A callVM not for an op (e.g., in the prologue) that can't
    118    // trigger debug mode.
    119    NonOpCallVM,
    120 
    121    // A callVM for the over-recursion check on function entry.
    122    StackCheck,
    123 
    124    // A callVM for an interrupt check.
    125    InterruptCheck,
    126 
    127    // DebugTrapHandler (for debugger breakpoints/stepping).
    128    DebugTrap,
    129 
    130    // A callVM for Debug{Prologue,AfterYield,Epilogue}.
    131    DebugPrologue,
    132    DebugAfterYield,
    133    DebugEpilogue,
    134 
    135    Invalid
    136  };
    137 
    138 private:
    139  // What this entry is for.
    140  uint32_t kind_ : 4;
    141 
    142 public:
    143  RetAddrEntry(uint32_t pcOffset, Kind kind, CodeOffset retOffset)
    144      : returnOffset_(uint32_t(retOffset.offset())),
    145        pcOffset_(pcOffset),
    146        kind_(uint32_t(kind)) {
    147    MOZ_ASSERT(returnOffset_ == retOffset.offset(),
    148               "retOffset must fit in returnOffset_");
    149 
    150    // The pc offset must fit in at least 28 bits, since we shave off 4 for
    151    // the Kind enum.
    152    MOZ_ASSERT(pcOffset_ == pcOffset);
    153    static_assert(BaselineMaxScriptLength <= (1u << 28) - 1);
    154    MOZ_ASSERT(pcOffset <= BaselineMaxScriptLength);
    155 
    156    MOZ_ASSERT(kind < Kind::Invalid);
    157    MOZ_ASSERT(this->kind() == kind, "kind must fit in kind_ bit field");
    158  }
    159 
    160  CodeOffset returnOffset() const { return CodeOffset(returnOffset_); }
    161 
    162  uint32_t pcOffset() const { return pcOffset_; }
    163 
    164  jsbytecode* pc(JSScript* script) const {
    165    return script->offsetToPC(pcOffset_);
    166  }
    167 
    168  Kind kind() const {
    169    MOZ_ASSERT(kind_ < uint32_t(Kind::Invalid));
    170    return Kind(kind_);
    171  }
    172 };
    173 
    174 // [SMDOC] BaselineScript
    175 //
    176 // This holds the metadata generated by the BaselineCompiler. The machine code
    177 // associated with this is owned by a JitCode instance. This class instance is
    178 // followed by several arrays:
    179 //
    180 //    <BaselineScript itself>
    181 //    --
    182 //    uint8_t*[]              resumeEntryList()
    183 //    RetAddrEntry[]          retAddrEntries()
    184 //    OSREntry[]              osrEntries()
    185 //    DebugTrapEntry[]        debugTrapEntries()
    186 //
    187 // Note: The arrays are arranged in order of descending alignment requires so
    188 // that padding is not required.
    189 class alignas(uintptr_t) BaselineScript final
    190    : public TrailingArray<BaselineScript> {
    191 private:
    192  // Code pointer containing the actual method.
    193  HeapPtr<JitCode*> method_ = nullptr;
    194 
    195  // An ion compilation that is ready, but isn't linked yet.
    196  MainThreadData<IonCompileTask*> pendingIonCompileTask_{nullptr};
    197 
    198  // Baseline Interpreter can enter Baseline Compiler code at this address. This
    199  // is right after the warm-up counter check in the prologue.
    200  uint32_t warmUpCheckPrologueOffset_ = 0;
    201 
    202  // The offsets for the toggledJump instructions for profiler instrumentation.
    203  uint32_t profilerEnterToggleOffset_ = 0;
    204  uint32_t profilerExitToggleOffset_ = 0;
    205 
    206 private:
    207  // Offset (in bytes) from `this` to the start of each trailing array. Each
    208  // array ends where following one begins. There is no implicit padding (except
    209  // possible at very end).
    210  Offset resumeEntriesOffset_ = 0;
    211  Offset retAddrEntriesOffset_ = 0;
    212  Offset osrEntriesOffset_ = 0;
    213  Offset debugTrapEntriesOffset_ = 0;
    214  Offset allocBytes_ = 0;
    215 
    216  // See `Flag` type below.
    217  uint8_t flags_ = 0;
    218 
    219  // End of fields.
    220 
    221 public:
    222  enum Flag {
    223    // Flag set when compiled for use with Debugger. Handles various
    224    // Debugger hooks and compiles toggled calls for traps.
    225    HAS_DEBUG_INSTRUMENTATION = 1 << 0,
    226 
    227    // Flag is set if this script has profiling instrumentation turned on.
    228    PROFILER_INSTRUMENTATION_ON = 1 << 1,
    229  };
    230 
    231  // Native code offset for OSR from Baseline Interpreter into Baseline JIT at
    232  // JSOp::LoopHead ops.
    233  class OSREntry : public BasePCToNativeEntry {
    234   public:
    235    using BasePCToNativeEntry::BasePCToNativeEntry;
    236  };
    237 
    238  // Native code offset for a debug trap when the script is compiled with debug
    239  // instrumentation.
    240  class DebugTrapEntry : public BasePCToNativeEntry {
    241   public:
    242    using BasePCToNativeEntry::BasePCToNativeEntry;
    243  };
    244 
    245 private:
    246  // Layout helpers
    247  Offset resumeEntriesOffset() const { return resumeEntriesOffset_; }
    248  Offset retAddrEntriesOffset() const { return retAddrEntriesOffset_; }
    249  Offset osrEntriesOffset() const { return osrEntriesOffset_; }
    250  Offset debugTrapEntriesOffset() const { return debugTrapEntriesOffset_; }
    251  Offset endOffset() const { return allocBytes_; }
    252 
    253  // Use BaselineScript::New to create new instances. It will properly
    254  // allocate trailing objects.
    255  BaselineScript(uint32_t warmUpCheckPrologueOffset,
    256                 uint32_t profilerEnterToggleOffset,
    257                 uint32_t profilerExitToggleOffset)
    258      : warmUpCheckPrologueOffset_(warmUpCheckPrologueOffset),
    259        profilerEnterToggleOffset_(profilerEnterToggleOffset),
    260        profilerExitToggleOffset_(profilerExitToggleOffset) {}
    261 
    262  template <typename T>
    263  mozilla::Span<T> makeSpan(Offset start, Offset end) {
    264    return mozilla::Span{offsetToPointer<T>(start), numElements<T>(start, end)};
    265  }
    266 
    267  // We store the native code address corresponding to each bytecode offset in
    268  // the script's resumeOffsets list.
    269  mozilla::Span<uint8_t*> resumeEntryList() {
    270    return makeSpan<uint8_t*>(resumeEntriesOffset(), retAddrEntriesOffset());
    271  }
    272 
    273  // See each type for documentation of these arrays.
    274  mozilla::Span<RetAddrEntry> retAddrEntries() {
    275    return makeSpan<RetAddrEntry>(retAddrEntriesOffset(), osrEntriesOffset());
    276  }
    277  mozilla::Span<OSREntry> osrEntries() {
    278    return makeSpan<OSREntry>(osrEntriesOffset(), debugTrapEntriesOffset());
    279  }
    280  mozilla::Span<DebugTrapEntry> debugTrapEntries() {
    281    return makeSpan<DebugTrapEntry>(debugTrapEntriesOffset(), endOffset());
    282  }
    283 
    284 public:
    285  static BaselineScript* New(JSContext* cx, uint32_t warmUpCheckPrologueOffset,
    286                             uint32_t profilerEnterToggleOffset,
    287                             uint32_t profilerExitToggleOffset,
    288                             size_t retAddrEntries, size_t osrEntries,
    289                             size_t debugTrapEntries, size_t resumeEntries);
    290 
    291  // Copies the given BaselineScript and all trailing arrays.
    292  // Both BaselineScripts will refer to the same method and IonCompileTask (if
    293  // any), but those objects won't be compiled.
    294  static BaselineScript* Copy(JSContext* cx, BaselineScript* bs);
    295 
    296  static void Destroy(JS::GCContext* gcx, BaselineScript* script);
    297 
    298  void trace(JSTracer* trc);
    299 
    300  static inline size_t offsetOfMethod() {
    301    return offsetof(BaselineScript, method_);
    302  }
    303 
    304  void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
    305                              size_t* data) const {
    306    *data += mallocSizeOf(this);
    307  }
    308 
    309  void setHasDebugInstrumentation() { flags_ |= HAS_DEBUG_INSTRUMENTATION; }
    310  bool hasDebugInstrumentation() const {
    311    return flags_ & HAS_DEBUG_INSTRUMENTATION;
    312  }
    313 
    314  uint8_t* warmUpCheckPrologueAddr() const {
    315    return method_->raw() + warmUpCheckPrologueOffset_;
    316  }
    317 
    318  JitCode* method() const { return method_; }
    319  void setMethod(JitCode* code) {
    320    MOZ_ASSERT(!method_);
    321    method_ = code;
    322  }
    323 
    324  bool containsCodeAddress(uint8_t* addr) const {
    325    return method()->raw() <= addr &&
    326           addr <= method()->raw() + method()->instructionsSize();
    327  }
    328 
    329  uint8_t* returnAddressForEntry(const RetAddrEntry& ent);
    330 
    331  const RetAddrEntry& retAddrEntryFromPCOffset(uint32_t pcOffset,
    332                                               RetAddrEntry::Kind kind);
    333  const RetAddrEntry& prologueRetAddrEntry(RetAddrEntry::Kind kind);
    334  const RetAddrEntry& retAddrEntryFromReturnOffset(CodeOffset returnOffset);
    335  const RetAddrEntry& retAddrEntryFromReturnAddress(const uint8_t* returnAddr);
    336 
    337  uint8_t* nativeCodeForOSREntry(uint32_t pcOffset);
    338 
    339  static bool OSREntryForFrame(JSContext* cx, BaselineFrame* frame,
    340                               uint8_t** entry);
    341 
    342  void copyRetAddrEntries(const RetAddrEntry* entries);
    343  void copyOSREntries(const OSREntry* entries);
    344  void copyDebugTrapEntries(const DebugTrapEntry* entries);
    345 
    346  // Copy resumeOffsets list from |script| and convert the pcOffsets
    347  // to native addresses in the Baseline code based on |entries|.
    348  void computeResumeNativeOffsets(JSScript* script,
    349                                  const ResumeOffsetEntryVector& entries);
    350 
    351  // Return the bytecode offset for a given native code address. Be careful
    352  // when using this method: it's an approximation and not guaranteed to be the
    353  // correct pc.
    354  jsbytecode* approximatePcForNativeAddress(JSScript* script,
    355                                            uint8_t* nativeAddress);
    356 
    357  // Toggle debug traps (used for breakpoints and step mode) in the script.
    358  // If |pc| is nullptr, toggle traps for all ops in the script. Else, only
    359  // toggle traps at |pc|.
    360  void toggleDebugTraps(JSScript* script, jsbytecode* pc);
    361 
    362  void toggleProfilerInstrumentation(bool enable);
    363  bool isProfilerInstrumentationOn() const {
    364    return flags_ & PROFILER_INSTRUMENTATION_ON;
    365  }
    366 
    367  static size_t offsetOfResumeEntriesOffset() {
    368    static_assert(sizeof(Offset) == sizeof(uint32_t),
    369                  "JIT expect Offset to be uint32_t");
    370    return offsetof(BaselineScript, resumeEntriesOffset_);
    371  }
    372 
    373  bool hasPendingIonCompileTask() const { return !!pendingIonCompileTask_; }
    374 
    375  js::jit::IonCompileTask* pendingIonCompileTask() {
    376    MOZ_ASSERT(hasPendingIonCompileTask());
    377    return pendingIonCompileTask_;
    378  }
    379  void setPendingIonCompileTask(JSRuntime* rt, JSScript* script,
    380                                js::jit::IonCompileTask* task);
    381  void removePendingIonCompileTask(JSRuntime* rt, JSScript* script);
    382 
    383  size_t allocBytes() const { return allocBytes_; }
    384 };
    385 static_assert(
    386    sizeof(BaselineScript) % sizeof(uintptr_t) == 0,
    387    "The data attached to the script must be aligned for fast JIT access.");
    388 
    389 enum class BaselineTier { Interpreter, Compiler };
    390 
    391 template <BaselineTier Tier>
    392 MethodStatus CanEnterBaselineMethod(JSContext* cx, RunState& state);
    393 
    394 MethodStatus CanEnterBaselineInterpreterAtBranch(JSContext* cx,
    395                                                 InterpreterFrame* fp);
    396 
    397 JitExecStatus EnterBaselineInterpreterAtBranch(JSContext* cx,
    398                                               InterpreterFrame* fp,
    399                                               jsbytecode* pc);
    400 
    401 bool CanBaselineInterpretScript(JSScript* script);
    402 
    403 // Called by the Baseline Interpreter to compile a script for the Baseline JIT.
    404 // |res| is set to the native code address in the BaselineScript to jump to, or
    405 // nullptr if we were unable to compile this script.
    406 bool BaselineCompileFromBaselineInterpreter(JSContext* cx, BaselineFrame* frame,
    407                                            uint8_t** res);
    408 
    409 void FinishDiscardBaselineScript(JS::GCContext* gcx, JSScript* script);
    410 
    411 void AddSizeOfBaselineData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf,
    412                           size_t* data);
    413 
    414 void ToggleBaselineProfiling(JSContext* cx, bool enable);
    415 
    416 struct alignas(uintptr_t) BaselineBailoutInfo {
    417  // Pointer into the current C stack, where overwriting will start.
    418  uint8_t* incomingStack = nullptr;
    419 
    420  // The top and bottom heapspace addresses of the reconstructed stack
    421  // which will be copied to the bottom.
    422  uint8_t* copyStackTop = nullptr;
    423  uint8_t* copyStackBottom = nullptr;
    424 
    425  // The value of the frame pointer register on resume.
    426  void* resumeFramePtr = nullptr;
    427 
    428  // The native code address to resume into.
    429  void* resumeAddr = nullptr;
    430 
    431  // The bytecode pc of try block and fault block.
    432  jsbytecode* tryPC = nullptr;
    433  jsbytecode* faultPC = nullptr;
    434 
    435  // We use this to transfer exception information out from
    436  // buildExpressionStack, since it would be too risky to throw from
    437  // there.
    438  jsid tempId = PropertyKey::Void();
    439 
    440  // Number of baseline frames to push on the stack.
    441  uint32_t numFrames = 0;
    442 
    443  // The bailout kind.
    444  mozilla::Maybe<BailoutKind> bailoutKind = {};
    445 
    446  BaselineBailoutInfo() = default;
    447  BaselineBailoutInfo(const BaselineBailoutInfo&) = default;
    448 
    449  void operator=(const BaselineBailoutInfo&) = delete;
    450 
    451  void trace(JSTracer* aTrc);
    452 };
    453 
    454 enum class BailoutReason {
    455  Normal,
    456  ExceptionHandler,
    457  Invalidate,
    458 };
    459 
    460 [[nodiscard]] bool BailoutIonToBaseline(
    461    JSContext* cx, JitActivation* activation, const JSJitFrameIter& iter,
    462    BaselineBailoutInfo** bailoutInfo,
    463    const ExceptionBailoutInfo* exceptionInfo, BailoutReason reason);
    464 
    465 enum class BaselineOption : uint8_t {
    466  ForceDebugInstrumentation = 1 << 0,
    467  ForceMainThreadCompilation = 1 << 1,
    468 };
    469 
    470 using BaselineOptions = EnumFlags<BaselineOption>;
    471 
    472 bool DispatchOffThreadBaselineBatchEager(JSContext* cx);
    473 bool DispatchOffThreadBaselineBatch(JSContext* cx);
    474 
    475 MethodStatus BaselineCompile(JSContext* cx, JSScript* script,
    476                             BaselineOptions options);
    477 
    478 // Class storing the generated Baseline Interpreter code for the runtime.
    479 class BaselineInterpreter {
    480 public:
    481  struct CallVMOffsets {
    482    uint32_t debugPrologueOffset = 0;
    483    uint32_t debugEpilogueOffset = 0;
    484    uint32_t debugAfterYieldOffset = 0;
    485  };
    486  struct ICReturnOffset {
    487    uint32_t offset;
    488    JSOp op;
    489    ICReturnOffset(uint32_t offset, JSOp op) : offset(offset), op(op) {}
    490  };
    491  using ICReturnOffsetVector = Vector<ICReturnOffset, 0, SystemAllocPolicy>;
    492 
    493 private:
    494  // The interpreter code.
    495  JitCode* code_ = nullptr;
    496 
    497  // Offset of the code to start interpreting a bytecode op.
    498  uint32_t interpretOpOffset_ = 0;
    499 
    500  // Like interpretOpOffset_ but skips the debug trap for the current op.
    501  uint32_t interpretOpNoDebugTrapOffset_ = 0;
    502 
    503  // Early Ion bailouts will enter at this address. This is after frame
    504  // construction and environment initialization.
    505  uint32_t bailoutPrologueOffset_ = 0;
    506 
    507  // The offsets for the toggledJump instructions for profiler instrumentation.
    508  uint32_t profilerEnterToggleOffset_ = 0;
    509  uint32_t profilerExitToggleOffset_ = 0;
    510 
    511  // Offset of the jump (tail call) to the debug trap handler trampoline code.
    512  // When the debugger is enabled, NOPs are patched to calls to this location.
    513  uint32_t debugTrapHandlerOffset_ = 0;
    514 
    515  // The offsets of toggled jumps for debugger instrumentation.
    516  using CodeOffsetVector = Vector<uint32_t, 0, SystemAllocPolicy>;
    517  CodeOffsetVector debugInstrumentationOffsets_;
    518 
    519  // Offsets of toggled calls to the DebugTrapHandler trampoline (for
    520  // breakpoints and stepping).
    521  CodeOffsetVector debugTrapOffsets_;
    522 
    523  // Offsets of toggled jumps for code coverage.
    524  CodeOffsetVector codeCoverageOffsets_;
    525 
    526  // Offsets of IC calls for IsIonInlinableOp ops, for Ion bailouts.
    527  ICReturnOffsetVector icReturnOffsets_;
    528 
    529  // Offsets of some callVMs for BaselineDebugModeOSR.
    530  CallVMOffsets callVMOffsets_;
    531 
    532  uint8_t* codeAtOffset(uint32_t offset) const {
    533    MOZ_ASSERT(offset > 0);
    534    MOZ_ASSERT(offset < code_->instructionsSize());
    535    return codeRaw() + offset;
    536  }
    537 
    538 public:
    539  BaselineInterpreter() = default;
    540 
    541  BaselineInterpreter(const BaselineInterpreter&) = delete;
    542  void operator=(const BaselineInterpreter&) = delete;
    543 
    544  void init(JitCode* code, uint32_t interpretOpOffset,
    545            uint32_t interpretOpNoDebugTrapOffset,
    546            uint32_t bailoutPrologueOffset, uint32_t profilerEnterToggleOffset,
    547            uint32_t profilerExitToggleOffset, uint32_t debugTrapHandlerOffset,
    548            CodeOffsetVector&& debugInstrumentationOffsets,
    549            CodeOffsetVector&& debugTrapOffsets,
    550            CodeOffsetVector&& codeCoverageOffsets,
    551            ICReturnOffsetVector&& icReturnOffsets,
    552            const CallVMOffsets& callVMOffsets);
    553 
    554  uint8_t* codeRaw() const { return code_->raw(); }
    555 
    556  uint8_t* retAddrForDebugPrologueCallVM() const {
    557    return codeAtOffset(callVMOffsets_.debugPrologueOffset);
    558  }
    559  uint8_t* retAddrForDebugEpilogueCallVM() const {
    560    return codeAtOffset(callVMOffsets_.debugEpilogueOffset);
    561  }
    562  uint8_t* retAddrForDebugAfterYieldCallVM() const {
    563    return codeAtOffset(callVMOffsets_.debugAfterYieldOffset);
    564  }
    565  uint8_t* bailoutPrologueEntryAddr() const {
    566    return codeAtOffset(bailoutPrologueOffset_);
    567  }
    568 
    569  uint8_t* retAddrForIC(JSOp op) const;
    570 
    571  TrampolinePtr interpretOpAddr() const {
    572    return TrampolinePtr(codeAtOffset(interpretOpOffset_));
    573  }
    574  TrampolinePtr interpretOpNoDebugTrapAddr() const {
    575    return TrampolinePtr(codeAtOffset(interpretOpNoDebugTrapOffset_));
    576  }
    577 
    578  void toggleProfilerInstrumentation(bool enable);
    579  void toggleDebuggerInstrumentation(bool enable);
    580 
    581  void toggleCodeCoverageInstrumentationUnchecked(bool enable);
    582  void toggleCodeCoverageInstrumentation(bool enable);
    583 };
    584 
    585 [[nodiscard]] bool GenerateBaselineInterpreter(
    586    JSContext* cx, BaselineInterpreter& interpreter);
    587 
    588 inline bool IsBaselineJitEnabled(JSContext* cx) {
    589  if (MOZ_UNLIKELY(!IsBaselineInterpreterEnabled())) {
    590    return false;
    591  }
    592  if (MOZ_LIKELY(JitOptions.baselineJit)) {
    593    return true;
    594  }
    595  if (JitOptions.jitForTrustedPrincipals) {
    596    JS::Realm* realm = js::GetContextRealm(cx);
    597    return realm && JS::GetRealmPrincipals(realm) &&
    598           JS::GetRealmPrincipals(realm)->isSystemOrAddonPrincipal();
    599  }
    600  return false;
    601 }
    602 
    603 }  // namespace jit
    604 }  // namespace js
    605 
    606 namespace JS {
    607 
    608 template <>
    609 struct DeletePolicy<js::jit::BaselineScript> {
    610  explicit DeletePolicy(JSRuntime* rt) : rt_(rt) {}
    611  void operator()(const js::jit::BaselineScript* script);
    612 
    613 private:
    614  JSRuntime* rt_;
    615 };
    616 
    617 template <>
    618 struct GCPolicy<js::jit::BaselineScript*> {
    619  static void trace(JSTracer* trc, js::jit::BaselineScript** thingp,
    620                    const char* name) {
    621    (*thingp)->trace(trc);
    622  }
    623 };
    624 
    625 }  // namespace JS
    626 
    627 #endif /* jit_BaselineJIT_h */