JitContext.h (4749B)
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_JitContext_h 8 #define jit_JitContext_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/Result.h" 12 13 #include <stdint.h> 14 15 #include "jstypes.h" 16 17 struct JS_PUBLIC_API JSContext; 18 19 namespace js { 20 namespace jit { 21 22 class CompileRealm; 23 class CompileRuntime; 24 class TempAllocator; 25 26 enum MethodStatus { 27 Method_Error, 28 Method_CantCompile, 29 Method_Skipped, 30 Method_Compiled 31 }; 32 33 // Use only even, non-zero values for errors, to allow using the UnusedZero and 34 // HasFreeLSB optimizations for mozilla::Result (see specializations of 35 // UnusedZero/HasFreeLSB below). 36 enum class AbortReason : uint8_t { 37 NoAbort, 38 Alloc = 2, 39 Disable = 4, 40 Error = 6, 41 }; 42 } // namespace jit 43 } // namespace js 44 45 namespace mozilla::detail { 46 47 template <> 48 struct UnusedZero<js::jit::AbortReason> : UnusedZeroEnum<js::jit::AbortReason> { 49 }; 50 51 template <> 52 struct HasFreeLSB<js::jit::AbortReason> { 53 static const bool value = true; 54 }; 55 56 } // namespace mozilla::detail 57 58 namespace js { 59 namespace jit { 60 61 template <typename V> 62 using AbortReasonOr = mozilla::Result<V, AbortReason>; 63 using mozilla::Err; 64 using mozilla::Ok; 65 66 static_assert(sizeof(AbortReasonOr<Ok>) <= sizeof(uintptr_t), 67 "Unexpected size of AbortReasonOr<Ok>"); 68 static_assert(mozilla::detail::SelectResultImpl<bool, AbortReason>::value == 69 mozilla::detail::PackingStrategy::NullIsOk); 70 static_assert(sizeof(AbortReasonOr<bool>) <= sizeof(uintptr_t), 71 "Unexpected size of AbortReasonOr<bool>"); 72 static_assert(sizeof(AbortReasonOr<uint16_t*>) == sizeof(uintptr_t), 73 "Unexpected size of AbortReasonOr<uint16_t*>"); 74 75 // A JIT context is needed for parts of the compiler backend such as the 76 // MacroAssembler. It points to the JSContext (nullptr for off-thread 77 // compilations or Wasm compilations) and also stores some extra information, 78 // most of it only used in debug builds. 79 // 80 // JIT contexts must not be nested. 81 82 class MOZ_RAII JitContext { 83 #ifdef DEBUG 84 // Whether this thread is actively Baseline compiling offthread 85 bool inBaselineBackend_ = false; 86 87 // Whether this thread is actively Ion compiling (does not include Wasm or 88 // WarpOracle). 89 bool inIonBackend_ = false; 90 91 bool isCompilingWasm_ = false; 92 bool oom_ = false; 93 #endif 94 95 public: 96 // Running context when compiling on the main thread. Not available during 97 // off-thread compilation. 98 JSContext* cx = nullptr; 99 100 // Wrapper with information about the current runtime. nullptr for Wasm 101 // compilations. 102 CompileRuntime* runtime = nullptr; 103 104 // Constructor for compilations happening on the main thread. 105 explicit JitContext(JSContext* cx); 106 107 // Constructor for off-thread Ion compilations. 108 explicit JitContext(CompileRuntime* rt); 109 110 // Constructor for Wasm compilation. 111 JitContext(); 112 113 ~JitContext(); 114 115 #ifdef DEBUG 116 bool isCompilingWasm() { return isCompilingWasm_; } 117 bool setIsCompilingWasm(bool flag) { 118 bool oldFlag = isCompilingWasm_; 119 isCompilingWasm_ = flag; 120 return oldFlag; 121 } 122 bool hasOOM() { return oom_; } 123 void setOOM() { oom_ = true; } 124 125 bool inBaselineBackend() const { return inBaselineBackend_; } 126 bool inIonBackend() const { return inIonBackend_; } 127 128 void enterBaselineBackend() { 129 MOZ_ASSERT(!inBaselineBackend_); 130 inBaselineBackend_ = true; 131 } 132 void leaveBaselineBackend() { 133 MOZ_ASSERT(inBaselineBackend_); 134 inBaselineBackend_ = false; 135 } 136 void enterIonBackend() { 137 MOZ_ASSERT(!inIonBackend_); 138 inIonBackend_ = true; 139 } 140 void leaveIonBackend() { 141 MOZ_ASSERT(inIonBackend_); 142 inIonBackend_ = false; 143 } 144 #endif 145 }; 146 147 // Process-wide initialization and shutdown of JIT data structures. 148 [[nodiscard]] bool InitializeJit(); 149 void ShutdownJit(); 150 151 // Get and set the current JIT context. 152 JitContext* GetJitContext(); 153 JitContext* MaybeGetJitContext(); 154 155 void SetJitContext(JitContext* ctx); 156 157 enum JitExecStatus { 158 // The method call had to be aborted due to a stack limit check. This 159 // error indicates that Ion never attempted to clean up frames. 160 JitExec_Aborted, 161 162 // The method call resulted in an error, and IonMonkey has cleaned up 163 // frames. 164 JitExec_Error, 165 166 // The method call succeeded and returned a value. 167 JitExec_Ok 168 }; 169 170 static inline bool IsErrorStatus(JitExecStatus status) { 171 return status == JitExec_Error || status == JitExec_Aborted; 172 } 173 174 bool JitSupportsWasmSimd(); 175 bool JitSupportsAtomics(); 176 177 } // namespace jit 178 } // namespace js 179 180 #endif /* jit_JitContext_h */