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_JitFrames_h
8 #define jit_JitFrames_h
10 #include "mozilla/Assertions.h"
15 #include "jit/CalleeToken.h"
16 #include "jit/MachineState.h"
17 #include "jit/Registers.h"
19 #include "js/TypeDecls.h"
31 enum class VMFunctionId
;
35 struct SafepointSlotEntry
;
36 struct VMFunctionData
;
38 // [SMDOC] JIT Frame Layout
42 // In between every two frames lies a small header describing both frames. This
43 // header, minimally, contains a returnAddress word and a descriptor word (See
44 // CommonFrameLayout). The descriptor describes the type of the older (caller)
45 // frame, whereas the returnAddress describes the address the newer (callee)
46 // frame will return to. For JitFrameLayout, the descriptor also stores the
47 // number of arguments passed from the caller to the callee frame.
51 // Two special frame types exist:
52 // - Entry frames begin a JitActivation, and therefore there is exactly one
53 // per activation of EnterJit or EnterBaseline. These reuse JitFrameLayout.
54 // - Exit frames are necessary to leave JIT code and enter C++, and thus,
55 // C++ code will always begin iterating from the topmost exit frame.
57 // Approximate Layout:
59 // The layout of an Ion frame on the C stack is roughly:
61 // ... \ - These are jsvals
69 // [SMDOC] Frame Descriptor Layout
71 // A frame descriptor word has the following data:
73 // high bits: [ numActualArgs |
74 // has-cached-saved-frame bit |
75 // low bits: frame type ]
77 // * numActualArgs: for JitFrameLayout, the number of arguments passed by the
79 // * Has-cache-saved-frame bit: Used to power the LiveSavedFrameCache
80 // optimization. See the comment in Activation.h
81 // * Frame Type: BaselineJS, Exit, etc. (jit::FrameType)
84 static const uintptr_t FRAMETYPE_BITS
= 4;
85 static const uintptr_t FRAMETYPE_MASK
= (1 << FRAMETYPE_BITS
) - 1;
86 static const uintptr_t HASCACHEDSAVEDFRAME_BIT
= 1 << FRAMETYPE_BITS
;
87 static const uintptr_t NUMACTUALARGS_SHIFT
=
88 FRAMETYPE_BITS
+ 1 /* HASCACHEDSAVEDFRAME_BIT */;
90 struct BaselineBailoutInfo
;
92 enum class ExceptionResumeKind
: int32_t {
93 // There is no exception handler in this activation.
94 // Return from the entry frame.
97 // The exception was caught in baseline.
98 // Restore state and jump to the catch block.
101 // A finally block must be executed in baseline.
102 // Stash the exception on the stack and jump to the finally block.
105 // We are forcing an early return with a specific return value.
106 // This is used by the debugger and when closing generators.
107 // Immediately return from the current frame with the given value.
108 ForcedReturnBaseline
,
111 // This frame is currently executing in Ion, but we must bail out
112 // to baseline before handling the exception.
113 // Jump to the bailout tail stub.
116 // The innermost frame was a wasm frame.
117 // Return to the wasm entry frame.
120 // The exception was caught by a wasm catch handler.
121 // Restore state and jump to it.
125 // Data needed to recover from an exception.
126 struct ResumeFromException
{
127 uint8_t* framePointer
;
128 uint8_t* stackPointer
;
130 ExceptionResumeKind kind
;
131 wasm::Instance
* instance
;
133 // Value to push when resuming into a |finally| block.
134 // Also used by Wasm to send the exception object to the throw stub.
137 BaselineBailoutInfo
* bailoutInfo
;
139 #if defined(JS_CODEGEN_ARM64)
143 static size_t offsetOfFramePointer() {
144 return offsetof(ResumeFromException
, framePointer
);
146 static size_t offsetOfStackPointer() {
147 return offsetof(ResumeFromException
, stackPointer
);
149 static size_t offsetOfTarget() {
150 return offsetof(ResumeFromException
, target
);
152 static size_t offsetOfKind() { return offsetof(ResumeFromException
, kind
); }
153 static size_t offsetOfInstance() {
154 return offsetof(ResumeFromException
, instance
);
156 static size_t offsetOfException() {
157 return offsetof(ResumeFromException
, exception
);
159 static size_t offsetOfBailoutInfo() {
160 return offsetof(ResumeFromException
, bailoutInfo
);
164 #if defined(JS_CODEGEN_ARM64)
165 static_assert(sizeof(ResumeFromException
) % 16 == 0,
166 "ResumeFromException should be aligned");
169 void HandleException(ResumeFromException
* rfe
);
171 void EnsureUnwoundJitExitFrame(JitActivation
* act
, JitFrameLayout
* frame
);
173 void TraceJitActivations(JSContext
* cx
, JSTracer
* trc
);
175 // Trace weak pointers in baseline stubs in activations for zones that are
176 // currently being swept.
177 void TraceWeakJitActivationsInSweepingZones(JSContext
* cx
, JSTracer
* trc
);
179 void UpdateJitActivationsForMinorGC(JSRuntime
* rt
);
181 static inline uint32_t MakeFrameDescriptor(FrameType type
) {
182 return uint32_t(type
);
185 // For JitFrameLayout, the descriptor also stores the number of arguments passed
186 // by the caller. Note that |type| is the type of the *older* frame and |argc|
187 // is the number of arguments passed to the *newer* frame.
188 static inline uint32_t MakeFrameDescriptorForJitCall(FrameType type
,
190 uint32_t descriptor
= (argc
<< NUMACTUALARGS_SHIFT
) | uint32_t(type
);
191 MOZ_ASSERT((descriptor
>> NUMACTUALARGS_SHIFT
) == argc
,
192 "argc must fit in descriptor");
196 // Returns the JSScript associated with the topmost JIT frame.
197 JSScript
* GetTopJitJSScript(JSContext
* cx
);
199 #if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_ARM64)
200 uint8_t* alignDoubleSpill(uint8_t* pointer
);
202 inline uint8_t* alignDoubleSpill(uint8_t* pointer
) {
203 // This is a no-op on most platforms.
208 // Layout of the frame prefix. This assumes the stack architecture grows down.
209 // If this is ever not the case, we'll have to refactor.
210 class CommonFrameLayout
{
211 uint8_t* callerFramePtr_
;
212 uint8_t* returnAddress_
;
213 uintptr_t descriptor_
;
216 static constexpr size_t offsetOfDescriptor() {
217 return offsetof(CommonFrameLayout
, descriptor_
);
219 uintptr_t descriptor() const { return descriptor_
; }
220 static constexpr size_t offsetOfReturnAddress() {
221 return offsetof(CommonFrameLayout
, returnAddress_
);
223 FrameType
prevType() const { return FrameType(descriptor_
& FRAMETYPE_MASK
); }
224 void changePrevType(FrameType type
) {
225 descriptor_
&= ~FRAMETYPE_MASK
;
226 descriptor_
|= uintptr_t(type
);
228 bool hasCachedSavedFrame() const {
229 return descriptor_
& HASCACHEDSAVEDFRAME_BIT
;
231 void setHasCachedSavedFrame() { descriptor_
|= HASCACHEDSAVEDFRAME_BIT
; }
232 void clearHasCachedSavedFrame() { descriptor_
&= ~HASCACHEDSAVEDFRAME_BIT
; }
233 uint8_t* returnAddress() const { return returnAddress_
; }
234 void setReturnAddress(uint8_t* addr
) { returnAddress_
= addr
; }
236 uint8_t* callerFramePtr() const { return callerFramePtr_
; }
237 static constexpr size_t offsetOfCallerFramePtr() {
238 return offsetof(CommonFrameLayout
, callerFramePtr_
);
240 static constexpr size_t bytesPoppedAfterCall() {
241 // The return address and frame pointer are popped by the callee/call.
242 return 2 * sizeof(void*);
246 class JitFrameLayout
: public CommonFrameLayout
{
247 CalleeToken calleeToken_
;
250 CalleeToken
calleeToken() const { return calleeToken_
; }
251 void replaceCalleeToken(CalleeToken calleeToken
) {
252 calleeToken_
= calleeToken
;
255 static constexpr size_t offsetOfCalleeToken() {
256 return offsetof(JitFrameLayout
, calleeToken_
);
258 static constexpr size_t offsetOfThis() { return sizeof(JitFrameLayout
); }
259 static constexpr size_t offsetOfActualArgs() {
260 return offsetOfThis() + sizeof(JS::Value
);
262 static constexpr size_t offsetOfActualArg(size_t arg
) {
263 return offsetOfActualArgs() + arg
* sizeof(JS::Value
);
267 MOZ_ASSERT(CalleeTokenIsFunction(calleeToken()));
268 return thisAndActualArgs()[0];
270 JS::Value
* thisAndActualArgs() {
271 MOZ_ASSERT(CalleeTokenIsFunction(calleeToken()));
272 return (JS::Value
*)(this + 1);
274 JS::Value
* actualArgs() { return thisAndActualArgs() + 1; }
275 uintptr_t numActualArgs() const {
276 return descriptor() >> NUMACTUALARGS_SHIFT
;
279 // Computes a reference to a stack or argument slot, where a slot is a
280 // distance from the base frame pointer, as would be used for LStackSlot
282 uintptr_t* slotRef(SafepointSlotEntry where
);
284 static inline size_t Size() { return sizeof(JitFrameLayout
); }
287 class BaselineInterpreterEntryFrameLayout
: public JitFrameLayout
{
289 static inline size_t Size() {
290 return sizeof(BaselineInterpreterEntryFrameLayout
);
294 class RectifierFrameLayout
: public JitFrameLayout
{
296 static inline size_t Size() { return sizeof(RectifierFrameLayout
); }
299 class WasmToJSJitFrameLayout
: public JitFrameLayout
{
301 static inline size_t Size() { return sizeof(WasmToJSJitFrameLayout
); }
304 class IonICCallFrameLayout
: public CommonFrameLayout
{
306 // Pointer to root the stub's JitCode.
310 static constexpr size_t LocallyTracedValueOffset
= sizeof(void*);
312 JitCode
** stubCode() { return &stubCode_
; }
313 static size_t Size() { return sizeof(IonICCallFrameLayout
); }
315 inline Value
* locallyTracedValuePtr(size_t index
) {
316 uint8_t* fp
= reinterpret_cast<uint8_t*>(this);
317 return reinterpret_cast<Value
*>(fp
- LocallyTracedValueOffset
-
318 index
* sizeof(Value
));
322 enum class ExitFrameType
: uint8_t {
324 ConstructNative
= 0x1,
330 WasmGenericJitEntry
= 0x7,
331 DirectWasmJitCall
= 0x8,
333 InterpreterStub
= 0xA,
337 // This must be the last value in this enum. See ExitFooterFrame::data_.
341 // GC related data used to keep alive data surrounding the Exit frame.
342 class ExitFooterFrame
{
343 // Stores either the ExitFrameType or, for a VMFunction call,
344 // `ExitFrameType::VMFunction + VMFunctionId`.
348 void assertValidVMFunctionId() const;
350 void assertValidVMFunctionId() const {}
354 static constexpr size_t Size() { return sizeof(ExitFooterFrame
); }
355 void setUnwoundJitExitFrame() {
356 data_
= uintptr_t(ExitFrameType::UnwoundJit
);
358 ExitFrameType
type() const {
359 if (data_
>= uintptr_t(ExitFrameType::VMFunction
)) {
360 return ExitFrameType::VMFunction
;
362 return ExitFrameType(data_
);
364 VMFunctionId
functionId() const {
365 MOZ_ASSERT(type() == ExitFrameType::VMFunction
);
366 assertValidVMFunctionId();
367 return static_cast<VMFunctionId
>(data_
- size_t(ExitFrameType::VMFunction
));
370 #ifdef JS_CODEGEN_MIPS32
371 uint8_t* alignedForABI() {
372 // See: MacroAssemblerMIPSCompat::alignStackPointer()
373 uint8_t* address
= reinterpret_cast<uint8_t*>(this);
374 address
-= sizeof(intptr_t);
375 return alignDoubleSpill(address
);
378 uint8_t* alignedForABI() {
379 // This is NO-OP on non-MIPS platforms.
380 return reinterpret_cast<uint8_t*>(this);
384 // This should only be called for function()->outParam == Type_Handle
385 template <typename T
>
387 uint8_t* address
= alignedForABI();
388 return reinterpret_cast<T
*>(address
- sizeof(T
));
392 class NativeExitFrameLayout
;
393 class IonOOLNativeExitFrameLayout
;
394 class IonOOLProxyExitFrameLayout
;
395 class IonDOMExitFrameLayout
;
397 // this is the frame layout when we are exiting ion code, and about to enter
399 class ExitFrameLayout
: public CommonFrameLayout
{
400 inline uint8_t* top() { return reinterpret_cast<uint8_t*>(this + 1); }
403 static inline size_t Size() { return sizeof(ExitFrameLayout
); }
404 static inline size_t SizeWithFooter() {
405 return Size() + ExitFooterFrame::Size();
408 inline ExitFooterFrame
* footer() {
409 uint8_t* sp
= reinterpret_cast<uint8_t*>(this);
410 return reinterpret_cast<ExitFooterFrame
*>(sp
- ExitFooterFrame::Size());
413 // argBase targets the point which precedes the exit frame. Arguments of VM
414 // each wrapper are pushed before the exit frame. This correspond exactly
415 // to the value of the argBase register of the generateVMWrapper function.
416 inline uint8_t* argBase() {
417 MOZ_ASSERT(isWrapperExit());
421 inline bool isWrapperExit() {
422 return footer()->type() == ExitFrameType::VMFunction
;
424 inline bool isBareExit() { return footer()->type() == ExitFrameType::Bare
; }
425 inline bool isUnwoundJitExit() {
426 return footer()->type() == ExitFrameType::UnwoundJit
;
429 // See the various exit frame layouts below.
430 template <typename T
>
432 return footer()->type() == T::Type();
434 template <typename T
>
436 MOZ_ASSERT(this->is
<T
>());
437 return reinterpret_cast<T
*>(footer());
441 // Cannot inherit implementation since we need to extend the top of
443 class NativeExitFrameLayout
{
444 protected: // only to silence a clang warning about unused private fields
445 ExitFooterFrame footer_
;
446 ExitFrameLayout exit_
;
449 // We need to split the Value into 2 fields of 32 bits, otherwise the C++
450 // compiler may add some padding between the fields.
451 uint32_t loCalleeResult_
;
452 uint32_t hiCalleeResult_
;
455 static inline size_t Size() { return sizeof(NativeExitFrameLayout
); }
457 static size_t offsetOfResult() {
458 return offsetof(NativeExitFrameLayout
, loCalleeResult_
);
460 inline JS::Value
* vp() {
461 return reinterpret_cast<JS::Value
*>(&loCalleeResult_
);
463 inline uintptr_t argc() const { return argc_
; }
466 class CallNativeExitFrameLayout
: public NativeExitFrameLayout
{
468 static ExitFrameType
Type() { return ExitFrameType::CallNative
; }
471 class ConstructNativeExitFrameLayout
: public NativeExitFrameLayout
{
473 static ExitFrameType
Type() { return ExitFrameType::ConstructNative
; }
477 inline bool ExitFrameLayout::is
<NativeExitFrameLayout
>() {
478 return is
<CallNativeExitFrameLayout
>() ||
479 is
<ConstructNativeExitFrameLayout
>();
482 class IonOOLNativeExitFrameLayout
{
483 protected: // only to silence a clang warning about unused private fields
484 ExitFooterFrame footer_
;
485 ExitFrameLayout exit_
;
487 // pointer to root the stub's JitCode
492 // We need to split the Value into 2 fields of 32 bits, otherwise the C++
493 // compiler may add some padding between the fields.
494 uint32_t loCalleeResult_
;
495 uint32_t hiCalleeResult_
;
497 // Split Value for |this| and args above.
502 static ExitFrameType
Type() { return ExitFrameType::IonOOLNative
; }
504 static inline size_t Size(size_t argc
) {
505 // The frame accounts for the callee/result and |this|, so we only need
507 return sizeof(IonOOLNativeExitFrameLayout
) + (argc
* sizeof(JS::Value
));
510 static size_t offsetOfResult() {
511 return offsetof(IonOOLNativeExitFrameLayout
, loCalleeResult_
);
514 inline JitCode
** stubCode() { return &stubCode_
; }
515 inline JS::Value
* vp() {
516 return reinterpret_cast<JS::Value
*>(&loCalleeResult_
);
518 inline JS::Value
* thisp() { return reinterpret_cast<JS::Value
*>(&loThis_
); }
519 inline uintptr_t argc() const { return argc_
; }
522 // ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id,
523 // MutableHandleValue vp)
524 // ProxyCallProperty(JSContext* cx, HandleObject proxy, HandleId id,
525 // MutableHandleValue vp)
526 // ProxySetProperty(JSContext* cx, HandleObject proxy, HandleId id,
527 // MutableHandleValue vp, bool strict)
528 class IonOOLProxyExitFrameLayout
{
529 protected: // only to silence a clang warning about unused private fields
530 ExitFooterFrame footer_
;
531 ExitFrameLayout exit_
;
539 // space for MutableHandleValue result
540 // use two uint32_t so compiler doesn't align.
544 // pointer to root the stub's JitCode
548 static ExitFrameType
Type() { return ExitFrameType::IonOOLProxy
; }
550 static inline size_t Size() { return sizeof(IonOOLProxyExitFrameLayout
); }
552 static size_t offsetOfResult() {
553 return offsetof(IonOOLProxyExitFrameLayout
, vp0_
);
556 inline JitCode
** stubCode() { return &stubCode_
; }
557 inline JS::Value
* vp() { return reinterpret_cast<JS::Value
*>(&vp0_
); }
558 inline jsid
* id() { return &id_
; }
559 inline JSObject
** proxy() { return &proxy_
; }
562 class IonDOMExitFrameLayout
{
563 protected: // only to silence a clang warning about unused private fields
564 ExitFooterFrame footer_
;
565 ExitFrameLayout exit_
;
568 // We need to split the Value into 2 fields of 32 bits, otherwise the C++
569 // compiler may add some padding between the fields.
570 uint32_t loCalleeResult_
;
571 uint32_t hiCalleeResult_
;
574 static ExitFrameType
GetterType() { return ExitFrameType::IonDOMGetter
; }
575 static ExitFrameType
SetterType() { return ExitFrameType::IonDOMSetter
; }
577 static inline size_t Size() { return sizeof(IonDOMExitFrameLayout
); }
579 static size_t offsetOfResult() {
580 return offsetof(IonDOMExitFrameLayout
, loCalleeResult_
);
582 inline JS::Value
* vp() {
583 return reinterpret_cast<JS::Value
*>(&loCalleeResult_
);
585 inline JSObject
** thisObjAddress() { return &thisObj
; }
586 inline bool isMethodFrame();
589 struct IonDOMMethodExitFrameLayoutTraits
;
591 class IonDOMMethodExitFrameLayout
{
592 protected: // only to silence a clang warning about unused private fields
593 ExitFooterFrame footer_
;
594 ExitFrameLayout exit_
;
595 // This must be the last thing pushed, so as to stay common with
596 // IonDOMExitFrameLayout.
601 // We need to split the Value into 2 fields of 32 bits, otherwise the C++
602 // compiler may add some padding between the fields.
603 uint32_t loCalleeResult_
;
604 uint32_t hiCalleeResult_
;
606 friend struct IonDOMMethodExitFrameLayoutTraits
;
609 static ExitFrameType
Type() { return ExitFrameType::IonDOMMethod
; }
611 static inline size_t Size() { return sizeof(IonDOMMethodExitFrameLayout
); }
613 static size_t offsetOfResult() {
614 return offsetof(IonDOMMethodExitFrameLayout
, loCalleeResult_
);
617 inline JS::Value
* vp() {
618 // The code in visitCallDOMNative depends on this static assert holding
620 offsetof(IonDOMMethodExitFrameLayout
, loCalleeResult_
) ==
621 (offsetof(IonDOMMethodExitFrameLayout
, argc_
) + sizeof(uintptr_t)));
622 return reinterpret_cast<JS::Value
*>(&loCalleeResult_
);
624 inline JSObject
** thisObjAddress() { return &thisObj_
; }
625 inline uintptr_t argc() { return argc_
; }
628 inline bool IonDOMExitFrameLayout::isMethodFrame() {
629 return footer_
.type() == IonDOMMethodExitFrameLayout::Type();
633 inline bool ExitFrameLayout::is
<IonDOMExitFrameLayout
>() {
634 ExitFrameType type
= footer()->type();
635 return type
== IonDOMExitFrameLayout::GetterType() ||
636 type
== IonDOMExitFrameLayout::SetterType() ||
637 type
== IonDOMMethodExitFrameLayout::Type();
641 inline IonDOMExitFrameLayout
* ExitFrameLayout::as
<IonDOMExitFrameLayout
>() {
642 MOZ_ASSERT(is
<IonDOMExitFrameLayout
>());
643 return reinterpret_cast<IonDOMExitFrameLayout
*>(footer());
646 struct IonDOMMethodExitFrameLayoutTraits
{
647 static const size_t offsetOfArgcFromArgv
=
648 offsetof(IonDOMMethodExitFrameLayout
, argc_
) -
649 offsetof(IonDOMMethodExitFrameLayout
, argv_
);
652 // Cannot inherit implementation since we need to extend the top of
654 class CalledFromJitExitFrameLayout
{
655 protected: // silence clang warning about unused private fields
656 ExitFooterFrame footer_
;
657 JitFrameLayout exit_
;
660 static inline size_t Size() { return sizeof(CalledFromJitExitFrameLayout
); }
661 inline JitFrameLayout
* jsFrame() { return &exit_
; }
662 static size_t offsetOfExitFrame() {
663 return offsetof(CalledFromJitExitFrameLayout
, exit_
);
667 class LazyLinkExitFrameLayout
: public CalledFromJitExitFrameLayout
{
669 static ExitFrameType
Type() { return ExitFrameType::LazyLink
; }
672 class InterpreterStubExitFrameLayout
: public CalledFromJitExitFrameLayout
{
674 static ExitFrameType
Type() { return ExitFrameType::InterpreterStub
; }
677 class WasmGenericJitEntryFrameLayout
: CalledFromJitExitFrameLayout
{
679 static ExitFrameType
Type() { return ExitFrameType::WasmGenericJitEntry
; }
683 inline bool ExitFrameLayout::is
<CalledFromJitExitFrameLayout
>() {
684 return is
<InterpreterStubExitFrameLayout
>() ||
685 is
<LazyLinkExitFrameLayout
>() || is
<WasmGenericJitEntryFrameLayout
>();
689 inline CalledFromJitExitFrameLayout
*
690 ExitFrameLayout::as
<CalledFromJitExitFrameLayout
>() {
691 MOZ_ASSERT(is
<CalledFromJitExitFrameLayout
>());
692 uint8_t* sp
= reinterpret_cast<uint8_t*>(this);
693 sp
-= CalledFromJitExitFrameLayout::offsetOfExitFrame();
694 return reinterpret_cast<CalledFromJitExitFrameLayout
*>(sp
);
697 class DirectWasmJitCallFrameLayout
{
698 protected: // silence clang warning about unused private fields
699 ExitFooterFrame footer_
;
700 ExitFrameLayout exit_
;
703 static ExitFrameType
Type() { return ExitFrameType::DirectWasmJitCall
; }
708 class BaselineStubFrameLayout
: public CommonFrameLayout
{
711 // +-----------------------+
712 // |BaselineStubFrameLayout|
713 // +-----------------------+
714 // | - Descriptor | => Marks end of FrameType::BaselineJS
715 // | - Return address |
716 // | - CallerFramePtr |
717 // +-----------------------+
718 // | - StubPtr | Technically this last field is not part
719 // +-----------------------+ of the frame layout.
722 static constexpr size_t ICStubOffset
= sizeof(void*);
723 static constexpr int ICStubOffsetFromFP
= -int(ICStubOffset
);
724 static constexpr size_t LocallyTracedValueOffset
= 2 * sizeof(void*);
726 static inline size_t Size() { return sizeof(BaselineStubFrameLayout
); }
728 ICStub
* maybeStubPtr() {
729 uint8_t* fp
= reinterpret_cast<uint8_t*>(this);
730 return *reinterpret_cast<ICStub
**>(fp
- ICStubOffset
);
732 void setStubPtr(ICStub
* stub
) {
734 uint8_t* fp
= reinterpret_cast<uint8_t*>(this);
735 *reinterpret_cast<ICStub
**>(fp
- ICStubOffset
) = stub
;
738 inline Value
* locallyTracedValuePtr(size_t index
) {
739 uint8_t* fp
= reinterpret_cast<uint8_t*>(this);
740 return reinterpret_cast<Value
*>(fp
- LocallyTracedValueOffset
-
741 index
* sizeof(Value
));
745 // An invalidation bailout stack is at the stack pointer for the callee frame.
746 class InvalidationBailoutStack
{
747 RegisterDump::FPUArray fpregs_
;
748 RegisterDump::GPRArray regs_
;
749 IonScript
* ionScript_
;
750 uint8_t* osiPointReturnAddress_
;
753 uint8_t* sp() const {
754 return (uint8_t*)this + sizeof(InvalidationBailoutStack
);
756 JitFrameLayout
* fp() const;
757 MachineState
machine() { return MachineState::FromBailout(regs_
, fpregs_
); }
759 IonScript
* ionScript() const { return ionScript_
; }
760 uint8_t* osiPointReturnAddress() const { return osiPointReturnAddress_
; }
761 static size_t offsetOfFpRegs() {
762 return offsetof(InvalidationBailoutStack
, fpregs_
);
764 static size_t offsetOfRegs() {
765 return offsetof(InvalidationBailoutStack
, regs_
);
768 void checkInvariants() const;
771 void GetPcScript(JSContext
* cx
, JSScript
** scriptRes
, jsbytecode
** pcRes
);
773 // Baseline requires one slot for this/argument type checks.
774 static const uint32_t MinJITStackSize
= 1;
776 } /* namespace jit */
779 #endif /* jit_JitFrames_h */