tor-browser

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

WarpSnapshot.h (22588B)


      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_WarpSnapshot_h
      8 #define jit_WarpSnapshot_h
      9 
     10 #include "mozilla/LinkedList.h"
     11 #include "mozilla/Variant.h"
     12 
     13 #include "builtin/ModuleObject.h"
     14 #include "jit/JitAllocPolicy.h"
     15 #include "jit/JitContext.h"
     16 #include "jit/JitZone.h"
     17 #include "jit/OffthreadSnapshot.h"
     18 #include "jit/TypeData.h"
     19 #include "vm/EnvironmentObject.h"
     20 #include "vm/FunctionFlags.h"  // js::FunctionFlags
     21 
     22 namespace js {
     23 
     24 class ArgumentsObject;
     25 class CallObject;
     26 class GlobalLexicalEnvironmentObject;
     27 class LexicalEnvironmentObject;
     28 class ModuleEnvironmentObject;
     29 class NamedLambdaObject;
     30 
     31 namespace jit {
     32 
     33 class CacheIRStubInfo;
     34 class CompileInfo;
     35 class WarpScriptSnapshot;
     36 
     37 #define WARP_OP_SNAPSHOT_LIST(_)        \
     38  _(WarpArguments)                      \
     39  _(WarpRegExp)                         \
     40  _(WarpBuiltinObject)                  \
     41  _(WarpGetIntrinsic)                   \
     42  _(WarpGetImport)                      \
     43  _(WarpRest)                           \
     44  _(WarpBindUnqualifiedGName)           \
     45  _(WarpVarEnvironment)                 \
     46  _(WarpLexicalEnvironment)             \
     47  _(WarpClassBodyEnvironment)           \
     48  _(WarpBailout)                        \
     49  _(WarpCacheIR)                        \
     50  _(WarpCacheIRWithShapeList)           \
     51  _(WarpCacheIRWithShapeListAndOffsets) \
     52  _(WarpInlinedCall)                    \
     53  _(WarpPolymorphicTypes)
     54 
     55 // WarpOpSnapshot is the base class for data attached to a single bytecode op by
     56 // WarpOracle. This is typically data that WarpBuilder can't read off-thread
     57 // without racing.
     58 class WarpOpSnapshot : public TempObject,
     59                       public mozilla::LinkedListElement<WarpOpSnapshot> {
     60 public:
     61  enum class Kind : uint16_t {
     62 #define DEF_KIND(KIND) KIND,
     63    WARP_OP_SNAPSHOT_LIST(DEF_KIND)
     64 #undef DEF_KIND
     65  };
     66 
     67 private:
     68  // Bytecode offset.
     69  uint32_t offset_ = 0;
     70 
     71  Kind kind_;
     72 
     73 protected:
     74  WarpOpSnapshot(Kind kind, uint32_t offset) : offset_(offset), kind_(kind) {}
     75 
     76 public:
     77  uint32_t offset() const { return offset_; }
     78  Kind kind() const { return kind_; }
     79 
     80  template <typename T>
     81  bool is() const {
     82    return kind_ == T::ThisKind;
     83  }
     84 
     85  template <typename T>
     86  const T* as() const {
     87    MOZ_ASSERT(is<T>());
     88    return static_cast<const T*>(this);
     89  }
     90 
     91  template <typename T>
     92  T* as() {
     93    MOZ_ASSERT(is<T>());
     94    return static_cast<T*>(this);
     95  }
     96 
     97  void trace(JSTracer* trc);
     98 
     99 #ifdef JS_JITSPEW
    100  void dump(GenericPrinter& out, JSScript* script) const;
    101 #endif
    102 };
    103 
    104 using WarpOpSnapshotList = mozilla::LinkedList<WarpOpSnapshot>;
    105 
    106 // Template object for JSOp::Arguments.
    107 class WarpArguments : public WarpOpSnapshot {
    108  // Note: this can be nullptr if the realm has no template object yet.
    109  OffthreadGCPtr<ArgumentsObject*> templateObj_;
    110 
    111 public:
    112  static constexpr Kind ThisKind = Kind::WarpArguments;
    113 
    114  WarpArguments(uint32_t offset, ArgumentsObject* templateObj)
    115      : WarpOpSnapshot(ThisKind, offset), templateObj_(templateObj) {}
    116  ArgumentsObject* templateObj() const { return templateObj_; }
    117 
    118  void traceData(JSTracer* trc);
    119 
    120 #ifdef JS_JITSPEW
    121  void dumpData(GenericPrinter& out) const;
    122 #endif
    123 };
    124 
    125 // The "has RegExpShared" state for JSOp::RegExp's template object.
    126 class WarpRegExp : public WarpOpSnapshot {
    127  bool hasShared_;
    128 
    129 public:
    130  static constexpr Kind ThisKind = Kind::WarpRegExp;
    131 
    132  WarpRegExp(uint32_t offset, bool hasShared)
    133      : WarpOpSnapshot(ThisKind, offset), hasShared_(hasShared) {}
    134  bool hasShared() const { return hasShared_; }
    135 
    136  void traceData(JSTracer* trc);
    137 
    138 #ifdef JS_JITSPEW
    139  void dumpData(GenericPrinter& out) const;
    140 #endif
    141 };
    142 
    143 // The object for JSOp::BuiltinObject if it exists at compile-time.
    144 class WarpBuiltinObject : public WarpOpSnapshot {
    145  OffthreadGCPtr<JSObject*> builtin_;
    146 
    147 public:
    148  static constexpr Kind ThisKind = Kind::WarpBuiltinObject;
    149 
    150  WarpBuiltinObject(uint32_t offset, JSObject* builtin)
    151      : WarpOpSnapshot(ThisKind, offset), builtin_(builtin) {
    152    MOZ_ASSERT(builtin);
    153  }
    154  JSObject* builtin() const { return builtin_; }
    155 
    156  void traceData(JSTracer* trc);
    157 
    158 #ifdef JS_JITSPEW
    159  void dumpData(GenericPrinter& out) const;
    160 #endif
    161 };
    162 
    163 // The intrinsic for JSOp::GetIntrinsic if it exists at compile-time.
    164 class WarpGetIntrinsic : public WarpOpSnapshot {
    165  OffthreadGCPtr<Value> intrinsic_;
    166 
    167 public:
    168  static constexpr Kind ThisKind = Kind::WarpGetIntrinsic;
    169 
    170  WarpGetIntrinsic(uint32_t offset, const Value& intrinsic)
    171      : WarpOpSnapshot(ThisKind, offset), intrinsic_(intrinsic) {}
    172  Value intrinsic() const { return intrinsic_; }
    173 
    174  void traceData(JSTracer* trc);
    175 
    176 #ifdef JS_JITSPEW
    177  void dumpData(GenericPrinter& out) const;
    178 #endif
    179 };
    180 
    181 // Target module environment and slot information for JSOp::GetImport.
    182 class WarpGetImport : public WarpOpSnapshot {
    183  OffthreadGCPtr<ModuleEnvironmentObject*> targetEnv_;
    184  uint32_t numFixedSlots_;
    185  uint32_t slot_;
    186  bool needsLexicalCheck_;
    187 
    188 public:
    189  static constexpr Kind ThisKind = Kind::WarpGetImport;
    190 
    191  WarpGetImport(uint32_t offset, ModuleEnvironmentObject* targetEnv,
    192                uint32_t numFixedSlots, uint32_t slot, bool needsLexicalCheck)
    193      : WarpOpSnapshot(ThisKind, offset),
    194        targetEnv_(targetEnv),
    195        numFixedSlots_(numFixedSlots),
    196        slot_(slot),
    197        needsLexicalCheck_(needsLexicalCheck) {}
    198  ModuleEnvironmentObject* targetEnv() const { return targetEnv_; }
    199  uint32_t numFixedSlots() const { return numFixedSlots_; }
    200  uint32_t slot() const { return slot_; }
    201  bool needsLexicalCheck() const { return needsLexicalCheck_; }
    202 
    203  void traceData(JSTracer* trc);
    204 
    205 #ifdef JS_JITSPEW
    206  void dumpData(GenericPrinter& out) const;
    207 #endif
    208 };
    209 
    210 // Informs WarpBuilder that an IC site is cold and execution should bail out.
    211 class WarpBailout : public WarpOpSnapshot {
    212 public:
    213  static constexpr Kind ThisKind = Kind::WarpBailout;
    214 
    215  explicit WarpBailout(uint32_t offset) : WarpOpSnapshot(ThisKind, offset) {}
    216 
    217  void traceData(JSTracer* trc);
    218 
    219 #ifdef JS_JITSPEW
    220  void dumpData(GenericPrinter& out) const;
    221 #endif
    222 };
    223 
    224 class WarpCacheIRBase : public WarpOpSnapshot {
    225  // Baseline stub code. Stored here to keep the CacheIRStubInfo alive.
    226  OffthreadGCPtr<JitCode*> stubCode_;
    227  const CacheIRStubInfo* stubInfo_;
    228 
    229  // Copied Baseline stub data. Allocated in the same LifoAlloc.
    230  const uint8_t* stubData_;
    231 
    232 protected:
    233  WarpCacheIRBase(Kind kind, uint32_t offset, JitCode* stubCode,
    234                  const CacheIRStubInfo* stubInfo, const uint8_t* stubData)
    235      : WarpOpSnapshot(kind, offset),
    236        stubCode_(stubCode),
    237        stubInfo_(stubInfo),
    238        stubData_(stubData) {}
    239 
    240  void traceData(JSTracer* trc);
    241 
    242 #ifdef JS_JITSPEW
    243  void dumpData(GenericPrinter& out) const;
    244 #endif
    245 
    246 public:
    247  const CacheIRStubInfo* stubInfo() const { return stubInfo_; }
    248  const uint8_t* stubData() const { return stubData_; }
    249 };
    250 
    251 // Information from a Baseline IC stub.
    252 class WarpCacheIR : public WarpCacheIRBase {
    253 public:
    254  static constexpr Kind ThisKind = Kind::WarpCacheIR;
    255 
    256  WarpCacheIR(uint32_t offset, JitCode* stubCode,
    257              const CacheIRStubInfo* stubInfo, const uint8_t* stubData)
    258      : WarpCacheIRBase(ThisKind, offset, stubCode, stubInfo, stubData) {}
    259 
    260  void traceData(JSTracer* trc);
    261 
    262 #ifdef JS_JITSPEW
    263  void dumpData(GenericPrinter& out) const;
    264 #endif
    265 };
    266 
    267 class ShapeListSnapshot {
    268 public:
    269  ShapeListSnapshot() = default;
    270 
    271  void init(size_t index, Shape* shape) {
    272    MOZ_ASSERT(shape);
    273    shapes_[index].init(shape);
    274  }
    275  const auto& shapes() const { return shapes_; }
    276 
    277  static bool shouldSnapshot(size_t length) {
    278    // ShapeListObject has weak pointers so a GC can remove shapes from the
    279    // list. Don't snapshot empty shape lists to avoid bailouts and because
    280    // handling this edge case would complicate the compiler code.
    281    return length > 0 && length <= NumShapes;
    282  }
    283 
    284  void trace(JSTracer* trc) const;
    285 
    286 protected:
    287  static constexpr size_t NumShapes = 4;
    288  mozilla::Array<OffthreadGCPtr<Shape*>, NumShapes> shapes_{};
    289 };
    290 
    291 class ShapeListWithOffsetsSnapshot : public ShapeListSnapshot {
    292 public:
    293  ShapeListWithOffsetsSnapshot() = default;
    294 
    295  void init(size_t index, Shape* shape, uint32_t offset) {
    296    MOZ_ASSERT(shape);
    297    shapes_[index].init(shape);
    298    offsets_[index] = offset;
    299  }
    300 
    301  const auto& offsets() const { return offsets_; }
    302 
    303 private:
    304  mozilla::Array<uint32_t, NumShapes> offsets_{};
    305 };
    306 
    307 // Like WarpCacheIR, but also includes a ShapeListSnapshot for the
    308 // GuardMultipleShapes CacheIR op.
    309 class WarpCacheIRWithShapeList : public WarpCacheIRBase {
    310  const ShapeListSnapshot shapes_;
    311 
    312 public:
    313  static constexpr Kind ThisKind = Kind::WarpCacheIRWithShapeList;
    314 
    315  WarpCacheIRWithShapeList(uint32_t offset, JitCode* stubCode,
    316                           const CacheIRStubInfo* stubInfo,
    317                           const uint8_t* stubData,
    318                           const ShapeListSnapshot& shapes)
    319      : WarpCacheIRBase(ThisKind, offset, stubCode, stubInfo, stubData),
    320        shapes_(shapes) {}
    321 
    322  void traceData(JSTracer* trc);
    323 
    324 #ifdef JS_JITSPEW
    325  void dumpData(GenericPrinter& out) const;
    326 #endif
    327 
    328  const ShapeListSnapshot* shapes() const { return &shapes_; }
    329 };
    330 
    331 // Like WarpCacheIR, but also includes a ShapeListWithOffsetsSnapshot for the
    332 // GuardMultipleShapesToOffset CacheIR op.
    333 class WarpCacheIRWithShapeListAndOffsets : public WarpCacheIRBase {
    334  const ShapeListWithOffsetsSnapshot shapes_;
    335 
    336 public:
    337  static constexpr Kind ThisKind = Kind::WarpCacheIRWithShapeListAndOffsets;
    338 
    339  WarpCacheIRWithShapeListAndOffsets(uint32_t offset, JitCode* stubCode,
    340                                     const CacheIRStubInfo* stubInfo,
    341                                     const uint8_t* stubData,
    342                                     const ShapeListWithOffsetsSnapshot& shapes)
    343      : WarpCacheIRBase(ThisKind, offset, stubCode, stubInfo, stubData),
    344        shapes_(shapes) {}
    345 
    346  void traceData(JSTracer* trc);
    347 
    348 #ifdef JS_JITSPEW
    349  void dumpData(GenericPrinter& out) const;
    350 #endif
    351 
    352  const ShapeListWithOffsetsSnapshot* shapes() const { return &shapes_; }
    353 };
    354 
    355 // [SMDOC] Warp Nursery Object/Value support
    356 //
    357 // CacheIR stub data can contain nursery allocated objects or values. This can
    358 // happen for example for GuardSpecificObject/GuardSpecificFunction or
    359 // GuardProto.
    360 //
    361 // To support nursery GCs in parallel with off-thread compilation, we use the
    362 // following mechanism for nursery objects:
    363 //
    364 // * When WarpOracle copies stub data, it builds a Vector of nursery objects.
    365 //   The nursery object pointers in the stub data are replaced with the
    366 //   corresponding index into this Vector.
    367 //   See WarpScriptOracle::replaceNurseryPointers.
    368 //
    369 // * The Vector is copied to the snapshot and, at the end of compilation, to
    370 //   the IonScript. The Vector is only accessed on the main thread.
    371 //
    372 // * The MIR backend never accesses the raw JSObject*. Instead, it uses
    373 //   MNurseryObject which will load the object at runtime from the IonScript.
    374 //
    375 // WarpObjectField is a helper class to encode/decode a stub data field that
    376 // either stores an object or a nursery index.
    377 //
    378 // A similar mechanism is used for boxed Values containing nursery pointers.
    379 // See ValueOrNurseryValueIndex.
    380 class WarpObjectField {
    381  // This is a nursery index if the low bit is set. Else it's a JSObject*.
    382  static constexpr uintptr_t NurseryIndexTag = 0x1;
    383  static constexpr uintptr_t NurseryIndexShift = 1;
    384 
    385  uintptr_t data_;
    386 
    387  explicit WarpObjectField(uintptr_t data) : data_(data) {}
    388 
    389 public:
    390  static WarpObjectField fromData(uintptr_t data) {
    391    return WarpObjectField(data);
    392  }
    393  static WarpObjectField fromObject(JSObject* obj) {
    394    return WarpObjectField(uintptr_t(obj));
    395  }
    396  static WarpObjectField fromNurseryIndex(uint32_t index) {
    397    uintptr_t data = (uintptr_t(index) << NurseryIndexShift) | NurseryIndexTag;
    398    return WarpObjectField(data);
    399  }
    400 
    401  uintptr_t rawData() const { return data_; }
    402 
    403  bool isNurseryIndex() const { return (data_ & NurseryIndexTag) != 0; }
    404 
    405  uint32_t toNurseryIndex() const {
    406    MOZ_ASSERT(isNurseryIndex());
    407    return data_ >> NurseryIndexShift;
    408  }
    409 
    410  JSObject* toObject() const {
    411    MOZ_ASSERT(!isNurseryIndex());
    412    return reinterpret_cast<JSObject*>(data_);
    413  }
    414 };
    415 
    416 // Information for inlining a scripted call IC.
    417 class WarpInlinedCall : public WarpOpSnapshot {
    418  // Used for generating the correct guards.
    419  WarpCacheIR* cacheIRSnapshot_;
    420 
    421  // Used for generating the inlined code.
    422  WarpScriptSnapshot* scriptSnapshot_;
    423  CompileInfo* info_;
    424 
    425 public:
    426  static constexpr Kind ThisKind = Kind::WarpInlinedCall;
    427 
    428  WarpInlinedCall(uint32_t offset, WarpCacheIR* cacheIRSnapshot,
    429                  WarpScriptSnapshot* scriptSnapshot, CompileInfo* info)
    430      : WarpOpSnapshot(ThisKind, offset),
    431        cacheIRSnapshot_(cacheIRSnapshot),
    432        scriptSnapshot_(scriptSnapshot),
    433        info_(info) {}
    434 
    435  WarpCacheIR* cacheIRSnapshot() const { return cacheIRSnapshot_; }
    436  WarpScriptSnapshot* scriptSnapshot() const { return scriptSnapshot_; }
    437  CompileInfo* info() const { return info_; }
    438 
    439  void traceData(JSTracer* trc);
    440 
    441 #ifdef JS_JITSPEW
    442  void dumpData(GenericPrinter& out) const;
    443 #endif
    444 };
    445 
    446 // Information for inlining an ordered set of types
    447 class WarpPolymorphicTypes : public WarpOpSnapshot {
    448  TypeDataList list_;
    449 
    450 public:
    451  static constexpr Kind ThisKind = Kind::WarpPolymorphicTypes;
    452 
    453  WarpPolymorphicTypes(uint32_t offset, TypeDataList list)
    454      : WarpOpSnapshot(ThisKind, offset), list_(list) {}
    455 
    456  const TypeDataList& list() const { return list_; }
    457 
    458  void traceData(JSTracer* trc);
    459 
    460 #ifdef JS_JITSPEW
    461  void dumpData(GenericPrinter& out) const;
    462 #endif
    463 };
    464 
    465 // Shape for JSOp::Rest.
    466 class WarpRest : public WarpOpSnapshot {
    467  OffthreadGCPtr<Shape*> shape_;
    468 
    469 public:
    470  static constexpr Kind ThisKind = Kind::WarpRest;
    471 
    472  WarpRest(uint32_t offset, Shape* shape)
    473      : WarpOpSnapshot(ThisKind, offset), shape_(shape) {}
    474 
    475  Shape* shape() const { return shape_; }
    476 
    477  void traceData(JSTracer* trc);
    478 
    479 #ifdef JS_JITSPEW
    480  void dumpData(GenericPrinter& out) const;
    481 #endif
    482 };
    483 
    484 // Global environment for BindUnqualifiedGName
    485 class WarpBindUnqualifiedGName : public WarpOpSnapshot {
    486  OffthreadGCPtr<JSObject*> globalEnv_;
    487 
    488 public:
    489  static constexpr Kind ThisKind = Kind::WarpBindUnqualifiedGName;
    490 
    491  WarpBindUnqualifiedGName(uint32_t offset, JSObject* globalEnv)
    492      : WarpOpSnapshot(ThisKind, offset), globalEnv_(globalEnv) {}
    493 
    494  JSObject* globalEnv() const { return globalEnv_; }
    495 
    496  void traceData(JSTracer* trc);
    497 
    498 #ifdef JS_JITSPEW
    499  void dumpData(GenericPrinter& out) const;
    500 #endif
    501 };
    502 
    503 // Block environment for PushVarEnv
    504 class WarpVarEnvironment : public WarpOpSnapshot {
    505  OffthreadGCPtr<VarEnvironmentObject*> templateObj_;
    506 
    507 public:
    508  static constexpr Kind ThisKind = Kind::WarpVarEnvironment;
    509 
    510  WarpVarEnvironment(uint32_t offset, VarEnvironmentObject* templateObj)
    511      : WarpOpSnapshot(ThisKind, offset), templateObj_(templateObj) {}
    512 
    513  VarEnvironmentObject* templateObj() const { return templateObj_; }
    514 
    515  void traceData(JSTracer* trc);
    516 
    517 #ifdef JS_JITSPEW
    518  void dumpData(GenericPrinter& out) const;
    519 #endif
    520 };
    521 
    522 // Block environment for PushLexicalEnv, FreshenLexicalEnv, RecreateLexicalEnv
    523 class WarpLexicalEnvironment : public WarpOpSnapshot {
    524  OffthreadGCPtr<BlockLexicalEnvironmentObject*> templateObj_;
    525 
    526 public:
    527  static constexpr Kind ThisKind = Kind::WarpLexicalEnvironment;
    528 
    529  WarpLexicalEnvironment(uint32_t offset,
    530                         BlockLexicalEnvironmentObject* templateObj)
    531      : WarpOpSnapshot(ThisKind, offset), templateObj_(templateObj) {}
    532 
    533  BlockLexicalEnvironmentObject* templateObj() const { return templateObj_; }
    534 
    535  void traceData(JSTracer* trc);
    536 
    537 #ifdef JS_JITSPEW
    538  void dumpData(GenericPrinter& out) const;
    539 #endif
    540 };
    541 
    542 // Class body lexical environment for PushClassBodyEnv
    543 class WarpClassBodyEnvironment : public WarpOpSnapshot {
    544  OffthreadGCPtr<ClassBodyLexicalEnvironmentObject*> templateObj_;
    545 
    546 public:
    547  static constexpr Kind ThisKind = Kind::WarpClassBodyEnvironment;
    548 
    549  WarpClassBodyEnvironment(uint32_t offset,
    550                           ClassBodyLexicalEnvironmentObject* templateObj)
    551      : WarpOpSnapshot(ThisKind, offset), templateObj_(templateObj) {}
    552 
    553  ClassBodyLexicalEnvironmentObject* templateObj() const {
    554    return templateObj_;
    555  }
    556 
    557  void traceData(JSTracer* trc);
    558 
    559 #ifdef JS_JITSPEW
    560  void dumpData(GenericPrinter& out) const;
    561 #endif
    562 };
    563 
    564 struct NoEnvironment {};
    565 using ConstantObjectEnvironment = OffthreadGCPtr<JSObject*>;
    566 struct FunctionEnvironment {
    567  OffthreadGCPtr<CallObject*> callObjectTemplate;
    568  OffthreadGCPtr<NamedLambdaObject*> namedLambdaTemplate;
    569  gc::Heap initialHeap;
    570 
    571 public:
    572  FunctionEnvironment(CallObject* callObjectTemplate,
    573                      NamedLambdaObject* namedLambdaTemplate,
    574                      gc::Heap initialHeap)
    575      : callObjectTemplate(callObjectTemplate),
    576        namedLambdaTemplate(namedLambdaTemplate),
    577        initialHeap(initialHeap) {}
    578 };
    579 
    580 // Snapshot data for the environment object(s) created in the script's prologue.
    581 //
    582 // One of:
    583 //
    584 // * NoEnvironment: No environment object should be set. Leave the slot
    585 //   initialized to |undefined|.
    586 //
    587 // * ConstantObjectEnvironment: Use this JSObject* as environment object.
    588 //
    589 // * FunctionEnvironment: Use the callee's environment chain. Optionally
    590 //   allocate a new NamedLambdaObject and/or CallObject based on
    591 //   namedLambdaTemplate and callObjectTemplate.
    592 using WarpEnvironment =
    593    mozilla::Variant<NoEnvironment, ConstantObjectEnvironment,
    594                     FunctionEnvironment>;
    595 
    596 // Snapshot data for a single JSScript.
    597 class WarpScriptSnapshot
    598    : public TempObject,
    599      public mozilla::LinkedListElement<WarpScriptSnapshot> {
    600  OffthreadGCPtr<JSScript*> script_;
    601  WarpEnvironment environment_;
    602  WarpOpSnapshotList opSnapshots_;
    603 
    604  // If the script has a JSOp::ImportMeta op, this is the module to bake in.
    605  OffthreadGCPtr<ModuleObject*> moduleObject_;
    606 
    607  // Whether this script is for an arrow function.
    608  bool isArrowFunction_;
    609 
    610 public:
    611  WarpScriptSnapshot(JSScript* script, const WarpEnvironment& env,
    612                     WarpOpSnapshotList&& opSnapshots,
    613                     ModuleObject* moduleObject);
    614 
    615  JSScript* script() const { return script_; }
    616  const WarpEnvironment& environment() const { return environment_; }
    617  const WarpOpSnapshotList& opSnapshots() const { return opSnapshots_; }
    618  ModuleObject* moduleObject() const { return moduleObject_; }
    619 
    620  bool isArrowFunction() const { return isArrowFunction_; }
    621 
    622  void trace(JSTracer* trc);
    623 
    624 #ifdef JS_JITSPEW
    625  void dump(GenericPrinter& out) const;
    626 #endif
    627 };
    628 
    629 // Captures information from previous bailouts to prevent bailout/recompile
    630 // loops.
    631 class WarpBailoutInfo {
    632  // True if any script in the compilation has the failedBoundsCheck flag. In
    633  // this case mark bounds checks as non-movable to prevent hoisting them in
    634  // TryEliminateBoundsCheck.
    635  bool failedBoundsCheck_ = false;
    636 
    637  // True if any script in the compilation has the failedLexicalCheck flag. In
    638  // this case mark lexical checks as non-movable.
    639  bool failedLexicalCheck_ = false;
    640 
    641 public:
    642  bool failedBoundsCheck() const { return failedBoundsCheck_; }
    643  void setFailedBoundsCheck() { failedBoundsCheck_ = true; }
    644 
    645  bool failedLexicalCheck() const { return failedLexicalCheck_; }
    646  void setFailedLexicalCheck() { failedLexicalCheck_ = true; }
    647 };
    648 
    649 using WarpScriptSnapshotList = mozilla::LinkedList<WarpScriptSnapshot>;
    650 
    651 using WarpZoneStubsSnapshot = JitZone::Stubs<JitCode*>;
    652 
    653 // Data allocated by WarpOracle on the main thread that's used off-thread by
    654 // WarpBuilder to build the MIR graph.
    655 class WarpSnapshot : public TempObject {
    656  // The scripts being compiled.
    657  WarpScriptSnapshotList scriptSnapshots_;
    658 
    659  // JitZone stubs this compilation depends on.
    660  const WarpZoneStubsSnapshot zoneStubs_;
    661 
    662  // The global lexical environment and its thisObject(). We don't inline
    663  // cross-realm calls so this can be stored once per snapshot.
    664  OffthreadGCPtr<GlobalLexicalEnvironmentObject*> globalLexicalEnv_;
    665  OffthreadGCPtr<JSObject*> globalLexicalEnvThis_;
    666 
    667  const WarpBailoutInfo bailoutInfo_;
    668 
    669  // List of (originally) nursery-allocated objects. Must only be accessed on
    670  // the main thread. See also WarpObjectField.
    671  using NurseryObjectVector = Vector<JSObject*, 0, JitAllocPolicy>;
    672  NurseryObjectVector nurseryObjects_;
    673 
    674  // List of Values containing (originally) nursery-allocated cells. Must only
    675  // be accessed on the main thread. See also the WarpObjectField SMDOC.
    676  using NurseryValueVector = mozilla::Vector<Value, 0, JitAllocPolicy>;
    677  NurseryValueVector nurseryValues_;
    678 
    679 #ifdef JS_CACHEIR_SPEW
    680  bool needsFinalWarmUpCount_ = false;
    681 #endif
    682 
    683 #ifdef DEBUG
    684  // A hash of the stub pointers and entry counts for each of the ICs
    685  // in this snapshot.
    686  mozilla::HashNumber icHash_ = 0;
    687 #endif
    688 
    689 public:
    690  explicit WarpSnapshot(JSContext* cx, TempAllocator& alloc,
    691                        WarpScriptSnapshotList&& scriptSnapshots,
    692                        const WarpZoneStubsSnapshot& zoneStubs,
    693                        const WarpBailoutInfo& bailoutInfo,
    694                        bool recordWarmUpCount);
    695 
    696  WarpScriptSnapshot* rootScript() { return scriptSnapshots_.getFirst(); }
    697  const WarpScriptSnapshotList& scripts() const { return scriptSnapshots_; }
    698 
    699  JitCode* getZoneStub(JitZone::StubKind kind) const {
    700    MOZ_ASSERT(zoneStubs_[kind]);
    701    return zoneStubs_[kind];
    702  }
    703 
    704  GlobalLexicalEnvironmentObject* globalLexicalEnv() const {
    705    return globalLexicalEnv_;
    706  }
    707  JSObject* globalLexicalEnvThis() const { return globalLexicalEnvThis_; }
    708 
    709  void trace(JSTracer* trc);
    710 
    711  const WarpBailoutInfo& bailoutInfo() const { return bailoutInfo_; }
    712 
    713  NurseryObjectVector& nurseryObjects() { return nurseryObjects_; }
    714  const NurseryObjectVector& nurseryObjects() const { return nurseryObjects_; }
    715 
    716  NurseryValueVector& nurseryValues() { return nurseryValues_; }
    717  const NurseryValueVector& nurseryValues() const { return nurseryValues_; }
    718 
    719 #ifdef DEBUG
    720  mozilla::HashNumber icHash() const { return icHash_; }
    721  void setICHash(mozilla::HashNumber hash) { icHash_ = hash; }
    722 #endif
    723 
    724 #ifdef JS_JITSPEW
    725  void dump() const;
    726  void dump(GenericPrinter& out) const;
    727 #endif
    728 
    729 #ifdef JS_CACHEIR_SPEW
    730  bool needsFinalWarmUpCount() const { return needsFinalWarmUpCount_; }
    731 #endif
    732 };
    733 
    734 }  // namespace jit
    735 }  // namespace js
    736 
    737 #endif /* jit_WarpSnapshot_h */