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_JSJitFrameIter_h
8 #define jit_JSJitFrameIter_h
10 #include "mozilla/Maybe.h"
14 #include "jit/JitCode.h"
15 #include "jit/MachineState.h"
16 #include "jit/Snapshots.h"
17 #include "js/ProfilingFrameIterator.h"
18 #include "vm/JSFunction.h"
19 #include "vm/JSScript.h"
23 class ArgumentsObject
;
27 enum class FrameType
{
28 // A JS frame is analogous to a js::InterpreterFrame, representing one
29 // scripted function activation. IonJS frames are used by the optimizing
33 // JS frame used by the Baseline Interpreter and Baseline JIT.
36 // Frame pushed by Baseline stubs that make non-tail calls, so that the
37 // return address -> ICEntry mapping works.
40 // The entry frame is the initial prologue block transitioning from the VM
41 // into the Ion world.
44 // This entry frame sits right before the baseline interpreter
45 // so that external profilers can identify which function is being
46 // interpreted. Only used under the --emit-interpreter-entry option.
47 BaselineInterpreterEntry
,
49 // A rectifier frame sits in between two JS frames, adapting argc != nargs
50 // mismatches in calls.
53 // Ion IC calling a scripted getter/setter or a VMFunction.
56 // An exit frame is necessary for transitioning from a JS frame into C++.
57 // From within C++, an exit frame is always the last frame in any
61 // A bailout frame is a special IonJS jit frame after a bailout, and before
62 // the reconstruction of the BaselineJS frame. From within C++, a bailout
63 // frame is always the last frame in a JitActivation iff the bailout frame
64 // information is recorded on the JitActivation.
67 // A wasm to JS frame is constructed during fast calls from wasm to the JS
68 // jits, used as a marker to interleave JS jit and wasm frames. From the
69 // point of view of JS JITs, this is just another kind of entry frame.
72 // A JS to wasm frame is constructed during fast calls from any JS jits to
73 // wasm, and is a special kind of exit frame that doesn't have the exit
74 // footer. From the point of view of the jit, it can be skipped as an exit.
77 // Frame for a TrampolineNative, a JS builtin implemented with a JIT
78 // trampoline. See jit/TrampolineNatives.h.
82 enum class ReadFrameArgsBehavior
{
83 // Read all actual arguments. Will invoke the callback numActualArgs times.
86 // Read all argument values in the stack frame. Will invoke the callback
87 // max(numFormalArgs, numActualArgs) times.
91 class CommonFrameLayout
;
93 class ExitFrameLayout
;
100 // Iterate over the JIT stack to assert that all invariants are respected.
101 // - Check that all entry frames are aligned on JitStackAlignment.
102 // - Check that all rectifier frames keep the JitStackAlignment.
104 void AssertJitStackInvariants(JSContext
* cx
);
106 // A JSJitFrameIter can iterate over a linear frame group of JS jit frames
107 // only. It will stop at the first frame that is not of the same kind, or at
108 // the end of an activation.
110 // If you want to handle every kind of frames (including wasm frames), use
111 // JitFrameIter. If you want to skip interleaved frames of other kinds, use
112 // OnlyJSJitFrameIter.
114 class JSJitFrameIter
{
118 uint8_t* resumePCinCurrentFrame_
;
120 // Size of the current Baseline frame. Equivalent to
121 // BaselineFrame::debugFrameSize_ in debug builds.
122 mozilla::Maybe
<uint32_t> baselineFrameSize_
;
125 mutable const SafepointIndex
* cachedSafepointIndex_
;
126 const JitActivation
* activation_
;
128 void dumpBaseline() const;
131 // See comment above the class.
132 explicit JSJitFrameIter(const JitActivation
* activation
);
134 // A constructor specialized for jit->wasm frames, which starts at a
136 JSJitFrameIter(const JitActivation
* activation
, FrameType frameType
,
139 void setResumePCInCurrentFrame(uint8_t* newAddr
) {
140 resumePCinCurrentFrame_
= newAddr
;
143 // Current frame information.
144 FrameType
type() const { return type_
; }
145 uint8_t* fp() const { return current_
; }
146 const JitActivation
* activation() const { return activation_
; }
148 CommonFrameLayout
* current() const { return (CommonFrameLayout
*)current_
; }
150 inline uint8_t* returnAddress() const;
152 // Return the pointer of the JitFrame, the iterator is assumed to be settled
153 // on a scripted frame.
154 JitFrameLayout
* jsFrame() const;
156 inline ExitFrameLayout
* exitFrame() const;
158 // Returns whether the JS frame has been invalidated and, if so,
159 // places the invalidated Ion script in |ionScript|.
160 bool checkInvalidation(IonScript
** ionScript
) const;
161 bool checkInvalidation() const;
163 bool isExitFrame() const { return type_
== FrameType::Exit
; }
164 bool isScripted() const {
165 return type_
== FrameType::BaselineJS
|| type_
== FrameType::IonJS
||
166 type_
== FrameType::Bailout
;
168 bool isBaselineJS() const { return type_
== FrameType::BaselineJS
; }
169 bool isIonScripted() const {
170 return type_
== FrameType::IonJS
|| type_
== FrameType::Bailout
;
172 bool isIonJS() const { return type_
== FrameType::IonJS
; }
173 bool isIonICCall() const { return type_
== FrameType::IonICCall
; }
174 bool isBailoutJS() const { return type_
== FrameType::Bailout
; }
175 bool isBaselineStub() const { return type_
== FrameType::BaselineStub
; }
176 bool isBaselineInterpreterEntry() const {
177 return type_
== FrameType::BaselineInterpreterEntry
;
179 bool isRectifier() const { return type_
== FrameType::Rectifier
; }
180 bool isBareExit() const;
181 bool isUnwoundJitExit() const;
182 template <typename T
>
183 bool isExitFrameLayout() const;
185 static bool isEntry(FrameType type
) {
186 return type
== FrameType::CppToJSJit
|| type
== FrameType::WasmToJSJit
;
188 bool isEntry() const { return isEntry(type_
); }
190 bool isFunctionFrame() const;
192 bool isConstructing() const;
194 void* calleeToken() const;
195 JSFunction
* callee() const;
196 JSFunction
* maybeCallee() const;
197 unsigned numActualArgs() const;
198 JSScript
* script() const;
199 JSScript
* maybeForwardedScript() const;
200 void baselineScriptAndPc(JSScript
** scriptRes
, jsbytecode
** pcRes
) const;
201 Value
* actualArgs() const;
203 // Returns the address of the next instruction that will execute in this
204 // frame, once control returns to this frame.
205 uint8_t* resumePCinCurrentFrame() const { return resumePCinCurrentFrame_
; }
207 // Previous frame information extracted from the current frame.
208 inline FrameType
prevType() const;
209 uint8_t* prevFp() const;
211 // Functions used to iterate on frames. When prevType is an entry,
212 // the current frame is the last JS Jit frame.
213 bool done() const { return isEntry(); }
216 // Returns the IonScript associated with this JS frame.
217 IonScript
* ionScript() const;
219 // Returns the IonScript associated with this JS frame; the frame must
220 // not be invalidated.
221 IonScript
* ionScriptFromCalleeToken() const;
223 // Returns the Safepoint associated with this JS frame. Incurs a lookup
225 const SafepointIndex
* safepoint() const;
227 // Returns the OSI index associated with this JS frame. Incurs a lookup
229 const OsiIndex
* osiIndex() const;
231 // Returns the Snapshot offset associated with this JS frame. Incurs a
233 SnapshotOffset
snapshotOffset() const;
235 uintptr_t* spillBase() const;
236 MachineState
machineState() const;
239 void unaliasedForEachActual(Op op
) const {
240 MOZ_ASSERT(isBaselineJS());
242 unsigned nactual
= numActualArgs();
243 Value
* argv
= actualArgs();
244 for (unsigned i
= 0; i
< nactual
; i
++) {
251 inline BaselineFrame
* baselineFrame() const;
253 // Returns the number of local and expression stack Values for the current
255 inline uint32_t baselineFrameNumValueSlots() const;
257 // This function isn't used, but we keep it here (debug-only) because it is
258 // helpful when chasing issues with the jitcode map.
260 bool verifyReturnAddressUsingNativeToBytecodeMap();
262 bool verifyReturnAddressUsingNativeToBytecodeMap() { return true; }
266 class JitcodeGlobalTable
;
268 class JSJitProfilingFrameIterator
{
270 // See JS::ProfilingFrameIterator::endStackAddress_ comment.
271 void* endStackAddress_
= nullptr;
273 void* resumePCinCurrentFrame_
;
275 inline JSScript
* frameScript() const;
276 [[nodiscard
]] bool tryInitWithPC(void* pc
);
277 [[nodiscard
]] bool tryInitWithTable(JitcodeGlobalTable
* table
, void* pc
,
278 bool forLastCallSite
);
280 void moveToNextFrame(CommonFrameLayout
* frame
);
283 JSJitProfilingFrameIterator(JSContext
* cx
, void* pc
, void* sp
);
284 explicit JSJitProfilingFrameIterator(CommonFrameLayout
* exitFP
);
287 bool done() const { return fp_
== nullptr; }
289 const char* baselineInterpreterLabel() const;
290 void baselineInterpreterScriptPC(JSScript
** script
, jsbytecode
** pc
,
291 uint64_t* realmID
) const;
297 inline JitFrameLayout
* framePtr() const;
298 void* stackAddress() const { return fp(); }
299 FrameType
frameType() const {
303 void* resumePCinCurrentFrame() const {
305 return resumePCinCurrentFrame_
;
308 void* endStackAddress() const { return endStackAddress_
; }
311 class RInstructionResults
{
312 // Vector of results of recover instructions.
313 typedef mozilla::Vector
<HeapPtr
<Value
>, 1, SystemAllocPolicy
> Values
;
314 UniquePtr
<Values
> results_
;
316 // The frame pointer is used as a key to check if the current frame already
320 // Record if we tried and succeed at allocating and filling the vector of
321 // recover instruction results, if needed. This flag is needed in order to
322 // avoid evaluating the recover instruction twice.
326 explicit RInstructionResults(JitFrameLayout
* fp
);
327 RInstructionResults(RInstructionResults
&& src
);
329 RInstructionResults
& operator=(RInstructionResults
&& rhs
);
331 ~RInstructionResults();
333 [[nodiscard
]] bool init(JSContext
* cx
, uint32_t numResults
);
334 bool isInitialized() const;
335 size_t length() const;
337 JitFrameLayout
* frame() const;
339 HeapPtr
<Value
>& operator[](size_t index
);
341 void trace(JSTracer
* trc
);
344 struct MaybeReadFallback
{
345 enum FallbackConsequence
{ Fallback_Invalidate
, Fallback_DoNothing
};
347 JSContext
* maybeCx
= nullptr;
348 JitActivation
* activation
= nullptr;
349 const JSJitFrameIter
* frame
= nullptr;
350 const FallbackConsequence consequence
= Fallback_Invalidate
;
352 MaybeReadFallback() = default;
354 MaybeReadFallback(JSContext
* cx
, JitActivation
* activation
,
355 const JSJitFrameIter
* frame
,
356 FallbackConsequence consequence
= Fallback_Invalidate
)
358 activation(activation
),
360 consequence(consequence
) {}
362 bool canRecoverResults() { return maybeCx
; }
367 // Reads frame information in snapshot-encoding order (that is, outermost frame
368 // to innermost frame).
369 class SnapshotIterator
{
371 SnapshotReader snapshot_
;
372 RecoverReader recover_
;
374 const MachineState
* machine_
;
375 IonScript
* ionScript_
;
376 RInstructionResults
* instructionResults_
;
378 enum class ReadMethod
: bool {
379 // Read the normal value.
382 // Read the default value, or the normal value if there is no default.
387 // Read a spilled register from the machine state.
388 bool hasRegister(Register reg
) const { return machine_
->has(reg
); }
389 uintptr_t fromRegister(Register reg
) const { return machine_
->read(reg
); }
391 bool hasRegister(FloatRegister reg
) const { return machine_
->has(reg
); }
392 template <typename T
>
393 T
fromRegister(FloatRegister reg
) const {
394 return machine_
->read
<T
>(reg
);
397 // Read an uintptr_t from the stack.
398 bool hasStack(int32_t offset
) const { return true; }
399 uintptr_t fromStack(int32_t offset
) const;
401 bool hasInstructionResult(uint32_t index
) const {
402 return instructionResults_
;
404 bool hasInstructionResults() const { return instructionResults_
; }
405 Value
fromInstructionResult(uint32_t index
) const;
407 Value
allocationValue(const RValueAllocation
& a
,
408 ReadMethod rm
= ReadMethod::Normal
);
409 [[nodiscard
]] bool allocationReadable(const RValueAllocation
& a
,
410 ReadMethod rm
= ReadMethod::Normal
);
411 void writeAllocationValuePayload(const RValueAllocation
& a
, const Value
& v
);
412 void warnUnreadableAllocation();
415 // Handle iterating over RValueAllocations of the snapshots.
416 inline RValueAllocation
readAllocation() {
417 MOZ_ASSERT(moreAllocations());
418 return snapshot_
.readAllocation();
420 void skip() { snapshot_
.skipAllocation(); }
422 const RResumePoint
* resumePoint() const;
423 const RInstruction
* instruction() const { return recover_
.instruction(); }
425 uint32_t numAllocations() const;
426 inline bool moreAllocations() const {
427 return snapshot_
.numAllocationsRead() < numAllocations();
430 JitFrameLayout
* frame() { return fp_
; };
432 // Used by recover instruction to store the value back into the instruction
434 void storeInstructionResult(const Value
& v
);
437 // Exhibits frame properties contained in the snapshot.
438 uint32_t pcOffset() const;
439 ResumeMode
resumeMode() const;
441 bool resumeAfter() const {
442 // Calls in outer frames are never considered resume-after.
443 MOZ_ASSERT_IF(moreFrames(), !IsResumeAfter(resumeMode()));
444 return IsResumeAfter(resumeMode());
446 inline BailoutKind
bailoutKind() const { return snapshot_
.bailoutKind(); }
448 IonScript
* ionScript() const { return ionScript_
; }
451 // Read the next instruction available and get ready to either skip it or
453 inline void nextInstruction() {
454 MOZ_ASSERT(snapshot_
.numAllocationsRead() == numAllocations());
455 recover_
.nextInstruction();
456 snapshot_
.resetNumAllocationsRead();
459 // Skip an Instruction by walking to the next instruction and by skipping
460 // all the allocations corresponding to this instruction.
461 void skipInstruction();
463 inline bool moreInstructions() const { return recover_
.moreInstructions(); }
465 // Register a vector used for storing the results of the evaluation of
466 // recover instructions. This vector should be registered before the
467 // beginning of the iteration. This function is in charge of allocating
468 // enough space for all instructions results, and return false iff it fails.
469 [[nodiscard
]] bool initInstructionResults(MaybeReadFallback
& fallback
);
472 // This function is used internally for computing the result of the recover
474 [[nodiscard
]] bool computeInstructionResults(
475 JSContext
* cx
, RInstructionResults
* results
) const;
478 // Handle iterating over frames of the snapshots.
480 void settleOnFrame();
482 inline bool moreFrames() const {
483 // The last instruction is recovering the innermost frame, so as long as
484 // there is more instruction there is necesseray more frames.
485 return moreInstructions();
489 // Connect all informations about the current script in order to recover the
490 // content of baseline frames.
492 SnapshotIterator(const JSJitFrameIter
& iter
,
493 const MachineState
* machineState
);
496 Value
read() { return allocationValue(readAllocation()); }
498 int32_t readInt32() {
500 MOZ_RELEASE_ASSERT(val
.isInt32());
501 return val
.toInt32();
504 double readNumber() {
506 MOZ_RELEASE_ASSERT(val
.isNumber());
507 return val
.toNumber();
510 // Read the |Normal| value unless it is not available and that the snapshot
511 // provides a |Default| value. This is useful to avoid invalidations of the
512 // frame while we are only interested in a few properties which are provided
513 // by the |Default| value.
514 Value
readWithDefault(RValueAllocation
* alloc
) {
515 *alloc
= RValueAllocation();
516 RValueAllocation a
= readAllocation();
517 if (allocationReadable(a
)) {
518 return allocationValue(a
);
522 return allocationValue(a
, ReadMethod::AlwaysDefault
);
525 Value
maybeRead(const RValueAllocation
& a
, MaybeReadFallback
& fallback
);
526 Value
maybeRead(MaybeReadFallback
& fallback
) {
527 RValueAllocation a
= readAllocation();
528 return maybeRead(a
, fallback
);
531 bool tryRead(Value
* result
);
533 void traceAllocation(JSTracer
* trc
);
536 void readFunctionFrameArgs(Op
& op
, ArgumentsObject
** argsObj
, Value
* thisv
,
537 unsigned start
, unsigned end
, JSScript
* script
,
538 MaybeReadFallback
& fallback
) {
539 // Assumes that the common frame arguments have already been read.
540 if (script
->needsArgsObj()) {
542 Value v
= maybeRead(fallback
);
544 *argsObj
= &v
.toObject().as
<ArgumentsObject
>();
552 *thisv
= maybeRead(fallback
);
562 for (; i
< start
; i
++) {
565 for (; i
< end
; i
++) {
566 // We are not always able to read values from the snapshots, some values
567 // such as non-gc things may still be live in registers and cause an
568 // error while reading the machine state.
569 Value v
= maybeRead(fallback
);
574 // Iterate over all the allocations and return only the value of the
575 // allocation located at one index.
576 Value
maybeReadAllocByIndex(size_t index
);
578 #ifdef TRACK_SNAPSHOTS
579 void spewBailingFrom() const { snapshot_
.spewBailingFrom(); }
583 // Reads frame information in callstack order (that is, innermost frame to
585 class InlineFrameIterator
{
586 const JSJitFrameIter
* frame_
;
587 SnapshotIterator start_
;
588 SnapshotIterator si_
;
589 uint32_t framesRead_
;
591 // When the inline-frame-iterator is created, this variable is defined to
592 // UINT32_MAX. Then the first iteration of findNextFrame, which settle on
593 // the innermost frame, is used to update this counter to the number of
594 // frames contained in the recover buffer.
595 uint32_t frameCount_
;
597 // The |calleeTemplate_| fields contains either the JSFunction or the
598 // template from which it is supposed to be cloned. The |calleeRVA_| is an
599 // Invalid value allocation, if the |calleeTemplate_| field is the effective
600 // JSFunction, and not its template. On the other hand, any other value
601 // allocation implies that the |calleeTemplate_| is the template JSFunction
602 // from which the effective one would be derived and cached by the Recover
603 // instruction result.
604 RootedFunction calleeTemplate_
;
605 RValueAllocation calleeRVA_
;
607 RootedScript script_
;
609 uint32_t numActualArgs_
;
611 // Register state, used by all snapshot iterators.
612 MachineState machine_
;
615 void operator()(const Value
& v
) {}
619 void findNextFrame();
620 JSObject
* computeEnvironmentChain(const Value
& envChainValue
,
621 MaybeReadFallback
& fallback
,
622 bool* hasInitialEnv
= nullptr) const;
625 InlineFrameIterator(JSContext
* cx
, const JSJitFrameIter
* iter
);
626 InlineFrameIterator(JSContext
* cx
, const InlineFrameIterator
* iter
);
628 bool more() const { return frame_
&& framesRead_
< frameCount_
; }
630 // Due to optimizations, we are not always capable of reading the callee of
631 // inlined frames without invalidating the IonCode. This function might
632 // return either the effective callee of the JSFunction which might be used
635 // As such, the |calleeTemplate()| can be used to read most of the metadata
636 // which are conserved across clones.
637 JSFunction
* calleeTemplate() const {
638 MOZ_ASSERT(isFunctionFrame());
639 return calleeTemplate_
;
641 JSFunction
* maybeCalleeTemplate() const { return calleeTemplate_
; }
643 JSFunction
* callee(MaybeReadFallback
& fallback
) const;
645 unsigned numActualArgs() const {
646 // The number of actual arguments for inline frames is determined by this
647 // iterator based on the caller's bytecode instruction (Call, FunCall,
648 // GetProp/SetProp, etc). For the outer function it's stored in the stack
651 return numActualArgs_
;
654 return frame_
->numActualArgs();
657 template <class ArgOp
, class LocalOp
>
658 void readFrameArgsAndLocals(JSContext
* cx
, ArgOp
& argOp
, LocalOp
& localOp
,
659 JSObject
** envChain
, bool* hasInitialEnv
,
660 Value
* rval
, ArgumentsObject
** argsObj
,
661 Value
* thisv
, ReadFrameArgsBehavior behavior
,
662 MaybeReadFallback
& fallback
) const {
663 SnapshotIterator
s(si_
);
665 // Read the env chain.
667 Value envChainValue
= s
.maybeRead(fallback
);
669 computeEnvironmentChain(envChainValue
, fallback
, hasInitialEnv
);
674 // Read return value.
676 *rval
= s
.maybeRead(fallback
);
681 // Read arguments, which only function frames have.
682 if (isFunctionFrame()) {
683 unsigned nactual
= numActualArgs();
684 unsigned nformal
= calleeTemplate()->nargs();
686 // Read the formal arguments, which are taken from the inlined frame,
687 // because it will have the updated value when JSOp::SetArg is used.
688 unsigned numFormalsToRead
;
689 if (behavior
== ReadFrameArgsBehavior::Actuals
) {
690 numFormalsToRead
= std::min(nactual
, nformal
);
692 MOZ_ASSERT(behavior
== ReadFrameArgsBehavior::ActualsAndFormals
);
693 numFormalsToRead
= nformal
;
695 s
.readFunctionFrameArgs(argOp
, argsObj
, thisv
, 0, numFormalsToRead
,
698 // Skip formals we didn't read.
699 for (unsigned i
= numFormalsToRead
; i
< nformal
; i
++) {
703 if (nactual
> nformal
) {
705 // There is still a parent frame of this inlined frame. All
706 // arguments (also the overflown) are the last pushed values
707 // in the parent frame. To get the overflown arguments, we
708 // need to take them from there.
710 // The overflown arguments are not available in current frame.
711 // They are the last pushed arguments in the parent frame of
712 // this inlined frame.
713 InlineFrameIterator
it(cx
, this);
715 unsigned argsObjAdj
= it
.script()->needsArgsObj() ? 1 : 0;
716 bool hasNewTarget
= isConstructing();
717 SnapshotIterator
parent_s(it
.snapshotIterator());
719 // Skip over all slots until we get to the last slots
720 // (= arguments slots of callee) the +3 is for [this], [returnvalue],
721 // [envchain], and maybe +1 for [argsObj]
722 MOZ_ASSERT(parent_s
.numAllocations() >=
723 nactual
+ 3 + argsObjAdj
+ hasNewTarget
);
724 unsigned skip
= parent_s
.numAllocations() - nactual
- 3 - argsObjAdj
-
726 for (unsigned j
= 0; j
< skip
; j
++) {
730 // Get the overflown arguments
731 parent_s
.skip(); // env chain
732 parent_s
.skip(); // return value
733 parent_s
.readFunctionFrameArgs(argOp
, nullptr, nullptr, nformal
,
734 nactual
, it
.script(), fallback
);
736 // There is no parent frame to this inlined frame, we can read
737 // from the frame's Value vector directly.
738 Value
* argv
= frame_
->actualArgs();
739 for (unsigned i
= nformal
; i
< nactual
; i
++) {
746 // At this point we've read all the formals in s, and can read the
748 for (unsigned i
= 0; i
< script()->nfixed(); i
++) {
749 localOp(s
.maybeRead(fallback
));
754 void unaliasedForEachActual(JSContext
* cx
, Op op
,
755 MaybeReadFallback
& fallback
) const {
757 readFrameArgsAndLocals(cx
, op
, nop
, nullptr, nullptr, nullptr, nullptr,
758 nullptr, ReadFrameArgsBehavior::Actuals
, fallback
);
761 JSScript
* script() const { return script_
; }
762 jsbytecode
* pc() const { return pc_
; }
763 SnapshotIterator
snapshotIterator() const { return si_
; }
764 bool isFunctionFrame() const;
765 bool isModuleFrame() const;
766 bool isConstructing() const;
768 JSObject
* environmentChain(MaybeReadFallback
& fallback
,
769 bool* hasInitialEnvironment
= nullptr) const {
770 SnapshotIterator
s(si_
);
773 Value v
= s
.maybeRead(fallback
);
774 return computeEnvironmentChain(v
, fallback
, hasInitialEnvironment
);
777 Value
thisArgument(MaybeReadFallback
& fallback
) const {
778 SnapshotIterator
s(si_
);
787 if (script()->needsArgsObj()) {
791 return s
.maybeRead(fallback
);
794 InlineFrameIterator
& operator++() {
801 void resetOn(const JSJitFrameIter
* iter
);
803 const JSJitFrameIter
& frame() const { return *frame_
; }
805 // Inline frame number, 0 for the outermost (non-inlined) frame.
806 size_t frameNo() const { return frameCount() - framesRead_
; }
807 size_t frameCount() const {
808 MOZ_ASSERT(frameCount_
!= UINT32_MAX
);
813 InlineFrameIterator() = delete;
814 InlineFrameIterator(const InlineFrameIterator
& iter
) = delete;
820 #endif /* jit_JSJitFrameIter_h */