Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / js / src / vm / JitActivation.h
blobbe2d63066cd509e3f7315e8c76b6178a67e25b45
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/. */
7 #ifndef vm_JitActivation_h
8 #define vm_JitActivation_h
10 #include "mozilla/Assertions.h" // MOZ_ASSERT
11 #include "mozilla/Atomics.h" // mozilla::Atomic, mozilla::Relaxed
12 #include "mozilla/Maybe.h" // mozilla::Maybe
14 #include <stddef.h> // size_t
15 #include <stdint.h> // uint8_t, uint32_t, uintptr_t
17 #include "jstypes.h" // JS_PUBLIC_API
19 #include "jit/IonTypes.h" // CHECK_OSIPOINT_REGISTERS
20 #include "jit/JSJitFrameIter.h" // js::jit::{JSJitFrameIter,RInstructionResults}
21 #ifdef CHECK_OSIPOINT_REGISTERS
22 # include "jit/Registers.h" // js::jit::RegisterDump
23 #endif
24 #include "jit/RematerializedFrame.h" // js::jit::RematerializedFrame
25 #include "js/GCVector.h" // JS::GCVector
26 #include "js/HashTable.h" // js::HashMap
27 #include "js/UniquePtr.h" // js::UniquePtr
28 #include "vm/Activation.h" // js::Activation
29 #include "wasm/WasmCodegenTypes.h" // js::wasm::TrapData
30 #include "wasm/WasmConstants.h" // js::wasm::Trap
31 #include "wasm/WasmFrame.h" // js::wasm::Frame
32 #include "wasm/WasmFrameIter.h" // js::wasm::{ExitReason,RegisterState,WasmFrameIter}
34 struct JS_PUBLIC_API JSContext;
35 class JS_PUBLIC_API JSTracer;
37 namespace js {
39 namespace jit {
41 class BailoutFrameInfo;
43 // A JitActivation is used for frames running in Baseline or Ion.
44 class JitActivation : public Activation {
45 // If Baseline, Ion or Wasm code is on the stack, and has called into C++,
46 // this will be aligned to an ExitFrame. The last bit indicates if it's a
47 // wasm frame (bit set to wasm::ExitOrJitEntryFPTag) or not
48 // (bit set to ~wasm::ExitOrJitEntryFPTag).
49 uint8_t* packedExitFP_;
51 // When hasWasmExitFP(), encodedWasmExitReason_ holds ExitReason.
52 uint32_t encodedWasmExitReason_;
54 JitActivation* prevJitActivation_;
56 // Rematerialized Ion frames which has info copied out of snapshots. Maps
57 // frame pointers (i.e. packedExitFP_) to a vector of rematerializations of
58 // all inline frames associated with that frame.
60 // This table is lazily initialized by calling getRematerializedFrame.
61 using RematerializedFrameVector =
62 JS::GCVector<js::UniquePtr<RematerializedFrame>>;
63 using RematerializedFrameTable =
64 js::HashMap<uint8_t*, RematerializedFrameVector>;
65 js::UniquePtr<RematerializedFrameTable> rematerializedFrames_;
67 // This vector is used to remember the outcome of the evaluation of recover
68 // instructions.
70 // RInstructionResults are appended into this vector when Snapshot values
71 // have to be read, or when the evaluation has to run before some mutating
72 // code. Each RInstructionResults belongs to one frame which has to bailout
73 // as soon as we get back to it.
74 using IonRecoveryMap = Vector<RInstructionResults, 1>;
75 IonRecoveryMap ionRecovery_;
77 // If we are bailing out from Ion, then this field should be a non-null
78 // pointer which references the BailoutFrameInfo used to walk the inner
79 // frames. This field is used for all newly constructed JSJitFrameIters to
80 // read the innermost frame information from this bailout data instead of
81 // reading it from the stack.
82 BailoutFrameInfo* bailoutData_;
84 // When profiling is enabled, these fields will be updated to reflect the
85 // last pushed frame for this activation, and if that frame has been
86 // left for a call, the native code site of the call.
87 mozilla::Atomic<JitFrameLayout*, mozilla::Relaxed> lastProfilingFrame_;
88 mozilla::Atomic<void*, mozilla::Relaxed> lastProfilingCallSite_;
89 static_assert(sizeof(mozilla::Atomic<void*, mozilla::Relaxed>) ==
90 sizeof(void*),
91 "Atomic should have same memory format as underlying type.");
93 // When wasm traps, the signal handler records some data for unwinding
94 // purposes. Wasm code can't trap reentrantly.
95 mozilla::Maybe<wasm::TrapData> wasmTrapData_;
97 void clearRematerializedFrames();
99 #ifdef CHECK_OSIPOINT_REGISTERS
100 protected:
101 // Used to verify that live registers don't change between a VM call and
102 // the OsiPoint that follows it. Protected to silence Clang warning.
103 uint32_t checkRegs_ = 0;
104 RegisterDump regs_;
105 #endif
107 public:
108 explicit JitActivation(JSContext* cx);
109 ~JitActivation();
111 bool isProfiling() const {
112 // All JitActivations can be profiled.
113 return true;
116 JitActivation* prevJitActivation() const { return prevJitActivation_; }
117 static size_t offsetOfPrevJitActivation() {
118 return offsetof(JitActivation, prevJitActivation_);
121 bool hasExitFP() const { return !!packedExitFP_; }
122 uint8_t* jsOrWasmExitFP() const {
123 if (hasWasmExitFP()) {
124 return wasm::Frame::untagExitFP(packedExitFP_);
126 return packedExitFP_;
128 static size_t offsetOfPackedExitFP() {
129 return offsetof(JitActivation, packedExitFP_);
132 bool hasJSExitFP() const { return !hasWasmExitFP(); }
134 uint8_t* jsExitFP() const {
135 MOZ_ASSERT(hasJSExitFP());
136 return packedExitFP_;
138 void setJSExitFP(uint8_t* fp) { packedExitFP_ = fp; }
140 uint8_t* packedExitFP() const { return packedExitFP_; }
141 void setPackedExitFP(uint8_t* fp) { packedExitFP_ = fp; }
143 #ifdef CHECK_OSIPOINT_REGISTERS
144 void setCheckRegs(bool check) { checkRegs_ = check; }
145 static size_t offsetOfCheckRegs() {
146 return offsetof(JitActivation, checkRegs_);
148 static size_t offsetOfRegs() { return offsetof(JitActivation, regs_); }
149 #endif
151 // Look up a rematerialized frame keyed by the fp, rematerializing the
152 // frame if one doesn't already exist. A frame can only be rematerialized
153 // if an IonFrameIterator pointing to the nearest uninlined frame can be
154 // provided, as values need to be read out of snapshots.
156 // The inlineDepth must be within bounds of the frame pointed to by iter.
157 RematerializedFrame* getRematerializedFrame(
158 JSContext* cx, const JSJitFrameIter& iter, size_t inlineDepth = 0,
159 MaybeReadFallback::FallbackConsequence consequence =
160 MaybeReadFallback::Fallback_Invalidate);
162 // Look up a rematerialized frame by the fp. If inlineDepth is out of
163 // bounds of what has been rematerialized, nullptr is returned.
164 RematerializedFrame* lookupRematerializedFrame(uint8_t* top,
165 size_t inlineDepth = 0);
167 // Remove all rematerialized frames associated with the fp top from the
168 // Debugger.
169 void removeRematerializedFramesFromDebugger(JSContext* cx, uint8_t* top);
171 bool hasRematerializedFrame(uint8_t* top, size_t inlineDepth = 0) {
172 return !!lookupRematerializedFrame(top, inlineDepth);
175 // Remove a previous rematerialization by fp.
176 void removeRematerializedFrame(uint8_t* top);
178 void traceRematerializedFrames(JSTracer* trc);
180 // Register the results of on Ion frame recovery.
181 bool registerIonFrameRecovery(RInstructionResults&& results);
183 // Return the pointer to the Ion frame recovery, if it is already registered.
184 RInstructionResults* maybeIonFrameRecovery(JitFrameLayout* fp);
186 // If an Ion frame recovery exists for the |fp| frame exists, then remove it
187 // from the activation.
188 void removeIonFrameRecovery(JitFrameLayout* fp);
190 void traceIonRecovery(JSTracer* trc);
192 // Return the bailout information if it is registered.
193 const BailoutFrameInfo* bailoutData() const { return bailoutData_; }
195 // Register the bailout data when it is constructed.
196 void setBailoutData(BailoutFrameInfo* bailoutData);
198 // Unregister the bailout data when the frame is reconstructed.
199 void cleanBailoutData();
201 static size_t offsetOfLastProfilingFrame() {
202 return offsetof(JitActivation, lastProfilingFrame_);
204 JitFrameLayout* lastProfilingFrame() { return lastProfilingFrame_; }
205 void setLastProfilingFrame(JitFrameLayout* ptr) { lastProfilingFrame_ = ptr; }
207 static size_t offsetOfLastProfilingCallSite() {
208 return offsetof(JitActivation, lastProfilingCallSite_);
210 void* lastProfilingCallSite() { return lastProfilingCallSite_; }
211 void setLastProfilingCallSite(void* ptr) { lastProfilingCallSite_ = ptr; }
213 // WebAssembly specific attributes.
214 bool hasWasmExitFP() const { return wasm::Frame::isExitFP(packedExitFP_); }
215 wasm::Frame* wasmExitFP() const {
216 MOZ_ASSERT(hasWasmExitFP());
217 return reinterpret_cast<wasm::Frame*>(
218 wasm::Frame::untagExitFP(packedExitFP_));
220 wasm::Instance* wasmExitInstance() const {
221 return wasm::GetNearestEffectiveInstance(wasmExitFP());
223 void setWasmExitFP(const wasm::Frame* fp) {
224 if (fp) {
225 MOZ_ASSERT(!wasm::Frame::isExitFP(fp));
226 packedExitFP_ = wasm::Frame::addExitFPTag(fp);
227 MOZ_ASSERT(hasWasmExitFP());
228 } else {
229 packedExitFP_ = nullptr;
232 wasm::ExitReason wasmExitReason() const {
233 MOZ_ASSERT(hasWasmExitFP());
234 return wasm::ExitReason::Decode(encodedWasmExitReason_);
236 static size_t offsetOfEncodedWasmExitReason() {
237 return offsetof(JitActivation, encodedWasmExitReason_);
240 void startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset,
241 const wasm::RegisterState& state);
242 void finishWasmTrap();
243 bool isWasmTrapping() const { return !!wasmTrapData_; }
244 const wasm::TrapData& wasmTrapData() { return *wasmTrapData_; }
247 // A filtering of the ActivationIterator to only stop at JitActivations.
248 class JitActivationIterator : public ActivationIterator {
249 void settle() {
250 while (!done() && !activation_->isJit()) {
251 ActivationIterator::operator++();
255 public:
256 explicit JitActivationIterator(JSContext* cx) : ActivationIterator(cx) {
257 settle();
260 JitActivationIterator& operator++() {
261 ActivationIterator::operator++();
262 settle();
263 return *this;
267 } // namespace jit
269 } // namespace js
271 #endif // vm_JitActivation_h