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