JitScript.h (21957B)
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_JitScript_h 8 #define jit_JitScript_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/Atomics.h" 12 #include "mozilla/Attributes.h" 13 #include "mozilla/HashFunctions.h" 14 #include "mozilla/LinkedList.h" 15 #include "mozilla/Maybe.h" 16 #include "mozilla/MemoryReporting.h" 17 18 #include <stddef.h> 19 #include <stdint.h> 20 21 #include "jstypes.h" 22 #include "NamespaceImports.h" 23 24 #include "ds/LifoAlloc.h" 25 #include "gc/Barrier.h" 26 #include "jit/BaselineIC.h" 27 #include "js/TypeDecls.h" 28 #include "js/UniquePtr.h" 29 #include "js/Vector.h" 30 #include "util/TrailingArray.h" 31 #include "vm/EnvironmentObject.h" 32 33 class JS_PUBLIC_API JSScript; 34 class JS_PUBLIC_API JSTracer; 35 struct JS_PUBLIC_API JSContext; 36 37 namespace JS { 38 class Zone; 39 } 40 41 namespace js { 42 43 class SystemAllocPolicy; 44 45 namespace gc { 46 class AllocSite; 47 } 48 49 namespace jit { 50 51 class BaselineScript; 52 class ICStubSpace; 53 class InliningRoot; 54 class IonScript; 55 class JitScript; 56 class JitZone; 57 58 // Magic values indicating compilation has been disabled or the script 59 // is already scheduled for background compilation. 60 static constexpr uintptr_t DisabledScript = 0x1; 61 static constexpr uintptr_t QueuedScript = 0x3; 62 static constexpr uintptr_t CompilingScript = 0x5; 63 64 static constexpr uint32_t SpecialScriptBit = 0x1; 65 static_assert((DisabledScript & SpecialScriptBit) != 0); 66 static_assert((QueuedScript & SpecialScriptBit) != 0); 67 static_assert((CompilingScript & SpecialScriptBit) != 0); 68 69 static BaselineScript* const BaselineDisabledScriptPtr = 70 reinterpret_cast<BaselineScript*>(DisabledScript); 71 static BaselineScript* const BaselineQueuedScriptPtr = 72 reinterpret_cast<BaselineScript*>(QueuedScript); 73 static BaselineScript* const BaselineCompilingScriptPtr = 74 reinterpret_cast<BaselineScript*>(CompilingScript); 75 76 static IonScript* const IonDisabledScriptPtr = 77 reinterpret_cast<IonScript*>(DisabledScript); 78 static IonScript* const IonCompilingScriptPtr = 79 reinterpret_cast<IonScript*>(CompilingScript); 80 81 /* [SMDOC] ICScript Lifetimes 82 * 83 * An ICScript owns an array of ICEntries, each of which owns a linked 84 * list of ICStubs. 85 * 86 * A JitScript contains an embedded ICScript. If it has done any trial 87 * inlining, it also owns an InliningRoot. The InliningRoot owns all 88 * of the ICScripts that have been created for inlining into the 89 * corresponding JitScript. This ties the lifetime of the inlined 90 * ICScripts to the lifetime of the JitScript itself. 91 * 92 * We store pointers to ICScripts in two other places: on the stack in 93 * BaselineFrame, and in IC stubs for CallInlinedFunction. 94 * 95 * The ICScript pointer in a BaselineFrame either points to the 96 * ICScript embedded in the JitScript for that frame, or to an inlined 97 * ICScript owned by a caller. In each case, there must be a frame on 98 * the stack corresponding to the JitScript that owns the current 99 * ICScript, which will keep the ICScript alive. 100 * 101 * Each ICStub is owned by an ICScript and, indirectly, a 102 * JitScript. An ICStub that uses CallInlinedFunction contains an 103 * ICScript for use by the callee. The ICStub and the callee ICScript 104 * are always owned by the same JitScript, so the callee ICScript will 105 * not be freed while the ICStub is alive. 106 * 107 * The lifetime of an ICScript is independent of the lifetimes of the 108 * BaselineScript and IonScript/WarpScript to which it 109 * corresponds. They can be destroyed and recreated, and the ICScript 110 * will remain valid. 111 * 112 * When we discard JIT code, we mark ICScripts that are active on the stack as 113 * active and then purge all of the inactive ICScripts. We also purge ICStubs, 114 * including the CallInlinedFunction stub at the trial inining call site, and 115 * reset the ICStates to allow trial inlining again later. 116 * 117 * If there's a BaselineFrame for an inlined ICScript, we'll preserve both this 118 * ICScript and the IC chain for the call site in the caller's ICScript. 119 * See ICScript::purgeStubs and ICScript::purgeInactiveICScripts. 120 */ 121 122 class alignas(uintptr_t) ICScript final : public TrailingArray<ICScript> { 123 public: 124 ICScript(uint32_t warmUpCount, Offset fallbackStubsOffset, Offset endOffset, 125 uint32_t depth, uint32_t bytecodeSize, 126 InliningRoot* inliningRoot = nullptr) 127 : inliningRoot_(inliningRoot), 128 warmUpCount_(warmUpCount), 129 fallbackStubsOffset_(fallbackStubsOffset), 130 endOffset_(endOffset), 131 depth_(depth), 132 bytecodeSize_(bytecodeSize) {} 133 134 ~ICScript(); 135 136 bool isInlined() const { return depth_ > 0; } 137 138 void initICEntries(JSContext* cx, JSScript* script); 139 140 ICEntry& icEntry(size_t index) { 141 MOZ_ASSERT(index < numICEntries()); 142 return icEntries()[index]; 143 } 144 145 ICFallbackStub* fallbackStub(size_t index) { 146 MOZ_ASSERT(index < numICEntries()); 147 return fallbackStubs() + index; 148 } 149 150 ICEntry* icEntryForStub(const ICFallbackStub* stub) { 151 size_t index = stub - fallbackStubs(); 152 MOZ_ASSERT(index < numICEntries()); 153 return &icEntry(index); 154 } 155 ICFallbackStub* fallbackStubForICEntry(const ICEntry* entry) { 156 size_t index = entry - icEntries(); 157 MOZ_ASSERT(index < numICEntries()); 158 return fallbackStub(index); 159 } 160 161 InliningRoot* inliningRoot() const { return inliningRoot_; } 162 uint32_t depth() const { return depth_; } 163 164 uint32_t bytecodeSize() const { return bytecodeSize_; } 165 166 void resetWarmUpCount(uint32_t count) { warmUpCount_ = count; } 167 168 static constexpr size_t offsetOfFirstStub(uint32_t entryIndex) { 169 return sizeof(ICScript) + entryIndex * sizeof(ICEntry) + 170 ICEntry::offsetOfFirstStub(); 171 } 172 173 static constexpr Offset offsetOfWarmUpCount() { 174 return offsetof(ICScript, warmUpCount_); 175 } 176 static constexpr Offset offsetOfDepth() { return offsetof(ICScript, depth_); } 177 178 static constexpr Offset offsetOfICEntries() { return sizeof(ICScript); } 179 uint32_t numICEntries() const { 180 return numElements<ICEntry>(icEntriesOffset(), fallbackStubsOffset()); 181 } 182 183 static constexpr Offset offsetOfEnvAllocSite() { 184 return offsetof(ICScript, envAllocSite_); 185 } 186 187 ICEntry* interpreterICEntryFromPCOffset(uint32_t pcOffset); 188 189 ICEntry& icEntryFromPCOffset(uint32_t pcOffset); 190 191 [[nodiscard]] bool addInlinedChild(JSContext* cx, 192 js::UniquePtr<ICScript> child, 193 uint32_t pcOffset); 194 ICScript* findInlinedChild(uint32_t pcOffset); 195 void removeInlinedChild(uint32_t pcOffset); 196 bool hasInlinedChild(uint32_t pcOffset); 197 198 void purgeStubs(Zone* zone, ICStubSpace& newStubSpace); 199 200 void purgeInactiveICScripts(); 201 202 bool active() const { return active_; } 203 void setActive() { active_ = true; } 204 void resetActive() { active_ = false; } 205 206 gc::AllocSite* getOrCreateAllocSite(JSScript* outerScript, uint32_t pcOffset); 207 208 void ensureEnvAllocSite(JSScript* outerScript); 209 gc::AllocSite* maybeEnvAllocSite() const { return envAllocSite_; } 210 211 void prepareForDestruction(Zone* zone); 212 213 void trace(JSTracer* trc); 214 bool traceWeak(JSTracer* trc); 215 216 #ifdef DEBUG 217 mozilla::HashNumber hash(JSContext* cx); 218 #endif 219 220 private: 221 class CallSite { 222 public: 223 CallSite(ICScript* callee, uint32_t pcOffset) 224 : callee_(callee), pcOffset_(pcOffset) {} 225 ICScript* callee_; 226 uint32_t pcOffset_; 227 }; 228 229 // If this ICScript was created for trial inlining or has another 230 // ICScript inlined into it, a pointer to the root of the inlining 231 // tree. Otherwise, nullptr. 232 InliningRoot* inliningRoot_ = nullptr; 233 234 // ICScripts that have been inlined into this ICScript. 235 js::UniquePtr<Vector<CallSite>> inlinedChildren_; 236 237 // List of allocation sites referred to by ICs in this script. 238 static constexpr size_t AllocSiteChunkSize = 256; 239 LifoAlloc allocSitesSpace_{AllocSiteChunkSize, js::BackgroundMallocArena}; 240 Vector<gc::AllocSite*, 0, SystemAllocPolicy> allocSites_; 241 242 // Optional alloc site to use when allocating environment chain objects. 243 gc::AllocSite* envAllocSite_ = nullptr; 244 245 // Number of times this copy of the script has been called or has had 246 // backedges taken. Reset if the script's JIT code is forcibly discarded. 247 // See also the ScriptWarmUpData class. 248 mozilla::Atomic<uint32_t, mozilla::Relaxed> warmUpCount_ = {}; 249 250 // The offset of the ICFallbackStub array. 251 Offset fallbackStubsOffset_; 252 253 // The size of this allocation. 254 Offset endOffset_; 255 256 // The inlining depth of this ICScript. 0 for the inlining root. 257 uint32_t depth_; 258 259 // Bytecode size of the JSScript corresponding to this ICScript. 260 uint32_t bytecodeSize_; 261 262 // Flag set when discarding JIT code to indicate this script is on the stack 263 // and should not be discarded. 264 bool active_ = false; 265 266 Offset icEntriesOffset() const { return offsetOfICEntries(); } 267 Offset fallbackStubsOffset() const { return fallbackStubsOffset_; } 268 Offset endOffset() const { return endOffset_; } 269 270 public: 271 ICEntry* icEntries() { return offsetToPointer<ICEntry>(icEntriesOffset()); } 272 273 private: 274 ICFallbackStub* fallbackStubs() { 275 return offsetToPointer<ICFallbackStub>(fallbackStubsOffset()); 276 } 277 278 JitScript* outerJitScript(); 279 280 friend class JitScript; 281 }; 282 283 // [SMDOC] JitScript 284 // 285 // JitScript stores type inference data, Baseline ICs and other JIT-related data 286 // for a script. Scripts with a JitScript can run in the Baseline Interpreter. 287 // 288 // IC Data 289 // ======= 290 // All IC data for Baseline (Interpreter and JIT) is stored in an ICScript. Each 291 // JitScript contains an ICScript as the last field. Additional free-standing 292 // ICScripts may be created during trial inlining. Ion has its own IC chains 293 // stored in IonScript. 294 // 295 // For each IC we store an ICEntry, which points to the first ICStub in the 296 // chain, and an ICFallbackStub. Note that multiple stubs in the same zone can 297 // share Baseline IC code. This works because the stub data is stored in the 298 // ICStub instead of baked in in the stub code. 299 // 300 // Storing this separate from BaselineScript allows us to use the same ICs in 301 // the Baseline Interpreter and Baseline JIT. It also simplifies debug mode OSR 302 // because the JitScript can be reused when we have to recompile the 303 // BaselineScript. 304 // 305 // An ICScript contains a list of IC entries and a list of fallback stubs. 306 // There's one ICEntry and ICFallbackStub for each JOF_IC bytecode op. 307 // 308 // The ICScript also contains the warmUpCount for the script. 309 // 310 // Inlining Data 311 // ============= 312 // JitScript also contains a list of Warp compilations inlining this script, for 313 // invalidation. 314 // 315 // Memory Layout 316 // ============= 317 // JitScript contains an ICScript as the last field. ICScript has trailing 318 // (variable length) arrays for ICEntry and ICFallbackStub. The memory layout is 319 // as follows: 320 // 321 // Item | Offset 322 // ------------------------+------------------------ 323 // JitScript | 0 324 // -->ICScript (field) | 325 // ICEntry[] | icEntriesOffset() 326 // ICFallbackStub[] | fallbackStubsOffset() 327 // 328 // These offsets are also used to compute numICEntries. 329 class alignas(uintptr_t) JitScript final 330 : public mozilla::LinkedListElement<JitScript>, 331 public TrailingArray<JitScript> { 332 friend class ::JSScript; 333 334 // Profile string used by the profiler for Baseline Interpreter frames. 335 const char* profileString_ = nullptr; 336 337 HeapPtr<JSScript*> owningScript_; 338 339 // Baseline code for the script. Either nullptr, BaselineDisabledScriptPtr, 340 // BaselineQueuedScriptPtr, BaselineCompilingScriptPtr, 341 // or a valid BaselineScript*. 342 GCStructPtr<BaselineScript*> baselineScript_; 343 344 // Ion code for this script. Either nullptr, IonDisabledScriptPtr, 345 // IonCompilingScriptPtr or a valid IonScript*. 346 GCStructPtr<IonScript*> ionScript_; 347 348 // For functions that need a CallObject and/or NamedLambdaObject, the template 349 // objects used by the Baseline JIT and Ion. If the function needs both a 350 // named lambda object and a call object, the named lambda object template is 351 // linked via the call object's enclosing environment. This field is set the 352 // first time the Baseline JIT compiles this script. 353 mozilla::Maybe<HeapPtr<EnvironmentObject*>> templateEnv_; 354 355 // The size of this allocation. 356 Offset endOffset_ = 0; 357 358 // Analysis data computed lazily the first time this script is compiled or 359 // inlined by WarpBuilder. 360 mozilla::Maybe<bool> usesEnvironmentChain_; 361 362 struct Flags { 363 // True if this script entered Ion via OSR at a loop header. 364 bool hadIonOSR : 1; 365 bool ranBytecodeAnalysis : 1; 366 }; 367 Flags flags_ = {}; // Zero-initialize flags. 368 369 js::UniquePtr<InliningRoot> inliningRoot_; 370 371 #ifdef DEBUG 372 // If the last warp compilation invalidated because of TranspiledCacheIR 373 // bailouts, this is a hash of the ICScripts used in that compilation. 374 // When recompiling, we assert that the hash has changed. 375 mozilla::Maybe<mozilla::HashNumber> failedICHash_; 376 377 // To avoid pathological cases, we skip the check if we have purged 378 // stubs due to GC pressure. 379 bool hasPurgedStubs_ = false; 380 #endif 381 382 // Value of the warmup counter when the last IC stub was attached, 383 // used for Ion hints. 384 uint32_t warmUpCountAtLastICStub_ = 0; 385 386 ICScript icScript_; 387 // End of fields. 388 389 Offset endOffset() const { return endOffset_; } 390 391 public: 392 JitScript(JSScript* script, Offset fallbackStubsOffset, Offset endOffset, 393 const char* profileString); 394 395 ~JitScript(); 396 397 JSScript* owningScript() const { return owningScript_; } 398 399 [[nodiscard]] bool ensureHasCachedBaselineJitData(JSContext* cx, 400 HandleScript script); 401 [[nodiscard]] bool ensureHasCachedIonData(JSContext* cx, HandleScript script); 402 403 void setHadIonOSR() { flags_.hadIonOSR = true; } 404 bool hadIonOSR() const { return flags_.hadIonOSR; } 405 406 void setRanBytecodeAnalysis() { flags_.ranBytecodeAnalysis = true; } 407 bool ranBytecodeAnalysis() const { return flags_.ranBytecodeAnalysis; } 408 409 uint32_t numICEntries() const { return icScript_.numICEntries(); } 410 411 #ifdef DEBUG 412 bool hasActiveICScript() const; 413 #endif 414 void resetAllActiveFlags(); 415 416 void ensureProfileString(JSContext* cx, JSScript* script); 417 void ensureProfilerScriptSource(JSContext* cx, JSScript* script); 418 419 const char* profileString() const { 420 MOZ_ASSERT(profileString_); 421 return profileString_; 422 } 423 424 static void Destroy(Zone* zone, JitScript* script); 425 426 static constexpr Offset offsetOfICEntries() { return sizeof(JitScript); } 427 428 static constexpr size_t offsetOfBaselineScript() { 429 return offsetof(JitScript, baselineScript_); 430 } 431 static constexpr size_t offsetOfIonScript() { 432 return offsetof(JitScript, ionScript_); 433 } 434 static constexpr size_t offsetOfICScript() { 435 return offsetof(JitScript, icScript_); 436 } 437 static constexpr size_t offsetOfWarmUpCount() { 438 return offsetOfICScript() + ICScript::offsetOfWarmUpCount(); 439 } 440 441 uint32_t warmUpCount() const { return icScript_.warmUpCount_; } 442 void incWarmUpCount() { icScript_.warmUpCount_++; } 443 void resetWarmUpCount(uint32_t count); 444 445 void prepareForDestruction(Zone* zone); 446 447 void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* data, 448 size_t* allocSites) const; 449 450 ICEntry& icEntry(size_t index) { return icScript_.icEntry(index); } 451 452 ICFallbackStub* fallbackStub(size_t index) { 453 return icScript_.fallbackStub(index); 454 } 455 456 ICEntry* icEntryForStub(const ICFallbackStub* stub) { 457 return icScript_.icEntryForStub(stub); 458 } 459 ICFallbackStub* fallbackStubForICEntry(const ICEntry* entry) { 460 return icScript_.fallbackStubForICEntry(entry); 461 } 462 463 void trace(JSTracer* trc); 464 void traceWeak(JSTracer* trc); 465 void purgeStubs(JSScript* script, ICStubSpace& newStubSpace); 466 467 void purgeInactiveICScripts(); 468 469 ICEntry& icEntryFromPCOffset(uint32_t pcOffset) { 470 return icScript_.icEntryFromPCOffset(pcOffset); 471 }; 472 473 size_t allocBytes() const { return endOffset(); } 474 475 EnvironmentObject* templateEnvironment() const { return templateEnv_.ref(); } 476 477 std::pair<CallObject*, NamedLambdaObject*> functionEnvironmentTemplates( 478 JSFunction* fun) const; 479 480 bool usesEnvironmentChain() const { return *usesEnvironmentChain_; } 481 482 bool resetAllocSites(bool resetNurserySites, bool resetPretenuredSites); 483 bool hasPretenuredAllocSites(); 484 485 void updateLastICStubCounter() { warmUpCountAtLastICStub_ = warmUpCount(); } 486 uint32_t warmUpCountAtLastICStub() const { return warmUpCountAtLastICStub_; } 487 488 bool hasEnvAllocSite() const { return icScript_.envAllocSite_; } 489 490 private: 491 // Methods to set baselineScript_ to a BaselineScript*, nullptr, or 492 // BaselineDisabledScriptPtr. 493 void setBaselineScriptImpl(JSScript* script, BaselineScript* baselineScript); 494 void setBaselineScriptImpl(JS::GCContext* gcx, JSScript* script, 495 BaselineScript* baselineScript); 496 497 public: 498 // Methods for getting/setting/clearing a BaselineScript*. 499 bool hasBaselineScript() const { 500 bool res = baselineScript_ && 501 baselineScript_ != BaselineDisabledScriptPtr && 502 baselineScript_ != BaselineQueuedScriptPtr && 503 baselineScript_ != BaselineCompilingScriptPtr; 504 MOZ_ASSERT_IF(!res, !hasIonScript()); 505 return res; 506 } 507 BaselineScript* baselineScript() const { 508 MOZ_ASSERT(hasBaselineScript()); 509 return baselineScript_; 510 } 511 void setBaselineScript(JSScript* script, BaselineScript* baselineScript) { 512 MOZ_ASSERT(!hasBaselineScript()); 513 setBaselineScriptImpl(script, baselineScript); 514 MOZ_ASSERT(hasBaselineScript()); 515 } 516 [[nodiscard]] BaselineScript* clearBaselineScript(JS::GCContext* gcx, 517 JSScript* script) { 518 BaselineScript* baseline = baselineScript(); 519 setBaselineScriptImpl(gcx, script, nullptr); 520 return baseline; 521 } 522 bool isBaselineQueued() const { 523 return baselineScript_ == BaselineQueuedScriptPtr; 524 } 525 void clearIsBaselineQueued(JSScript* script) { 526 MOZ_ASSERT(isBaselineQueued()); 527 setBaselineScriptImpl(script, nullptr); 528 } 529 bool isBaselineCompiling() const { 530 return baselineScript_ == BaselineCompilingScriptPtr; 531 } 532 void setIsBaselineCompiling(JSScript* script) { 533 MOZ_ASSERT(baselineScript_ == nullptr); 534 setBaselineScriptImpl(script, BaselineCompilingScriptPtr); 535 } 536 void clearIsBaselineCompiling(JSScript* script) { 537 MOZ_ASSERT(isBaselineCompiling()); 538 setBaselineScriptImpl(script, nullptr); 539 } 540 541 private: 542 // Methods to set ionScript_ to an IonScript*, nullptr, or one of the special 543 // Ion{Disabled,Compiling}ScriptPtr values. 544 void setIonScriptImpl(JS::GCContext* gcx, JSScript* script, 545 IonScript* ionScript); 546 void setIonScriptImpl(JSScript* script, IonScript* ionScript); 547 548 // Helper that calls the passed function for the outer ICScript and for each 549 // inlined ICScript. 550 template <typename F> 551 void forEachICScript(const F& f); 552 template <typename F> 553 void forEachICScript(const F& f) const; 554 555 public: 556 // Methods for getting/setting/clearing an IonScript*. 557 bool hasIonScript() const { 558 bool res = ionScript_ && ionScript_ != IonDisabledScriptPtr && 559 ionScript_ != IonCompilingScriptPtr; 560 MOZ_ASSERT_IF(res, baselineScript_); 561 return res; 562 } 563 IonScript* ionScript() const { 564 MOZ_ASSERT(hasIonScript()); 565 return ionScript_; 566 } 567 void setIonScript(JSScript* script, IonScript* ionScript) { 568 MOZ_ASSERT(!hasIonScript()); 569 setIonScriptImpl(script, ionScript); 570 MOZ_ASSERT(hasIonScript()); 571 } 572 [[nodiscard]] IonScript* clearIonScript(JS::GCContext* gcx, 573 JSScript* script) { 574 IonScript* ion = ionScript(); 575 setIonScriptImpl(gcx, script, nullptr); 576 return ion; 577 } 578 579 // Methods for off-thread compilation. 580 bool isIonCompilingOffThread() const { 581 return ionScript_ == IonCompilingScriptPtr; 582 } 583 void setIsIonCompilingOffThread(JSScript* script) { 584 MOZ_ASSERT(ionScript_ == nullptr); 585 setIonScriptImpl(script, IonCompilingScriptPtr); 586 } 587 void clearIsIonCompilingOffThread(JSScript* script) { 588 MOZ_ASSERT(isIonCompilingOffThread()); 589 setIonScriptImpl(script, nullptr); 590 } 591 ICScript* icScript() { return &icScript_; } 592 593 bool hasInliningRoot() const { return !!inliningRoot_; } 594 InliningRoot* inliningRoot() const { return inliningRoot_.get(); } 595 InliningRoot* getOrCreateInliningRoot(JSContext* cx, JSScript* script); 596 597 inline void notePurgedStubs() { 598 #ifdef DEBUG 599 failedICHash_.reset(); 600 hasPurgedStubs_ = true; 601 #endif 602 } 603 604 #ifdef DEBUG 605 bool hasPurgedStubs() const { return hasPurgedStubs_; } 606 bool hasFailedICHash() const { return failedICHash_.isSome(); } 607 mozilla::HashNumber getFailedICHash() { return failedICHash_.extract(); } 608 void setFailedICHash(mozilla::HashNumber hash) { 609 MOZ_ASSERT(failedICHash_.isNothing()); 610 if (!hasPurgedStubs_) { 611 failedICHash_.emplace(hash); 612 } 613 } 614 #endif 615 616 inline void clearFailedICHash() { 617 #ifdef DEBUG 618 failedICHash_.reset(); 619 #endif 620 } 621 }; 622 623 // Ensures no JitScripts are purged in the current zone. 624 class MOZ_RAII AutoKeepJitScripts { 625 jit::JitZone* zone_; 626 bool prev_; 627 628 AutoKeepJitScripts(const AutoKeepJitScripts&) = delete; 629 void operator=(const AutoKeepJitScripts&) = delete; 630 631 public: 632 explicit inline AutoKeepJitScripts(JSContext* cx); 633 inline ~AutoKeepJitScripts(); 634 }; 635 636 // Mark ICScripts on the stack as active, so that they are not discarded 637 // during GC, and copy active Baseline IC stubs to the new stub space. 638 void MarkActiveICScriptsAndCopyStubs(Zone* zone, ICStubSpace& newStubSpace); 639 640 #ifdef JS_STRUCTURED_SPEW 641 void JitSpewBaselineICStats(JSScript* script, const char* dumpReason); 642 #endif 643 644 } // namespace jit 645 } // namespace js 646 647 #endif /* jit_JitScript_h */