Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_MACRO_ASSEMBLER_H_
6 : #define V8_MACRO_ASSEMBLER_H_
7 :
8 : #include "src/assembler.h"
9 : #include "src/frames.h"
10 :
11 : // Helper types to make boolean flag easier to read at call-site.
12 : enum InvokeFlag {
13 : CALL_FUNCTION,
14 : JUMP_FUNCTION
15 : };
16 :
17 :
18 : // Flags used for the AllocateInNewSpace functions.
19 : enum AllocationFlags {
20 : // No special flags.
21 : NO_ALLOCATION_FLAGS = 0,
22 : // The content of the result register already contains the allocation top in
23 : // new space.
24 : RESULT_CONTAINS_TOP = 1 << 0,
25 : // Specify that the requested size of the space to allocate is specified in
26 : // words instead of bytes.
27 : SIZE_IN_WORDS = 1 << 1,
28 : // Align the allocation to a multiple of kDoubleSize
29 : DOUBLE_ALIGNMENT = 1 << 2,
30 : // Directly allocate in old space
31 : PRETENURE = 1 << 3,
32 : };
33 :
34 : #if V8_TARGET_ARCH_IA32
35 : #include "src/ia32/macro-assembler-ia32.h"
36 : #elif V8_TARGET_ARCH_X64
37 : #include "src/x64/macro-assembler-x64.h"
38 : #elif V8_TARGET_ARCH_ARM64
39 : #include "src/arm64/constants-arm64.h"
40 : #include "src/arm64/macro-assembler-arm64.h"
41 : #elif V8_TARGET_ARCH_ARM
42 : #include "src/arm/constants-arm.h"
43 : #include "src/arm/macro-assembler-arm.h"
44 : #elif V8_TARGET_ARCH_PPC
45 : #include "src/ppc/constants-ppc.h"
46 : #include "src/ppc/macro-assembler-ppc.h"
47 : #elif V8_TARGET_ARCH_MIPS
48 : #include "src/mips/constants-mips.h"
49 : #include "src/mips/macro-assembler-mips.h"
50 : #elif V8_TARGET_ARCH_MIPS64
51 : #include "src/mips64/constants-mips64.h"
52 : #include "src/mips64/macro-assembler-mips64.h"
53 : #elif V8_TARGET_ARCH_S390
54 : #include "src/s390/constants-s390.h"
55 : #include "src/s390/macro-assembler-s390.h"
56 : #else
57 : #error Unsupported target architecture.
58 : #endif
59 :
60 : namespace v8 {
61 : namespace internal {
62 :
63 : // Simulators only support C calls with up to kMaxCParameters parameters.
64 : static constexpr int kMaxCParameters = 9;
65 :
66 : class FrameScope {
67 : public:
68 3258532 : explicit FrameScope(TurboAssembler* tasm, StackFrame::Type type)
69 3258532 : : tasm_(tasm), type_(type), old_has_frame_(tasm->has_frame()) {
70 : tasm->set_has_frame(true);
71 1629266 : if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) {
72 142681 : tasm->EnterFrame(type);
73 : }
74 1629266 : }
75 :
76 1629101 : ~FrameScope() {
77 1629101 : if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
78 142681 : tasm_->LeaveFrame(type_);
79 : }
80 1629101 : tasm_->set_has_frame(old_has_frame_);
81 1629101 : }
82 :
83 : // Normally we generate the leave-frame code when this object goes
84 : // out of scope. Sometimes we may need to generate the code somewhere else
85 : // in addition. Calling this will achieve that, but the object stays in
86 : // scope, the MacroAssembler is still marked as being in a frame scope, and
87 : // the code will be generated again when it goes out of scope.
88 : void GenerateLeaveFrame() {
89 : DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
90 31 : tasm_->LeaveFrame(type_);
91 : }
92 :
93 : private:
94 : TurboAssembler* tasm_;
95 : StackFrame::Type type_;
96 : bool old_has_frame_;
97 : };
98 :
99 : class FrameAndConstantPoolScope {
100 : public:
101 : FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
102 : : masm_(masm),
103 : type_(type),
104 : old_has_frame_(masm->has_frame()),
105 : old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
106 : masm->is_constant_pool_available()) {
107 : masm->set_has_frame(true);
108 : if (FLAG_enable_embedded_constant_pool) {
109 : masm->set_constant_pool_available(true);
110 : }
111 : if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
112 : masm->EnterFrame(type, !old_constant_pool_available_);
113 : }
114 : }
115 :
116 : ~FrameAndConstantPoolScope() {
117 : masm_->LeaveFrame(type_);
118 : masm_->set_has_frame(old_has_frame_);
119 : if (FLAG_enable_embedded_constant_pool) {
120 : masm_->set_constant_pool_available(old_constant_pool_available_);
121 : }
122 : }
123 :
124 : // Normally we generate the leave-frame code when this object goes
125 : // out of scope. Sometimes we may need to generate the code somewhere else
126 : // in addition. Calling this will achieve that, but the object stays in
127 : // scope, the MacroAssembler is still marked as being in a frame scope, and
128 : // the code will be generated again when it goes out of scope.
129 : void GenerateLeaveFrame() {
130 : DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
131 : masm_->LeaveFrame(type_);
132 : }
133 :
134 : private:
135 : MacroAssembler* masm_;
136 : StackFrame::Type type_;
137 : bool old_has_frame_;
138 : bool old_constant_pool_available_;
139 :
140 : DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
141 : };
142 :
143 : // Class for scoping the the unavailability of constant pool access.
144 : class ConstantPoolUnavailableScope {
145 : public:
146 : explicit ConstantPoolUnavailableScope(Assembler* assembler)
147 : : assembler_(assembler),
148 : old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
149 : assembler->is_constant_pool_available()) {
150 : if (FLAG_enable_embedded_constant_pool) {
151 : assembler->set_constant_pool_available(false);
152 : }
153 : }
154 : ~ConstantPoolUnavailableScope() {
155 : if (FLAG_enable_embedded_constant_pool) {
156 : assembler_->set_constant_pool_available(old_constant_pool_available_);
157 : }
158 : }
159 :
160 : private:
161 : Assembler* assembler_;
162 : int old_constant_pool_available_;
163 :
164 : DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
165 : };
166 :
167 :
168 77222 : class AllowExternalCallThatCantCauseGC: public FrameScope {
169 : public:
170 : explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
171 77222 : : FrameScope(masm, StackFrame::NONE) { }
172 : };
173 :
174 :
175 : class NoCurrentFrameScope {
176 : public:
177 : explicit NoCurrentFrameScope(MacroAssembler* masm)
178 20225 : : masm_(masm), saved_(masm->has_frame()) {
179 : masm->set_has_frame(false);
180 : }
181 :
182 : ~NoCurrentFrameScope() {
183 : masm_->set_has_frame(saved_);
184 : }
185 :
186 : private:
187 : MacroAssembler* masm_;
188 : bool saved_;
189 : };
190 :
191 : // Wrapper class for passing expected and actual parameter counts as
192 : // either registers or immediate values. Used to make sure that the
193 : // caller provides exactly the expected number of parameters to the
194 : // callee.
195 : class ParameterCount BASE_EMBEDDED {
196 : public:
197 1302 : explicit ParameterCount(Register reg) : reg_(reg), immediate_(0) {}
198 : explicit ParameterCount(int imm) : reg_(no_reg), immediate_(imm) {}
199 :
200 : bool is_reg() const { return reg_.is_valid(); }
201 : bool is_immediate() const { return !is_reg(); }
202 :
203 : Register reg() const {
204 : DCHECK(is_reg());
205 : return reg_;
206 : }
207 : int immediate() const {
208 : DCHECK(is_immediate());
209 : return immediate_;
210 : }
211 :
212 : private:
213 : const Register reg_;
214 : const int immediate_;
215 :
216 : DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
217 : };
218 :
219 : } // namespace internal
220 : } // namespace v8
221 :
222 : #endif // V8_MACRO_ASSEMBLER_H_
|