Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / js / src / jit / JitFrames.h
blob83e43af5f5833674190751dc1b1eab63f97d4c6a
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"
12 #include <stddef.h>
13 #include <stdint.h>
15 #include "jit/CalleeToken.h"
16 #include "jit/MachineState.h"
17 #include "jit/Registers.h"
18 #include "js/Id.h"
19 #include "js/TypeDecls.h"
20 #include "js/Value.h"
22 namespace js {
24 namespace wasm {
25 class Instance;
28 namespace jit {
30 enum class FrameType;
31 enum class VMFunctionId;
32 class IonScript;
33 class JitActivation;
34 class JitFrameLayout;
35 struct SafepointSlotEntry;
36 struct VMFunctionData;
38 // [SMDOC] JIT Frame Layout
40 // Frame Headers:
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.
49 // Special Frames:
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:
60 // argN _
61 // ... \ - These are jsvals
62 // arg0 /
63 // -3 this _/
64 // -2 callee
65 // -1 descriptor
66 // 0 returnAddress
67 // .. locals ..
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
78 // caller.
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.
95 EntryFrame,
97 // The exception was caught in baseline.
98 // Restore state and jump to the catch block.
99 Catch,
101 // A finally block must be executed in baseline.
102 // Stash the exception on the stack and jump to the finally block.
103 Finally,
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,
109 ForcedReturnIon,
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.
114 Bailout,
116 // The innermost frame was a wasm frame.
117 // Return to the wasm entry frame.
118 Wasm,
120 // The exception was caught by a wasm catch handler.
121 // Restore state and jump to it.
122 WasmCatch
125 // Data needed to recover from an exception.
126 struct ResumeFromException {
127 uint8_t* framePointer;
128 uint8_t* stackPointer;
129 uint8_t* target;
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.
135 JS::Value exception;
137 BaselineBailoutInfo* bailoutInfo;
139 #if defined(JS_CODEGEN_ARM64)
140 uint64_t padding_;
141 #endif
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");
167 #endif
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,
189 uint32_t argc) {
190 uint32_t descriptor = (argc << NUMACTUALARGS_SHIFT) | uint32_t(type);
191 MOZ_ASSERT((descriptor >> NUMACTUALARGS_SHIFT) == argc,
192 "argc must fit in descriptor");
193 return 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);
201 #else
202 inline uint8_t* alignDoubleSpill(uint8_t* pointer) {
203 // This is a no-op on most platforms.
204 return pointer;
206 #endif
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_;
215 public:
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_;
249 public:
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);
266 JS::Value& thisv() {
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
281 // or LArgument.
282 uintptr_t* slotRef(SafepointSlotEntry where);
284 static inline size_t Size() { return sizeof(JitFrameLayout); }
287 class BaselineInterpreterEntryFrameLayout : public JitFrameLayout {
288 public:
289 static inline size_t Size() {
290 return sizeof(BaselineInterpreterEntryFrameLayout);
294 class RectifierFrameLayout : public JitFrameLayout {
295 public:
296 static inline size_t Size() { return sizeof(RectifierFrameLayout); }
299 class WasmToJSJitFrameLayout : public JitFrameLayout {
300 public:
301 static inline size_t Size() { return sizeof(WasmToJSJitFrameLayout); }
304 class IonICCallFrameLayout : public CommonFrameLayout {
305 protected:
306 // Pointer to root the stub's JitCode.
307 JitCode* stubCode_;
309 public:
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 {
323 CallNative = 0x0,
324 ConstructNative = 0x1,
325 IonDOMGetter = 0x2,
326 IonDOMSetter = 0x3,
327 IonDOMMethod = 0x4,
328 IonOOLNative = 0x5,
329 IonOOLProxy = 0x6,
330 WasmGenericJitEntry = 0x7,
331 DirectWasmJitCall = 0x8,
332 UnwoundJit = 0x9,
333 InterpreterStub = 0xA,
334 LazyLink = 0xB,
335 Bare = 0xC,
337 // This must be the last value in this enum. See ExitFooterFrame::data_.
338 VMFunction = 0xD
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`.
345 uintptr_t data_;
347 #ifdef DEBUG
348 void assertValidVMFunctionId() const;
349 #else
350 void assertValidVMFunctionId() const {}
351 #endif
353 public:
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);
377 #else
378 uint8_t* alignedForABI() {
379 // This is NO-OP on non-MIPS platforms.
380 return reinterpret_cast<uint8_t*>(this);
382 #endif
384 // This should only be called for function()->outParam == Type_Handle
385 template <typename T>
386 T* outParam() {
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
398 // platform ABI code
399 class ExitFrameLayout : public CommonFrameLayout {
400 inline uint8_t* top() { return reinterpret_cast<uint8_t*>(this + 1); }
402 public:
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());
418 return top();
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>
431 inline bool is() {
432 return footer()->type() == T::Type();
434 template <typename T>
435 inline T* as() {
436 MOZ_ASSERT(this->is<T>());
437 return reinterpret_cast<T*>(footer());
441 // Cannot inherit implementation since we need to extend the top of
442 // ExitFrameLayout.
443 class NativeExitFrameLayout {
444 protected: // only to silence a clang warning about unused private fields
445 ExitFooterFrame footer_;
446 ExitFrameLayout exit_;
447 uintptr_t argc_;
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_;
454 public:
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 {
467 public:
468 static ExitFrameType Type() { return ExitFrameType::CallNative; }
471 class ConstructNativeExitFrameLayout : public NativeExitFrameLayout {
472 public:
473 static ExitFrameType Type() { return ExitFrameType::ConstructNative; }
476 template <>
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
488 JitCode* stubCode_;
490 uintptr_t argc_;
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.
498 uint32_t loThis_;
499 uint32_t hiThis_;
501 public:
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
506 // args.
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_;
533 // The proxy object.
534 JSObject* proxy_;
536 // id for HandleId
537 jsid id_;
539 // space for MutableHandleValue result
540 // use two uint32_t so compiler doesn't align.
541 uint32_t vp0_;
542 uint32_t vp1_;
544 // pointer to root the stub's JitCode
545 JitCode* stubCode_;
547 public:
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_;
566 JSObject* thisObj;
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_;
573 public:
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.
597 JSObject* thisObj_;
598 JS::Value* argv_;
599 uintptr_t argc_;
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;
608 public:
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
619 static_assert(
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();
632 template <>
633 inline bool ExitFrameLayout::is<IonDOMExitFrameLayout>() {
634 ExitFrameType type = footer()->type();
635 return type == IonDOMExitFrameLayout::GetterType() ||
636 type == IonDOMExitFrameLayout::SetterType() ||
637 type == IonDOMMethodExitFrameLayout::Type();
640 template <>
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
653 // ExitFrameLayout.
654 class CalledFromJitExitFrameLayout {
655 protected: // silence clang warning about unused private fields
656 ExitFooterFrame footer_;
657 JitFrameLayout exit_;
659 public:
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 {
668 public:
669 static ExitFrameType Type() { return ExitFrameType::LazyLink; }
672 class InterpreterStubExitFrameLayout : public CalledFromJitExitFrameLayout {
673 public:
674 static ExitFrameType Type() { return ExitFrameType::InterpreterStub; }
677 class WasmGenericJitEntryFrameLayout : CalledFromJitExitFrameLayout {
678 public:
679 static ExitFrameType Type() { return ExitFrameType::WasmGenericJitEntry; }
682 template <>
683 inline bool ExitFrameLayout::is<CalledFromJitExitFrameLayout>() {
684 return is<InterpreterStubExitFrameLayout>() ||
685 is<LazyLinkExitFrameLayout>() || is<WasmGenericJitEntryFrameLayout>();
688 template <>
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_;
702 public:
703 static ExitFrameType Type() { return ExitFrameType::DirectWasmJitCall; }
706 class ICStub;
708 class BaselineStubFrameLayout : public CommonFrameLayout {
709 // Info on the stack
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.
721 public:
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) {
733 MOZ_ASSERT(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_;
752 public:
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 */
777 } /* namespace js */
779 #endif /* jit_JitFrames_h */