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 vm_Stack_inl_h
8 : #define vm_Stack_inl_h
9 :
10 : #include "vm/Stack.h"
11 :
12 : #include "mozilla/PodOperations.h"
13 :
14 : #include "jscntxt.h"
15 : #include "jsscript.h"
16 :
17 : #include "jit/BaselineFrame.h"
18 : #include "jit/RematerializedFrame.h"
19 : #include "js/Debug.h"
20 : #include "vm/EnvironmentObject.h"
21 : #include "vm/GeneratorObject.h"
22 : #include "wasm/WasmInstance.h"
23 :
24 : #include "jsobjinlines.h"
25 : #include "jsscriptinlines.h"
26 :
27 : #include "jit/BaselineFrame-inl.h"
28 :
29 : namespace js {
30 :
31 : /*
32 : * We cache name lookup results only for the global object or for native
33 : * non-global objects without prototype or with prototype that never mutates,
34 : * see bug 462734 and bug 487039.
35 : */
36 : static inline bool
37 437 : IsCacheableEnvironment(JSObject* obj)
38 : {
39 437 : bool cacheable = obj->is<CallObject>() || obj->is<LexicalEnvironmentObject>();
40 :
41 437 : MOZ_ASSERT_IF(cacheable, !obj->getOpsLookupProperty());
42 437 : return cacheable;
43 : }
44 :
45 : inline HandleObject
46 83550 : InterpreterFrame::environmentChain() const
47 : {
48 83550 : return HandleObject::fromMarkedLocation(&envChain_);
49 : }
50 :
51 : inline GlobalObject&
52 691 : InterpreterFrame::global() const
53 : {
54 691 : return environmentChain()->global();
55 : }
56 :
57 : inline JSObject&
58 1141 : InterpreterFrame::varObj() const
59 : {
60 1141 : JSObject* obj = environmentChain();
61 3423 : while (!obj->isQualifiedVarObj())
62 1141 : obj = obj->enclosingEnvironment();
63 1141 : return *obj;
64 : }
65 :
66 : inline LexicalEnvironmentObject&
67 677 : InterpreterFrame::extensibleLexicalEnvironment() const
68 : {
69 677 : return NearestEnclosingExtensibleLexicalEnvironment(environmentChain());
70 : }
71 :
72 : inline void
73 11801 : InterpreterFrame::initCallFrame(JSContext* cx, InterpreterFrame* prev, jsbytecode* prevpc,
74 : Value* prevsp, JSFunction& callee, JSScript* script, Value* argv,
75 : uint32_t nactual, MaybeConstruct constructing)
76 : {
77 11801 : MOZ_ASSERT(callee.nonLazyScript() == script);
78 :
79 : /* Initialize stack frame members. */
80 11801 : flags_ = 0;
81 11801 : if (constructing)
82 422 : flags_ |= CONSTRUCTING;
83 11801 : argv_ = argv;
84 11801 : script_ = script;
85 11801 : nactual_ = nactual;
86 11801 : envChain_ = callee.environment();
87 11801 : prev_ = prev;
88 11801 : prevpc_ = prevpc;
89 11801 : prevsp_ = prevsp;
90 :
91 11801 : if (script->isDebuggee())
92 0 : setIsDebuggee();
93 :
94 11801 : initLocals();
95 11801 : }
96 :
97 : inline void
98 12299 : InterpreterFrame::initLocals()
99 : {
100 12299 : SetValueRangeToUndefined(slots(), script()->nfixed());
101 12299 : }
102 :
103 : inline Value&
104 84367 : InterpreterFrame::unaliasedLocal(uint32_t i)
105 : {
106 84367 : MOZ_ASSERT(i < script()->nfixed());
107 84367 : return slots()[i];
108 : }
109 :
110 : inline Value&
111 23961 : InterpreterFrame::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing)
112 : {
113 23961 : MOZ_ASSERT(i < numFormalArgs());
114 23961 : MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
115 23961 : MOZ_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
116 23961 : return argv()[i];
117 : }
118 :
119 : inline Value&
120 135 : InterpreterFrame::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing)
121 : {
122 135 : MOZ_ASSERT(i < numActualArgs());
123 135 : MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
124 135 : MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
125 135 : return argv()[i];
126 : }
127 :
128 : template <class Op>
129 : inline void
130 0 : InterpreterFrame::unaliasedForEachActual(Op op)
131 : {
132 : // Don't assert !script()->funHasAnyAliasedFormal() since this function is
133 : // called from ArgumentsObject::createUnexpected() which can access aliased
134 : // slots.
135 :
136 0 : const Value* argsEnd = argv() + numActualArgs();
137 0 : for (const Value* p = argv(); p < argsEnd; ++p)
138 0 : op(*p);
139 0 : }
140 :
141 : struct CopyTo
142 : {
143 : Value* dst;
144 0 : explicit CopyTo(Value* dst) : dst(dst) {}
145 0 : void operator()(const Value& src) { *dst++ = src; }
146 : };
147 :
148 : struct CopyToHeap
149 : {
150 : GCPtrValue* dst;
151 0 : explicit CopyToHeap(GCPtrValue* dst) : dst(dst) {}
152 0 : void operator()(const Value& src) { dst->init(src); ++dst; }
153 : };
154 :
155 : inline ArgumentsObject&
156 9 : InterpreterFrame::argsObj() const
157 : {
158 9 : MOZ_ASSERT(script()->needsArgsObj());
159 9 : MOZ_ASSERT(flags_ & HAS_ARGS_OBJ);
160 9 : return *argsObj_;
161 : }
162 :
163 : inline void
164 77 : InterpreterFrame::initArgsObj(ArgumentsObject& argsobj)
165 : {
166 77 : MOZ_ASSERT(script()->needsArgsObj());
167 77 : flags_ |= HAS_ARGS_OBJ;
168 77 : argsObj_ = &argsobj;
169 77 : }
170 :
171 : inline EnvironmentObject&
172 8186 : InterpreterFrame::aliasedEnvironment(EnvironmentCoordinate ec) const
173 : {
174 8186 : JSObject* env = &environmentChain()->as<EnvironmentObject>();
175 10853 : for (unsigned i = ec.hops(); i; i--)
176 2667 : env = &env->as<EnvironmentObject>().enclosingEnvironment();
177 8186 : return env->as<EnvironmentObject>();
178 : }
179 :
180 : template <typename SpecificEnvironment>
181 : inline void
182 1638 : InterpreterFrame::pushOnEnvironmentChain(SpecificEnvironment& env)
183 : {
184 1638 : MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment());
185 1638 : envChain_ = &env;
186 1638 : if (IsFrameInitialEnvironment(this, env))
187 1131 : flags_ |= HAS_INITIAL_ENV;
188 1638 : }
189 :
190 : template <typename SpecificEnvironment>
191 : inline void
192 1881 : InterpreterFrame::popOffEnvironmentChain()
193 : {
194 1881 : MOZ_ASSERT(envChain_->is<SpecificEnvironment>());
195 1881 : envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment();
196 1881 : }
197 :
198 : inline void
199 73 : InterpreterFrame::replaceInnermostEnvironment(EnvironmentObject& env)
200 : {
201 73 : MOZ_ASSERT(env.enclosingEnvironment() ==
202 : envChain_->as<EnvironmentObject>().enclosingEnvironment());
203 73 : envChain_ = &env;
204 73 : }
205 :
206 : bool
207 4304 : InterpreterFrame::hasInitialEnvironment() const
208 : {
209 4304 : MOZ_ASSERT(script()->initialEnvironmentShape());
210 4304 : return flags_ & HAS_INITIAL_ENV;
211 : }
212 :
213 : inline CallObject&
214 6 : InterpreterFrame::callObj() const
215 : {
216 6 : MOZ_ASSERT(callee().needsCallObject());
217 :
218 6 : JSObject* pobj = environmentChain();
219 6 : while (MOZ_UNLIKELY(!pobj->is<CallObject>()))
220 0 : pobj = pobj->enclosingEnvironment();
221 6 : return pobj->as<CallObject>();
222 : }
223 :
224 : inline void
225 0 : InterpreterFrame::unsetIsDebuggee()
226 : {
227 0 : MOZ_ASSERT(!script()->isDebuggee());
228 0 : flags_ &= ~DEBUGGEE;
229 0 : }
230 :
231 : /*****************************************************************************/
232 :
233 : inline void
234 1 : InterpreterStack::purge(JSRuntime* rt)
235 : {
236 1 : rt->gc.freeUnusedLifoBlocksAfterSweeping(&allocator_);
237 1 : }
238 :
239 : uint8_t*
240 12299 : InterpreterStack::allocateFrame(JSContext* cx, size_t size)
241 : {
242 : size_t maxFrames;
243 12299 : if (cx->compartment()->principals() == cx->runtime()->trustedPrincipals())
244 12154 : maxFrames = MAX_FRAMES_TRUSTED;
245 : else
246 145 : maxFrames = MAX_FRAMES;
247 :
248 12299 : if (MOZ_UNLIKELY(frameCount_ >= maxFrames)) {
249 0 : ReportOverRecursed(cx);
250 0 : return nullptr;
251 : }
252 :
253 12299 : uint8_t* buffer = reinterpret_cast<uint8_t*>(allocator_.alloc(size));
254 12299 : if (!buffer) {
255 0 : ReportOutOfMemory(cx);
256 0 : return nullptr;
257 : }
258 :
259 12299 : frameCount_++;
260 12299 : return buffer;
261 : }
262 :
263 : MOZ_ALWAYS_INLINE InterpreterFrame*
264 11603 : InterpreterStack::getCallFrame(JSContext* cx, const CallArgs& args, HandleScript script,
265 : MaybeConstruct constructing, Value** pargv)
266 : {
267 11603 : JSFunction* fun = &args.callee().as<JSFunction>();
268 :
269 11603 : MOZ_ASSERT(fun->nonLazyScript() == script);
270 11603 : unsigned nformal = fun->nargs();
271 11603 : unsigned nvals = script->nslots();
272 :
273 11603 : if (args.length() >= nformal) {
274 10943 : *pargv = args.array();
275 10943 : uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
276 10943 : return reinterpret_cast<InterpreterFrame*>(buffer);
277 : }
278 :
279 : // Pad any missing arguments with |undefined|.
280 660 : MOZ_ASSERT(args.length() < nformal);
281 :
282 660 : unsigned nfunctionState = 2 + constructing; // callee, |this|, |new.target|
283 :
284 660 : nvals += nformal + nfunctionState;
285 660 : uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
286 660 : if (!buffer)
287 0 : return nullptr;
288 :
289 660 : Value* argv = reinterpret_cast<Value*>(buffer);
290 660 : unsigned nmissing = nformal - args.length();
291 :
292 660 : mozilla::PodCopy(argv, args.base(), 2 + args.length());
293 660 : SetValueRangeToUndefined(argv + 2 + args.length(), nmissing);
294 :
295 660 : if (constructing)
296 37 : argv[2 + nformal] = args.newTarget();
297 :
298 660 : *pargv = argv + 2;
299 660 : return reinterpret_cast<InterpreterFrame*>(argv + nfunctionState + nformal);
300 : }
301 :
302 : MOZ_ALWAYS_INLINE bool
303 1674 : InterpreterStack::pushInlineFrame(JSContext* cx, InterpreterRegs& regs, const CallArgs& args,
304 : HandleScript script, MaybeConstruct constructing)
305 : {
306 3348 : RootedFunction callee(cx, &args.callee().as<JSFunction>());
307 1674 : MOZ_ASSERT(regs.sp == args.end());
308 1674 : MOZ_ASSERT(callee->nonLazyScript() == script);
309 :
310 1674 : script->ensureNonLazyCanonicalFunction();
311 :
312 1674 : InterpreterFrame* prev = regs.fp();
313 1674 : jsbytecode* prevpc = regs.pc;
314 1674 : Value* prevsp = regs.sp;
315 1674 : MOZ_ASSERT(prev);
316 :
317 1674 : LifoAlloc::Mark mark = allocator_.mark();
318 :
319 : Value* argv;
320 1674 : InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv);
321 1674 : if (!fp)
322 0 : return false;
323 :
324 1674 : fp->mark_ = mark;
325 :
326 : /* Initialize frame, locals, regs. */
327 3348 : fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, args.length(),
328 3348 : constructing);
329 :
330 1674 : regs.prepareToRun(*fp, script);
331 1674 : return true;
332 : }
333 :
334 : MOZ_ALWAYS_INLINE bool
335 198 : InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
336 : HandleFunction callee, HandleValue newTarget,
337 : HandleObject envChain)
338 : {
339 198 : MOZ_ASSERT(callee->isStarGenerator() || callee->isLegacyGenerator() || callee->isAsync());
340 396 : RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee));
341 198 : InterpreterFrame* prev = regs.fp();
342 198 : jsbytecode* prevpc = regs.pc;
343 198 : Value* prevsp = regs.sp;
344 198 : MOZ_ASSERT(prev);
345 :
346 198 : script->ensureNonLazyCanonicalFunction();
347 :
348 198 : LifoAlloc::Mark mark = allocator_.mark();
349 :
350 198 : MaybeConstruct constructing = MaybeConstruct(newTarget.isObject());
351 :
352 : // Include callee, |this|, and maybe |new.target|
353 198 : unsigned nformal = callee->nargs();
354 198 : unsigned nvals = 2 + constructing + nformal + script->nslots();
355 :
356 198 : uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
357 198 : if (!buffer)
358 0 : return false;
359 :
360 198 : Value* argv = reinterpret_cast<Value*>(buffer) + 2;
361 198 : argv[-2] = ObjectValue(*callee);
362 198 : argv[-1] = UndefinedValue();
363 198 : SetValueRangeToUndefined(argv, nformal);
364 198 : if (constructing)
365 0 : argv[nformal] = newTarget;
366 :
367 198 : InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(argv + nformal + constructing);
368 198 : fp->mark_ = mark;
369 198 : fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, 0, constructing);
370 198 : fp->resumeGeneratorFrame(envChain);
371 :
372 198 : regs.prepareToRun(*fp, script);
373 198 : return true;
374 : }
375 :
376 : MOZ_ALWAYS_INLINE void
377 1869 : InterpreterStack::popInlineFrame(InterpreterRegs& regs)
378 : {
379 1869 : InterpreterFrame* fp = regs.fp();
380 1869 : regs.popInlineFrame();
381 1869 : regs.sp[-1] = fp->returnValue();
382 1869 : releaseFrame(fp);
383 1869 : MOZ_ASSERT(regs.fp());
384 1869 : }
385 :
386 : template <class Op>
387 : inline void
388 0 : FrameIter::unaliasedForEachActual(JSContext* cx, Op op)
389 : {
390 0 : switch (data_.state_) {
391 : case DONE:
392 : case WASM:
393 0 : break;
394 : case INTERP:
395 0 : interpFrame()->unaliasedForEachActual(op);
396 0 : return;
397 : case JIT:
398 0 : if (data_.jitFrames_.isIonJS()) {
399 0 : jit::MaybeReadFallback recover(cx, activation()->asJit(), &data_.jitFrames_);
400 0 : ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals, recover);
401 0 : } else if (data_.jitFrames_.isBailoutJS()) {
402 : // :TODO: (Bug 1070962) If we are introspecting the frame which is
403 : // being bailed, then we might be in the middle of recovering
404 : // instructions. Stacking computeInstructionResults implies that we
405 : // might be recovering result twice. In the mean time, to avoid
406 : // that, we just return Undefined values for instruction results
407 : // which are not yet recovered.
408 0 : jit::MaybeReadFallback fallback;
409 0 : ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals, fallback);
410 : } else {
411 0 : MOZ_ASSERT(data_.jitFrames_.isBaselineJS());
412 0 : data_.jitFrames_.unaliasedForEachActual(op, jit::ReadFrame_Actuals);
413 : }
414 0 : return;
415 : }
416 0 : MOZ_CRASH("Unexpected state");
417 : }
418 :
419 : inline HandleValue
420 0 : AbstractFramePtr::returnValue() const
421 : {
422 0 : if (isInterpreterFrame())
423 0 : return asInterpreterFrame()->returnValue();
424 0 : if (isWasmDebugFrame())
425 0 : return asWasmDebugFrame()->returnValue();
426 0 : return asBaselineFrame()->returnValue();
427 : }
428 :
429 : inline void
430 0 : AbstractFramePtr::setReturnValue(const Value& rval) const
431 : {
432 0 : if (isInterpreterFrame()) {
433 0 : asInterpreterFrame()->setReturnValue(rval);
434 0 : return;
435 : }
436 0 : if (isBaselineFrame()) {
437 0 : asBaselineFrame()->setReturnValue(rval);
438 0 : return;
439 : }
440 0 : if (isWasmDebugFrame()) {
441 : // TODO handle wasm function return value
442 : // The function is called from Debugger::slowPathOnLeaveFrame --
443 : // ignoring value for wasm.
444 0 : return;
445 : }
446 0 : asRematerializedFrame()->setReturnValue(rval);
447 : }
448 :
449 : inline JSObject*
450 39463 : AbstractFramePtr::environmentChain() const
451 : {
452 39463 : if (isInterpreterFrame())
453 27551 : return asInterpreterFrame()->environmentChain();
454 11912 : if (isBaselineFrame())
455 11912 : return asBaselineFrame()->environmentChain();
456 0 : if (isWasmDebugFrame())
457 0 : return &global()->lexicalEnvironment();
458 0 : return asRematerializedFrame()->environmentChain();
459 : }
460 :
461 : template <typename SpecificEnvironment>
462 : inline void
463 4296 : AbstractFramePtr::pushOnEnvironmentChain(SpecificEnvironment& env)
464 : {
465 4296 : if (isInterpreterFrame()) {
466 1163 : asInterpreterFrame()->pushOnEnvironmentChain(env);
467 1163 : return;
468 : }
469 3133 : if (isBaselineFrame()) {
470 3133 : asBaselineFrame()->pushOnEnvironmentChain(env);
471 3133 : return;
472 : }
473 0 : asRematerializedFrame()->pushOnEnvironmentChain(env);
474 : }
475 :
476 : template <typename SpecificEnvironment>
477 : inline void
478 1457 : AbstractFramePtr::popOffEnvironmentChain()
479 : {
480 1457 : if (isInterpreterFrame()) {
481 1457 : asInterpreterFrame()->popOffEnvironmentChain<SpecificEnvironment>();
482 1457 : return;
483 : }
484 0 : if (isBaselineFrame()) {
485 0 : asBaselineFrame()->popOffEnvironmentChain<SpecificEnvironment>();
486 0 : return;
487 : }
488 0 : asRematerializedFrame()->popOffEnvironmentChain<SpecificEnvironment>();
489 : }
490 :
491 : inline CallObject&
492 6 : AbstractFramePtr::callObj() const
493 : {
494 6 : if (isInterpreterFrame())
495 6 : return asInterpreterFrame()->callObj();
496 0 : if (isBaselineFrame())
497 0 : return asBaselineFrame()->callObj();
498 0 : return asRematerializedFrame()->callObj();
499 : }
500 :
501 : inline bool
502 0 : AbstractFramePtr::initFunctionEnvironmentObjects(JSContext* cx)
503 : {
504 0 : return js::InitFunctionEnvironmentObjects(cx, *this);
505 : }
506 :
507 : inline bool
508 : AbstractFramePtr::pushVarEnvironment(JSContext* cx, HandleScope scope)
509 : {
510 : return js::PushVarEnvironmentObject(cx, scope, *this);
511 : }
512 :
513 : inline JSCompartment*
514 2 : AbstractFramePtr::compartment() const
515 : {
516 2 : return environmentChain()->compartment();
517 : }
518 :
519 : inline unsigned
520 405 : AbstractFramePtr::numActualArgs() const
521 : {
522 405 : if (isInterpreterFrame())
523 289 : return asInterpreterFrame()->numActualArgs();
524 116 : if (isBaselineFrame())
525 116 : return asBaselineFrame()->numActualArgs();
526 0 : return asRematerializedFrame()->numActualArgs();
527 : }
528 :
529 : inline unsigned
530 127 : AbstractFramePtr::numFormalArgs() const
531 : {
532 127 : if (isInterpreterFrame())
533 77 : return asInterpreterFrame()->numFormalArgs();
534 50 : if (isBaselineFrame())
535 50 : return asBaselineFrame()->numFormalArgs();
536 0 : return asRematerializedFrame()->numFormalArgs();
537 : }
538 :
539 : inline Value&
540 0 : AbstractFramePtr::unaliasedLocal(uint32_t i)
541 : {
542 0 : if (isInterpreterFrame())
543 0 : return asInterpreterFrame()->unaliasedLocal(i);
544 0 : if (isBaselineFrame())
545 0 : return asBaselineFrame()->unaliasedLocal(i);
546 0 : return asRematerializedFrame()->unaliasedLocal(i);
547 : }
548 :
549 : inline Value&
550 9526 : AbstractFramePtr::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing)
551 : {
552 9526 : if (isInterpreterFrame())
553 1563 : return asInterpreterFrame()->unaliasedFormal(i, checkAliasing);
554 7963 : if (isBaselineFrame())
555 7963 : return asBaselineFrame()->unaliasedFormal(i, checkAliasing);
556 0 : return asRematerializedFrame()->unaliasedFormal(i, checkAliasing);
557 : }
558 :
559 : inline Value&
560 151 : AbstractFramePtr::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing)
561 : {
562 151 : if (isInterpreterFrame())
563 135 : return asInterpreterFrame()->unaliasedActual(i, checkAliasing);
564 16 : if (isBaselineFrame())
565 16 : return asBaselineFrame()->unaliasedActual(i, checkAliasing);
566 0 : return asRematerializedFrame()->unaliasedActual(i, checkAliasing);
567 : }
568 :
569 : inline bool
570 3011 : AbstractFramePtr::hasInitialEnvironment() const
571 : {
572 3011 : if (isInterpreterFrame())
573 3011 : return asInterpreterFrame()->hasInitialEnvironment();
574 0 : if (isBaselineFrame())
575 0 : return asBaselineFrame()->hasInitialEnvironment();
576 0 : return asRematerializedFrame()->hasInitialEnvironment();
577 : }
578 :
579 : inline bool
580 : AbstractFramePtr::createSingleton() const
581 : {
582 : if (isInterpreterFrame())
583 : return asInterpreterFrame()->createSingleton();
584 : return false;
585 : }
586 :
587 : inline bool
588 0 : AbstractFramePtr::isGlobalFrame() const
589 : {
590 0 : if (isInterpreterFrame())
591 0 : return asInterpreterFrame()->isGlobalFrame();
592 0 : if (isBaselineFrame())
593 0 : return asBaselineFrame()->isGlobalFrame();
594 0 : if (isWasmDebugFrame())
595 0 : return false;
596 0 : return asRematerializedFrame()->isGlobalFrame();
597 : }
598 :
599 : inline bool
600 0 : AbstractFramePtr::isModuleFrame() const
601 : {
602 0 : if (isInterpreterFrame())
603 0 : return asInterpreterFrame()->isModuleFrame();
604 0 : if (isBaselineFrame())
605 0 : return asBaselineFrame()->isModuleFrame();
606 0 : if (isWasmDebugFrame())
607 0 : return false;
608 0 : return asRematerializedFrame()->isModuleFrame();
609 : }
610 :
611 : inline bool
612 12397 : AbstractFramePtr::isEvalFrame() const
613 : {
614 12397 : if (isInterpreterFrame())
615 12223 : return asInterpreterFrame()->isEvalFrame();
616 174 : if (isBaselineFrame())
617 174 : return asBaselineFrame()->isEvalFrame();
618 0 : if (isWasmDebugFrame())
619 0 : return false;
620 0 : MOZ_ASSERT(isRematerializedFrame());
621 0 : return false;
622 : }
623 :
624 : inline bool
625 0 : AbstractFramePtr::isDebuggerEvalFrame() const
626 : {
627 0 : if (isInterpreterFrame())
628 0 : return asInterpreterFrame()->isDebuggerEvalFrame();
629 0 : if (isBaselineFrame())
630 0 : return asBaselineFrame()->isDebuggerEvalFrame();
631 0 : MOZ_ASSERT(isRematerializedFrame());
632 0 : return false;
633 : }
634 :
635 : inline bool
636 5675 : AbstractFramePtr::hasCachedSavedFrame() const
637 : {
638 5675 : if (isInterpreterFrame())
639 4900 : return asInterpreterFrame()->hasCachedSavedFrame();
640 775 : if (isBaselineFrame())
641 775 : return asBaselineFrame()->hasCachedSavedFrame();
642 0 : if (isWasmDebugFrame())
643 0 : return asWasmDebugFrame()->hasCachedSavedFrame();
644 0 : return asRematerializedFrame()->hasCachedSavedFrame();
645 : }
646 :
647 : inline void
648 2641 : AbstractFramePtr::setHasCachedSavedFrame()
649 : {
650 2641 : if (isInterpreterFrame())
651 2170 : asInterpreterFrame()->setHasCachedSavedFrame();
652 471 : else if (isBaselineFrame())
653 471 : asBaselineFrame()->setHasCachedSavedFrame();
654 0 : else if (isWasmDebugFrame())
655 0 : asWasmDebugFrame()->setHasCachedSavedFrame();
656 : else
657 0 : asRematerializedFrame()->setHasCachedSavedFrame();
658 2641 : }
659 :
660 : inline bool
661 24416 : AbstractFramePtr::isDebuggee() const
662 : {
663 24416 : if (isInterpreterFrame())
664 24260 : return asInterpreterFrame()->isDebuggee();
665 156 : if (isBaselineFrame())
666 156 : return asBaselineFrame()->isDebuggee();
667 0 : if (isWasmDebugFrame())
668 0 : return asWasmDebugFrame()->isDebuggee();
669 0 : return asRematerializedFrame()->isDebuggee();
670 : }
671 :
672 : inline void
673 0 : AbstractFramePtr::setIsDebuggee()
674 : {
675 0 : if (isInterpreterFrame())
676 0 : asInterpreterFrame()->setIsDebuggee();
677 0 : else if (isBaselineFrame())
678 0 : asBaselineFrame()->setIsDebuggee();
679 0 : else if (isWasmDebugFrame())
680 0 : asWasmDebugFrame()->setIsDebuggee();
681 : else
682 0 : asRematerializedFrame()->setIsDebuggee();
683 0 : }
684 :
685 : inline void
686 0 : AbstractFramePtr::unsetIsDebuggee()
687 : {
688 0 : if (isInterpreterFrame())
689 0 : asInterpreterFrame()->unsetIsDebuggee();
690 0 : else if (isBaselineFrame())
691 0 : asBaselineFrame()->unsetIsDebuggee();
692 0 : else if (isWasmDebugFrame())
693 0 : asWasmDebugFrame()->unsetIsDebuggee();
694 : else
695 0 : asRematerializedFrame()->unsetIsDebuggee();
696 0 : }
697 :
698 : inline bool
699 0 : AbstractFramePtr::hasArgs() const
700 : {
701 0 : return isFunctionFrame();
702 : }
703 :
704 : inline bool
705 82307 : AbstractFramePtr::hasScript() const
706 : {
707 82307 : return !isWasmDebugFrame();
708 : }
709 :
710 : inline JSScript*
711 122734 : AbstractFramePtr::script() const
712 : {
713 122734 : if (isInterpreterFrame())
714 105510 : return asInterpreterFrame()->script();
715 17224 : if (isBaselineFrame())
716 17224 : return asBaselineFrame()->script();
717 0 : return asRematerializedFrame()->script();
718 : }
719 :
720 : inline wasm::Instance*
721 0 : AbstractFramePtr::wasmInstance() const
722 : {
723 0 : return asWasmDebugFrame()->instance();
724 : }
725 :
726 : inline GlobalObject*
727 12315 : AbstractFramePtr::global() const
728 : {
729 12315 : if (isWasmDebugFrame())
730 0 : return &wasmInstance()->object()->global();
731 12315 : return &script()->global();
732 : }
733 :
734 : inline JSFunction*
735 19200 : AbstractFramePtr::callee() const
736 : {
737 19200 : if (isInterpreterFrame())
738 9582 : return &asInterpreterFrame()->callee();
739 9618 : if (isBaselineFrame())
740 9618 : return asBaselineFrame()->callee();
741 0 : return asRematerializedFrame()->callee();
742 : }
743 :
744 : inline Value
745 : AbstractFramePtr::calleev() const
746 : {
747 : if (isInterpreterFrame())
748 : return asInterpreterFrame()->calleev();
749 : if (isBaselineFrame())
750 : return asBaselineFrame()->calleev();
751 : return asRematerializedFrame()->calleev();
752 : }
753 :
754 : inline bool
755 14141 : AbstractFramePtr::isFunctionFrame() const
756 : {
757 14141 : if (isInterpreterFrame())
758 7893 : return asInterpreterFrame()->isFunctionFrame();
759 6248 : if (isBaselineFrame())
760 6248 : return asBaselineFrame()->isFunctionFrame();
761 0 : if (isWasmDebugFrame())
762 0 : return false;
763 0 : return asRematerializedFrame()->isFunctionFrame();
764 : }
765 :
766 : inline bool
767 : AbstractFramePtr::isNonStrictDirectEvalFrame() const
768 : {
769 : if (isInterpreterFrame())
770 : return asInterpreterFrame()->isNonStrictDirectEvalFrame();
771 : if (isBaselineFrame())
772 : return asBaselineFrame()->isNonStrictDirectEvalFrame();
773 : MOZ_ASSERT(isRematerializedFrame());
774 : return false;
775 : }
776 :
777 : inline bool
778 : AbstractFramePtr::isStrictEvalFrame() const
779 : {
780 : if (isInterpreterFrame())
781 : return asInterpreterFrame()->isStrictEvalFrame();
782 : if (isBaselineFrame())
783 : return asBaselineFrame()->isStrictEvalFrame();
784 : MOZ_ASSERT(isRematerializedFrame());
785 : return false;
786 : }
787 :
788 : inline Value*
789 127 : AbstractFramePtr::argv() const
790 : {
791 127 : if (isInterpreterFrame())
792 77 : return asInterpreterFrame()->argv();
793 50 : if (isBaselineFrame())
794 50 : return asBaselineFrame()->argv();
795 0 : return asRematerializedFrame()->argv();
796 : }
797 :
798 : inline bool
799 0 : AbstractFramePtr::hasArgsObj() const
800 : {
801 0 : if (isInterpreterFrame())
802 0 : return asInterpreterFrame()->hasArgsObj();
803 0 : if (isBaselineFrame())
804 0 : return asBaselineFrame()->hasArgsObj();
805 0 : return asRematerializedFrame()->hasArgsObj();
806 : }
807 :
808 : inline ArgumentsObject&
809 0 : AbstractFramePtr::argsObj() const
810 : {
811 0 : if (isInterpreterFrame())
812 0 : return asInterpreterFrame()->argsObj();
813 0 : if (isBaselineFrame())
814 0 : return asBaselineFrame()->argsObj();
815 0 : return asRematerializedFrame()->argsObj();
816 : }
817 :
818 : inline void
819 127 : AbstractFramePtr::initArgsObj(ArgumentsObject& argsobj) const
820 : {
821 127 : if (isInterpreterFrame()) {
822 77 : asInterpreterFrame()->initArgsObj(argsobj);
823 77 : return;
824 : }
825 50 : asBaselineFrame()->initArgsObj(argsobj);
826 : }
827 :
828 : inline bool
829 0 : AbstractFramePtr::prevUpToDate() const
830 : {
831 0 : if (isInterpreterFrame())
832 0 : return asInterpreterFrame()->prevUpToDate();
833 0 : if (isBaselineFrame())
834 0 : return asBaselineFrame()->prevUpToDate();
835 0 : if (isWasmDebugFrame())
836 0 : return asWasmDebugFrame()->prevUpToDate();
837 0 : return asRematerializedFrame()->prevUpToDate();
838 : }
839 :
840 : inline void
841 0 : AbstractFramePtr::setPrevUpToDate() const
842 : {
843 0 : if (isInterpreterFrame()) {
844 0 : asInterpreterFrame()->setPrevUpToDate();
845 0 : return;
846 : }
847 0 : if (isBaselineFrame()) {
848 0 : asBaselineFrame()->setPrevUpToDate();
849 0 : return;
850 : }
851 0 : if (isWasmDebugFrame()) {
852 0 : asWasmDebugFrame()->setPrevUpToDate();
853 0 : return;
854 : }
855 0 : asRematerializedFrame()->setPrevUpToDate();
856 : }
857 :
858 : inline void
859 0 : AbstractFramePtr::unsetPrevUpToDate() const
860 : {
861 0 : if (isInterpreterFrame()) {
862 0 : asInterpreterFrame()->unsetPrevUpToDate();
863 0 : return;
864 : }
865 0 : if (isBaselineFrame()) {
866 0 : asBaselineFrame()->unsetPrevUpToDate();
867 0 : return;
868 : }
869 0 : if (isWasmDebugFrame()) {
870 0 : asWasmDebugFrame()->unsetPrevUpToDate();
871 0 : return;
872 : }
873 0 : asRematerializedFrame()->unsetPrevUpToDate();
874 : }
875 :
876 : inline Value&
877 11262 : AbstractFramePtr::thisArgument() const
878 : {
879 11262 : if (isInterpreterFrame())
880 11262 : return asInterpreterFrame()->thisArgument();
881 0 : if (isBaselineFrame())
882 0 : return asBaselineFrame()->thisArgument();
883 0 : return asRematerializedFrame()->thisArgument();
884 : }
885 :
886 : inline Value
887 136 : AbstractFramePtr::newTarget() const
888 : {
889 136 : if (isInterpreterFrame())
890 72 : return asInterpreterFrame()->newTarget();
891 64 : if (isBaselineFrame())
892 64 : return asBaselineFrame()->newTarget();
893 0 : return asRematerializedFrame()->newTarget();
894 : }
895 :
896 : inline bool
897 0 : AbstractFramePtr::debuggerNeedsCheckPrimitiveReturn() const
898 : {
899 0 : if (isWasmDebugFrame())
900 0 : return false;
901 0 : return script()->isDerivedClassConstructor();
902 : }
903 :
904 36184 : ActivationEntryMonitor::~ActivationEntryMonitor()
905 : {
906 18092 : if (entryMonitor_)
907 0 : entryMonitor_->Exit(cx_);
908 :
909 18092 : cx_->entryMonitor = entryMonitor_;
910 18092 : }
911 :
912 18100 : Activation::Activation(JSContext* cx, Kind kind)
913 : : cx_(cx),
914 18100 : compartment_(cx->compartment()),
915 : prev_(cx->activation_),
916 18100 : prevProfiling_(prev_ ? prev_->mostRecentProfiling() : nullptr),
917 : hideScriptedCallerCount_(0),
918 : frameCache_(cx),
919 : asyncStack_(cx, cx->asyncStackForNewActivations()),
920 : asyncCause_(cx->asyncCauseForNewActivations),
921 : asyncCallIsExplicit_(cx->asyncCallIsExplicit),
922 54300 : kind_(kind)
923 : {
924 18100 : cx->asyncStackForNewActivations() = nullptr;
925 18100 : cx->asyncCauseForNewActivations = nullptr;
926 18100 : cx->asyncCallIsExplicit = false;
927 18100 : cx->activation_ = this;
928 18100 : }
929 :
930 36184 : Activation::~Activation()
931 : {
932 18092 : MOZ_ASSERT_IF(isProfiling(), this != cx_->profilingActivation_);
933 18092 : MOZ_ASSERT(cx_->activation_ == this);
934 18092 : MOZ_ASSERT(hideScriptedCallerCount_ == 0);
935 18092 : cx_->activation_ = prev_;
936 18092 : cx_->asyncCauseForNewActivations = asyncCause_;
937 18092 : cx_->asyncStackForNewActivations() = asyncStack_;
938 18092 : cx_->asyncCallIsExplicit = asyncCallIsExplicit_;
939 18092 : }
940 :
941 : bool
942 50617 : Activation::isProfiling() const
943 : {
944 50617 : if (isInterpreter())
945 24141 : return asInterpreter()->isProfiling();
946 :
947 26476 : if (isJit())
948 26476 : return asJit()->isProfiling();
949 :
950 0 : MOZ_ASSERT(isWasm());
951 0 : return asWasm()->isProfiling();
952 : }
953 :
954 : Activation*
955 17179 : Activation::mostRecentProfiling()
956 : {
957 17179 : if (isProfiling())
958 3457 : return this;
959 13722 : return prevProfiling_;
960 : }
961 :
962 : inline LiveSavedFrameCache*
963 4158 : Activation::getLiveSavedFrameCache(JSContext* cx) {
964 4158 : if (!frameCache_.get().initialized() && !frameCache_.get().init(cx))
965 0 : return nullptr;
966 4158 : return frameCache_.address();
967 : }
968 :
969 10427 : InterpreterActivation::InterpreterActivation(RunState& state, JSContext* cx,
970 10427 : InterpreterFrame* entryFrame)
971 : : Activation(cx, Interpreter),
972 : entryFrame_(entryFrame),
973 : opMask_(0)
974 : #ifdef DEBUG
975 10427 : , oldFrameCount_(cx->interpreterStack().frameCount_)
976 : #endif
977 : {
978 10427 : regs_.prepareToRun(*entryFrame, state.script());
979 10427 : MOZ_ASSERT(regs_.pc == state.script()->code());
980 10427 : MOZ_ASSERT_IF(entryFrame_->isEvalFrame(), state.script()->isActiveEval());
981 10427 : }
982 :
983 20838 : InterpreterActivation::~InterpreterActivation()
984 : {
985 : // Pop all inline frames.
986 10419 : while (regs_.fp() != entryFrame_)
987 0 : popInlineFrame(regs_.fp());
988 :
989 10419 : MOZ_ASSERT(oldFrameCount_ == cx_->interpreterStack().frameCount_);
990 10419 : MOZ_ASSERT_IF(oldFrameCount_ == 0, cx_->interpreterStack().allocator_.used() == 0);
991 :
992 10419 : if (entryFrame_)
993 10419 : cx_->interpreterStack().releaseFrame(entryFrame_);
994 10419 : }
995 :
996 : inline bool
997 1674 : InterpreterActivation::pushInlineFrame(const CallArgs& args, HandleScript script,
998 : MaybeConstruct constructing)
999 : {
1000 1674 : if (!cx_->interpreterStack().pushInlineFrame(cx_, regs_, args, script, constructing))
1001 0 : return false;
1002 1674 : MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment());
1003 1674 : return true;
1004 : }
1005 :
1006 : inline void
1007 1869 : InterpreterActivation::popInlineFrame(InterpreterFrame* frame)
1008 : {
1009 : (void)frame; // Quell compiler warning.
1010 1869 : MOZ_ASSERT(regs_.fp() == frame);
1011 1869 : MOZ_ASSERT(regs_.fp() != entryFrame_);
1012 :
1013 1869 : cx_->interpreterStack().popInlineFrame(regs_);
1014 1869 : }
1015 :
1016 : inline bool
1017 198 : InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget,
1018 : HandleObject envChain)
1019 : {
1020 198 : InterpreterStack& stack = cx_->interpreterStack();
1021 198 : if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, newTarget, envChain))
1022 0 : return false;
1023 :
1024 198 : MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_);
1025 198 : return true;
1026 : }
1027 :
1028 : inline bool
1029 5675 : FrameIter::hasCachedSavedFrame() const
1030 : {
1031 5675 : if (isWasm())
1032 0 : return false;
1033 :
1034 5675 : if (hasUsableAbstractFramePtr())
1035 5675 : return abstractFramePtr().hasCachedSavedFrame();
1036 :
1037 0 : MOZ_ASSERT(data_.jitFrames_.isIonScripted());
1038 : // SavedFrame caching is done at the physical frame granularity (rather than
1039 : // for each inlined frame) for ion. Therefore, it is impossible to have a
1040 : // cached SavedFrame if this frame is not a physical frame.
1041 0 : return isPhysicalIonFrame() && data_.jitFrames_.current()->hasCachedSavedFrame();
1042 : }
1043 :
1044 : inline void
1045 : FrameIter::setHasCachedSavedFrame()
1046 : {
1047 : MOZ_ASSERT(!isWasm());
1048 :
1049 : if (hasUsableAbstractFramePtr()) {
1050 : abstractFramePtr().setHasCachedSavedFrame();
1051 : return;
1052 : }
1053 :
1054 : MOZ_ASSERT(isPhysicalIonFrame());
1055 : data_.jitFrames_.current()->setHasCachedSavedFrame();
1056 : }
1057 :
1058 : } /* namespace js */
1059 :
1060 : #endif /* vm_Stack_inl_h */
|