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/. */
6
7 #ifndef jit_x64_SharedICHelpers_x64_inl_h
8 #define jit_x64_SharedICHelpers_x64_inl_h
9
10 #include "jit/BaselineFrame.h"
11 #include "jit/SharedICHelpers.h"
12
13 #include "jit/MacroAssembler-inl.h"
14
15 namespace js {
16 namespace jit {
17
EmitBaselineTailCallVM(TrampolinePtr target,MacroAssembler & masm,uint32_t argSize)18 inline void EmitBaselineTailCallVM(TrampolinePtr target, MacroAssembler& masm,
19 uint32_t argSize) {
20 ScratchRegisterScope scratch(masm);
21
22 // We an assume during this that R0 and R1 have been pushed.
23 masm.movq(BaselineFrameReg, scratch);
24 masm.addq(Imm32(BaselineFrame::FramePointerOffset), scratch);
25 masm.subq(BaselineStackReg, scratch);
26
27 #ifdef DEBUG
28 // Store frame size without VMFunction arguments for debug assertions.
29 masm.movq(scratch, rdx);
30 masm.subq(Imm32(argSize), rdx);
31 Address frameSizeAddr(BaselineFrameReg,
32 BaselineFrame::reverseOffsetOfDebugFrameSize());
33 masm.store32(rdx, frameSizeAddr);
34 #endif
35
36 // Push frame descriptor and perform the tail call.
37 masm.makeFrameDescriptor(scratch, FrameType::BaselineJS,
38 ExitFrameLayout::Size());
39 masm.push(scratch);
40 masm.push(ICTailCallReg);
41 masm.jump(target);
42 }
43
EmitBaselineCreateStubFrameDescriptor(MacroAssembler & masm,Register reg,uint32_t headerSize)44 inline void EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm,
45 Register reg,
46 uint32_t headerSize) {
47 // Compute stub frame size. We have to add two pointers: the stub reg and
48 // previous frame pointer pushed by EmitEnterStubFrame.
49 masm.movq(BaselineFrameReg, reg);
50 masm.addq(Imm32(sizeof(void*) * 2), reg);
51 masm.subq(BaselineStackReg, reg);
52
53 masm.makeFrameDescriptor(reg, FrameType::BaselineStub, headerSize);
54 }
55
EmitBaselineCallVM(TrampolinePtr target,MacroAssembler & masm)56 inline void EmitBaselineCallVM(TrampolinePtr target, MacroAssembler& masm) {
57 ScratchRegisterScope scratch(masm);
58 EmitBaselineCreateStubFrameDescriptor(masm, scratch, ExitFrameLayout::Size());
59 masm.push(scratch);
60 masm.call(target);
61 }
62
63 // Size of values pushed by EmitBaselineEnterStubFrame.
64 static const uint32_t STUB_FRAME_SIZE = 4 * sizeof(void*);
65 static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = sizeof(void*);
66
EmitBaselineEnterStubFrame(MacroAssembler & masm,Register)67 inline void EmitBaselineEnterStubFrame(MacroAssembler& masm, Register) {
68 ScratchRegisterScope scratch(masm);
69
70 // Compute frame size. Because the return address is still on the stack,
71 // this is:
72 //
73 // BaselineFrameReg
74 // + BaselineFrame::FramePointerOffset
75 // - BaselineStackReg
76 // - sizeof(return address)
77 //
78 // The two constants cancel each other out, so we can just calculate
79 // BaselineFrameReg - BaselineStackReg.
80
81 static_assert(
82 BaselineFrame::FramePointerOffset == sizeof(void*),
83 "FramePointerOffset must be the same as the return address size");
84
85 masm.movq(BaselineFrameReg, scratch);
86 masm.subq(BaselineStackReg, scratch);
87
88 #ifdef DEBUG
89 Address frameSizeAddr(BaselineFrameReg,
90 BaselineFrame::reverseOffsetOfDebugFrameSize());
91 masm.store32(scratch, frameSizeAddr);
92 #endif
93
94 // Note: when making changes here, don't forget to update STUB_FRAME_SIZE
95 // if needed.
96
97 // Push the return address that's currently on top of the stack.
98 masm.Push(Operand(BaselineStackReg, 0));
99
100 // Replace the original return address with the frame descriptor.
101 masm.makeFrameDescriptor(scratch, FrameType::BaselineJS,
102 BaselineStubFrameLayout::Size());
103 masm.storePtr(scratch, Address(BaselineStackReg, sizeof(uintptr_t)));
104
105 // Save old frame pointer, stack pointer and stub reg.
106 masm.Push(ICStubReg);
107 masm.Push(BaselineFrameReg);
108 masm.mov(BaselineStackReg, BaselineFrameReg);
109 }
110
111 } // namespace jit
112 } // namespace js
113
114 #endif /* jit_x64_SharedICHelpers_x64_inl_h */
115