Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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_RematerializedFrame_h
8 : #define jit_RematerializedFrame_h
9 :
10 : #include <algorithm>
11 :
12 : #include "jsfun.h"
13 :
14 : #include "jit/JitFrameIterator.h"
15 : #include "jit/JitFrames.h"
16 :
17 : #include "vm/EnvironmentObject.h"
18 : #include "vm/Stack.h"
19 :
20 : namespace js {
21 : namespace jit {
22 :
23 : //
24 : // An optimized frame that has been rematerialized with values read out of
25 : // Snapshots.
26 : //
27 : class RematerializedFrame
28 : {
29 : // See DebugScopes::updateLiveScopes.
30 : bool prevUpToDate_;
31 :
32 : // Propagated to the Baseline frame once this is popped.
33 : bool isDebuggee_;
34 :
35 : // Has an initial environment has been pushed on the environment chain for
36 : // function frames that need a CallObject or eval frames that need a
37 : // VarEnvironmentObject?
38 : bool hasInitialEnv_;
39 :
40 : // Is this frame constructing?
41 : bool isConstructing_;
42 :
43 : // If true, this frame has been on the stack when
44 : // |js::SavedStacks::saveCurrentStack| was called, and so there is a
45 : // |js::SavedFrame| object cached for this frame.
46 : bool hasCachedSavedFrame_;
47 :
48 : // The fp of the top frame associated with this possibly inlined frame.
49 : uint8_t* top_;
50 :
51 : // The bytecode at the time of rematerialization.
52 : jsbytecode* pc_;
53 :
54 : size_t frameNo_;
55 : unsigned numActualArgs_;
56 :
57 : JSScript* script_;
58 : JSObject* envChain_;
59 : JSFunction* callee_;
60 : ArgumentsObject* argsObj_;
61 :
62 : Value returnValue_;
63 : Value thisArgument_;
64 : Value newTarget_;
65 : Value slots_[1];
66 :
67 : RematerializedFrame(JSContext* cx, uint8_t* top, unsigned numActualArgs,
68 : InlineFrameIterator& iter, MaybeReadFallback& fallback);
69 :
70 : public:
71 : static RematerializedFrame* New(JSContext* cx, uint8_t* top, InlineFrameIterator& iter,
72 : MaybeReadFallback& fallback);
73 :
74 : // Rematerialize all remaining frames pointed to by |iter| into |frames|
75 : // in older-to-younger order, e.g., frames[0] is the oldest frame.
76 : static MOZ_MUST_USE bool RematerializeInlineFrames(JSContext* cx, uint8_t* top,
77 : InlineFrameIterator& iter,
78 : MaybeReadFallback& fallback,
79 : GCVector<RematerializedFrame*>& frames);
80 :
81 : // Free a vector of RematerializedFrames; takes care to call the
82 : // destructor. Also clears the vector.
83 : static void FreeInVector(GCVector<RematerializedFrame*>& frames);
84 :
85 0 : bool prevUpToDate() const {
86 0 : return prevUpToDate_;
87 : }
88 0 : void setPrevUpToDate() {
89 0 : prevUpToDate_ = true;
90 0 : }
91 0 : void unsetPrevUpToDate() {
92 0 : prevUpToDate_ = false;
93 0 : }
94 :
95 0 : bool isDebuggee() const {
96 0 : return isDebuggee_;
97 : }
98 0 : void setIsDebuggee() {
99 0 : isDebuggee_ = true;
100 0 : }
101 0 : void unsetIsDebuggee() {
102 0 : MOZ_ASSERT(!script()->isDebuggee());
103 0 : isDebuggee_ = false;
104 0 : }
105 :
106 0 : uint8_t* top() const {
107 0 : return top_;
108 : }
109 0 : JSScript* outerScript() const {
110 0 : JitFrameLayout* jsFrame = (JitFrameLayout*)top_;
111 0 : return ScriptFromCalleeToken(jsFrame->calleeToken());
112 : }
113 0 : jsbytecode* pc() const {
114 0 : return pc_;
115 : }
116 0 : size_t frameNo() const {
117 0 : return frameNo_;
118 : }
119 0 : bool inlined() const {
120 0 : return frameNo_ > 0;
121 : }
122 :
123 0 : JSObject* environmentChain() const {
124 0 : return envChain_;
125 : }
126 :
127 : template <typename SpecificEnvironment>
128 0 : void pushOnEnvironmentChain(SpecificEnvironment& env) {
129 0 : MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment());
130 0 : envChain_ = &env;
131 0 : if (IsFrameInitialEnvironment(this, env))
132 0 : hasInitialEnv_ = true;
133 0 : }
134 :
135 : template <typename SpecificEnvironment>
136 0 : void popOffEnvironmentChain() {
137 0 : MOZ_ASSERT(envChain_->is<SpecificEnvironment>());
138 0 : envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment();
139 0 : }
140 :
141 : MOZ_MUST_USE bool initFunctionEnvironmentObjects(JSContext* cx);
142 : MOZ_MUST_USE bool pushVarEnvironment(JSContext* cx, HandleScope scope);
143 :
144 0 : bool hasInitialEnvironment() const {
145 0 : return hasInitialEnv_;
146 : }
147 : CallObject& callObj() const;
148 :
149 0 : bool hasArgsObj() const {
150 0 : return !!argsObj_;
151 : }
152 0 : ArgumentsObject& argsObj() const {
153 0 : MOZ_ASSERT(hasArgsObj());
154 0 : MOZ_ASSERT(script()->needsArgsObj());
155 0 : return *argsObj_;
156 : }
157 :
158 0 : bool isFunctionFrame() const {
159 0 : return !!script_->functionNonDelazifying();
160 : }
161 0 : bool isGlobalFrame() const {
162 0 : return script_->isGlobalCode();
163 : }
164 0 : bool isModuleFrame() const {
165 0 : return script_->module();
166 : }
167 :
168 0 : JSScript* script() const {
169 0 : return script_;
170 : }
171 0 : JSFunction* callee() const {
172 0 : MOZ_ASSERT(isFunctionFrame());
173 0 : MOZ_ASSERT(callee_);
174 0 : return callee_;
175 : }
176 : Value calleev() const {
177 : return ObjectValue(*callee());
178 : }
179 0 : Value& thisArgument() {
180 0 : return thisArgument_;
181 : }
182 :
183 0 : bool isConstructing() const {
184 0 : return isConstructing_;
185 : }
186 :
187 0 : bool hasCachedSavedFrame() const {
188 0 : return hasCachedSavedFrame_;
189 : }
190 :
191 0 : void setHasCachedSavedFrame() {
192 0 : hasCachedSavedFrame_ = true;
193 0 : }
194 :
195 0 : unsigned numFormalArgs() const {
196 0 : return isFunctionFrame() ? callee()->nargs() : 0;
197 : }
198 0 : unsigned numActualArgs() const {
199 0 : return numActualArgs_;
200 : }
201 0 : unsigned numArgSlots() const {
202 0 : return (std::max)(numFormalArgs(), numActualArgs());
203 : }
204 :
205 0 : Value* argv() {
206 0 : return slots_;
207 : }
208 0 : Value* locals() {
209 0 : return slots_ + numArgSlots();
210 : }
211 :
212 0 : Value& unaliasedLocal(unsigned i) {
213 0 : MOZ_ASSERT(i < script()->nfixed());
214 0 : return locals()[i];
215 : }
216 0 : Value& unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) {
217 0 : MOZ_ASSERT(i < numFormalArgs());
218 0 : MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals() &&
219 : !script()->formalIsAliased(i));
220 0 : return argv()[i];
221 : }
222 0 : Value& unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) {
223 0 : MOZ_ASSERT(i < numActualArgs());
224 0 : MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
225 0 : MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
226 0 : return argv()[i];
227 : }
228 :
229 0 : Value newTarget() {
230 0 : MOZ_ASSERT(isFunctionFrame());
231 0 : if (callee()->isArrow())
232 0 : return callee()->getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
233 0 : MOZ_ASSERT_IF(!isConstructing(), newTarget_.isUndefined());
234 0 : return newTarget_;
235 : }
236 :
237 0 : void setReturnValue(const Value& value) {
238 0 : returnValue_ = value;
239 0 : }
240 :
241 0 : Value& returnValue() {
242 0 : return returnValue_;
243 : }
244 :
245 : void trace(JSTracer* trc);
246 : void dump();
247 : };
248 :
249 : } // namespace jit
250 : } // namespace js
251 :
252 : namespace JS {
253 :
254 : template <>
255 : struct MapTypeToRootKind<js::jit::RematerializedFrame*>
256 : {
257 : static const RootKind kind = RootKind::Traceable;
258 : };
259 :
260 : template <>
261 : struct GCPolicy<js::jit::RematerializedFrame*>
262 : {
263 : static js::jit::RematerializedFrame* initial() {
264 : return nullptr;
265 : }
266 :
267 0 : static void trace(JSTracer* trc, js::jit::RematerializedFrame** frame, const char* name) {
268 0 : if (*frame)
269 0 : (*frame)->trace(trc);
270 0 : }
271 : };
272 :
273 : } // namespace JS
274 :
275 : #endif // jit_RematerializedFrame_h
|