Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / js / src / jit / RematerializedFrame.h
blob06f0c475a299197ec3fc630223ed569d23f1a073
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 jit_RematerializedFrame_h
8 #define jit_RematerializedFrame_h
10 #include "mozilla/Assertions.h"
12 #include <algorithm>
13 #include <stddef.h>
14 #include <stdint.h>
16 #include "jstypes.h"
18 #include "jit/JitFrames.h"
19 #include "jit/ScriptFromCalleeToken.h"
20 #include "js/GCVector.h"
21 #include "js/TypeDecls.h"
22 #include "js/UniquePtr.h"
23 #include "js/Value.h"
24 #include "vm/JSFunction.h"
25 #include "vm/JSScript.h"
26 #include "vm/Stack.h"
28 class JS_PUBLIC_API JSTracer;
30 namespace js {
32 class ArgumentsObject;
33 class CallObject;
35 namespace jit {
37 class InlineFrameIterator;
38 struct MaybeReadFallback;
40 // RematerializedFrame: An optimized frame that has been rematerialized with
41 // values read out of Snapshots.
43 // If the Debugger API tries to inspect or modify an IonMonkey frame, much of
44 // the information it expects to find in a frame is missing: function calls may
45 // have been inlined, variables may have been optimized out, and so on. So when
46 // this happens, SpiderMonkey builds one or more Rematerialized frames from the
47 // IonMonkey frame, using the snapshot metadata built by Ion to reconstruct the
48 // missing parts. The Rematerialized frames are now the authority on the state
49 // of those frames, and the Ion frame is ignored: stack iterators ignore the Ion
50 // frame, producing the Rematerialized frames in their stead; and when control
51 // returns to the Ion frame, we pop it, rebuild Baseline frames from the
52 // Rematerialized frames, and resume execution in Baseline.
53 class RematerializedFrame {
54 // See DebugScopes::updateLiveScopes.
55 bool prevUpToDate_;
57 // Propagated to the Baseline frame once this is popped.
58 bool isDebuggee_;
60 // Has an initial environment has been pushed on the environment chain for
61 // function frames that need a CallObject or eval frames that need a
62 // VarEnvironmentObject?
63 bool hasInitialEnv_;
65 // Is this frame constructing?
66 bool isConstructing_;
68 // If true, this frame has been on the stack when
69 // |js::SavedStacks::saveCurrentStack| was called, and so there is a
70 // |js::SavedFrame| object cached for this frame.
71 bool hasCachedSavedFrame_;
73 // The fp of the top frame associated with this possibly inlined frame.
74 uint8_t* top_;
76 // The bytecode at the time of rematerialization.
77 jsbytecode* pc_;
79 size_t frameNo_;
80 unsigned numActualArgs_;
82 JSScript* script_;
83 JSObject* envChain_;
84 JSFunction* callee_;
85 ArgumentsObject* argsObj_;
87 Value returnValue_;
88 Value thisArgument_;
89 Value slots_[1];
91 RematerializedFrame(JSContext* cx, uint8_t* top, unsigned numActualArgs,
92 InlineFrameIterator& iter, MaybeReadFallback& fallback);
94 public:
95 static RematerializedFrame* New(JSContext* cx, uint8_t* top,
96 InlineFrameIterator& iter,
97 MaybeReadFallback& fallback);
99 // RematerializedFrame are allocated on non-GC heap, so use GCVector and
100 // UniquePtr to ensure they are traced and cleaned up correctly.
101 using RematerializedFrameVector = GCVector<UniquePtr<RematerializedFrame>>;
103 // Rematerialize all remaining frames pointed to by |iter| into |frames|
104 // in older-to-younger order, e.g., frames[0] is the oldest frame.
105 [[nodiscard]] static bool RematerializeInlineFrames(
106 JSContext* cx, uint8_t* top, InlineFrameIterator& iter,
107 MaybeReadFallback& fallback, RematerializedFrameVector& frames);
109 bool prevUpToDate() const { return prevUpToDate_; }
110 void setPrevUpToDate() { prevUpToDate_ = true; }
111 void unsetPrevUpToDate() { prevUpToDate_ = false; }
113 bool isDebuggee() const { return isDebuggee_; }
114 void setIsDebuggee() { isDebuggee_ = true; }
115 inline void unsetIsDebuggee();
117 uint8_t* top() const { return top_; }
118 JSScript* outerScript() const {
119 JitFrameLayout* jsFrame = (JitFrameLayout*)top_;
120 return ScriptFromCalleeToken(jsFrame->calleeToken());
122 jsbytecode* pc() const { return pc_; }
123 size_t frameNo() const { return frameNo_; }
124 bool inlined() const { return frameNo_ > 0; }
126 JSObject* environmentChain() const { return envChain_; }
128 template <typename SpecificEnvironment>
129 void pushOnEnvironmentChain(SpecificEnvironment& env) {
130 MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment());
131 envChain_ = &env;
132 if (IsFrameInitialEnvironment(this, env)) {
133 hasInitialEnv_ = true;
137 template <typename SpecificEnvironment>
138 void popOffEnvironmentChain() {
139 MOZ_ASSERT(envChain_->is<SpecificEnvironment>());
140 envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment();
143 [[nodiscard]] bool initFunctionEnvironmentObjects(JSContext* cx);
144 [[nodiscard]] bool pushVarEnvironment(JSContext* cx, Handle<Scope*> scope);
146 bool hasInitialEnvironment() const { return hasInitialEnv_; }
147 CallObject& callObj() const;
149 bool hasArgsObj() const { return !!argsObj_; }
150 ArgumentsObject& argsObj() const {
151 MOZ_ASSERT(hasArgsObj());
152 MOZ_ASSERT(script()->needsArgsObj());
153 return *argsObj_;
156 bool isFunctionFrame() const { return script_->isFunction(); }
157 bool isGlobalFrame() const { return script_->isGlobalCode(); }
158 bool isModuleFrame() const { return script_->isModule(); }
160 JSScript* script() const { return script_; }
161 JSFunction* callee() const {
162 MOZ_ASSERT(isFunctionFrame());
163 MOZ_ASSERT(callee_);
164 return callee_;
166 Value calleev() const { return ObjectValue(*callee()); }
167 Value& thisArgument() { return thisArgument_; }
169 bool isConstructing() const { return isConstructing_; }
171 bool hasCachedSavedFrame() const { return hasCachedSavedFrame_; }
173 void setHasCachedSavedFrame() { hasCachedSavedFrame_ = true; }
175 void clearHasCachedSavedFrame() { hasCachedSavedFrame_ = false; }
177 unsigned numFormalArgs() const {
178 return isFunctionFrame() ? callee()->nargs() : 0;
180 unsigned numActualArgs() const { return numActualArgs_; }
181 unsigned numArgSlots() const {
182 return (std::max)(numFormalArgs(), numActualArgs());
185 Value* argv() { return slots_; }
186 Value* locals() { return slots_ + numArgSlots(); }
188 Value& unaliasedLocal(unsigned i) {
189 MOZ_ASSERT(i < script()->nfixed());
190 return locals()[i];
192 Value& unaliasedFormal(unsigned i,
193 MaybeCheckAliasing checkAliasing = CHECK_ALIASING) {
194 MOZ_ASSERT(i < numFormalArgs());
195 MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals() &&
196 !script()->formalIsAliased(i));
197 return argv()[i];
199 Value& unaliasedActual(unsigned i,
200 MaybeCheckAliasing checkAliasing = CHECK_ALIASING) {
201 MOZ_ASSERT(i < numActualArgs());
202 MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
203 MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(),
204 !script()->formalIsAliased(i));
205 return argv()[i];
208 void setReturnValue(const Value& value) { returnValue_ = value; }
210 Value& returnValue() {
211 MOZ_ASSERT(!script()->noScriptRval());
212 return returnValue_;
215 void trace(JSTracer* trc);
216 void dump();
219 } // namespace jit
220 } // namespace js
222 #endif // jit_RematerializedFrame_h