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