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-inl.h"
9 :
10 : // Helper types to make boolean flag easier to read at call-site.
11 : enum InvokeFlag {
12 : CALL_FUNCTION,
13 : JUMP_FUNCTION
14 : };
15 :
16 :
17 : // Flags used for the AllocateInNewSpace functions.
18 : enum AllocationFlags {
19 : // No special flags.
20 : NO_ALLOCATION_FLAGS = 0,
21 : // The content of the result register already contains the allocation top in
22 : // new space.
23 : RESULT_CONTAINS_TOP = 1 << 0,
24 : // Specify that the requested size of the space to allocate is specified in
25 : // words instead of bytes.
26 : SIZE_IN_WORDS = 1 << 1,
27 : // Align the allocation to a multiple of kDoubleSize
28 : DOUBLE_ALIGNMENT = 1 << 2,
29 : // Directly allocate in old space
30 : PRETENURE = 1 << 3,
31 : // Allocation folding dominator
32 : ALLOCATION_FOLDING_DOMINATOR = 1 << 4,
33 : // Folded allocation
34 : ALLOCATION_FOLDED = 1 << 5
35 : };
36 :
37 : #if V8_TARGET_ARCH_IA32
38 : #include "src/ia32/macro-assembler-ia32.h"
39 : #elif V8_TARGET_ARCH_X64
40 : #include "src/x64/macro-assembler-x64.h"
41 : #elif V8_TARGET_ARCH_ARM64
42 : #include "src/arm64/constants-arm64.h"
43 : #include "src/arm64/macro-assembler-arm64.h"
44 : #elif V8_TARGET_ARCH_ARM
45 : #include "src/arm/constants-arm.h"
46 : #include "src/arm/macro-assembler-arm.h"
47 : #elif V8_TARGET_ARCH_PPC
48 : #include "src/ppc/constants-ppc.h"
49 : #include "src/ppc/macro-assembler-ppc.h"
50 : #elif V8_TARGET_ARCH_MIPS
51 : #include "src/mips/constants-mips.h"
52 : #include "src/mips/macro-assembler-mips.h"
53 : #elif V8_TARGET_ARCH_MIPS64
54 : #include "src/mips64/constants-mips64.h"
55 : #include "src/mips64/macro-assembler-mips64.h"
56 : #elif V8_TARGET_ARCH_S390
57 : #include "src/s390/constants-s390.h"
58 : #include "src/s390/macro-assembler-s390.h"
59 : #elif V8_TARGET_ARCH_X87
60 : #include "src/x87/macro-assembler-x87.h"
61 : #else
62 : #error Unsupported target architecture.
63 : #endif
64 :
65 : namespace v8 {
66 : namespace internal {
67 :
68 : // Simulators only support C calls with up to kMaxCParameters parameters.
69 : static constexpr int kMaxCParameters = 9;
70 :
71 : class FrameScope {
72 : public:
73 5512240 : explicit FrameScope(MacroAssembler* masm, StackFrame::Type type)
74 5512240 : : masm_(masm), type_(type), old_has_frame_(masm->has_frame()) {
75 : masm->set_has_frame(true);
76 2756120 : if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) {
77 119962 : masm->EnterFrame(type);
78 : }
79 2756120 : }
80 :
81 2756120 : ~FrameScope() {
82 2756120 : if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
83 119962 : masm_->LeaveFrame(type_);
84 : }
85 2756120 : masm_->set_has_frame(old_has_frame_);
86 2756120 : }
87 :
88 : // Normally we generate the leave-frame code when this object goes
89 : // out of scope. Sometimes we may need to generate the code somewhere else
90 : // in addition. Calling this will achieve that, but the object stays in
91 : // scope, the MacroAssembler is still marked as being in a frame scope, and
92 : // the code will be generated again when it goes out of scope.
93 : void GenerateLeaveFrame() {
94 : DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
95 43 : masm_->LeaveFrame(type_);
96 : }
97 :
98 : private:
99 : MacroAssembler* masm_;
100 : StackFrame::Type type_;
101 : bool old_has_frame_;
102 : };
103 :
104 : class FrameAndConstantPoolScope {
105 : public:
106 : FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
107 : : masm_(masm),
108 : type_(type),
109 : old_has_frame_(masm->has_frame()),
110 : old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
111 : masm->is_constant_pool_available()) {
112 : masm->set_has_frame(true);
113 : if (FLAG_enable_embedded_constant_pool) {
114 : masm->set_constant_pool_available(true);
115 : }
116 : if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
117 : masm->EnterFrame(type, !old_constant_pool_available_);
118 : }
119 : }
120 :
121 : ~FrameAndConstantPoolScope() {
122 : masm_->LeaveFrame(type_);
123 : masm_->set_has_frame(old_has_frame_);
124 : if (FLAG_enable_embedded_constant_pool) {
125 : masm_->set_constant_pool_available(old_constant_pool_available_);
126 : }
127 : }
128 :
129 : // Normally we generate the leave-frame code when this object goes
130 : // out of scope. Sometimes we may need to generate the code somewhere else
131 : // in addition. Calling this will achieve that, but the object stays in
132 : // scope, the MacroAssembler is still marked as being in a frame scope, and
133 : // the code will be generated again when it goes out of scope.
134 : void GenerateLeaveFrame() {
135 : DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
136 : masm_->LeaveFrame(type_);
137 : }
138 :
139 : private:
140 : MacroAssembler* masm_;
141 : StackFrame::Type type_;
142 : bool old_has_frame_;
143 : bool old_constant_pool_available_;
144 :
145 : DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
146 : };
147 :
148 : // Class for scoping the the unavailability of constant pool access.
149 : class ConstantPoolUnavailableScope {
150 : public:
151 : explicit ConstantPoolUnavailableScope(Assembler* assembler)
152 : : assembler_(assembler),
153 : old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
154 : assembler->is_constant_pool_available()) {
155 : if (FLAG_enable_embedded_constant_pool) {
156 : assembler->set_constant_pool_available(false);
157 : }
158 : }
159 : ~ConstantPoolUnavailableScope() {
160 : if (FLAG_enable_embedded_constant_pool) {
161 : assembler_->set_constant_pool_available(old_constant_pool_available_);
162 : }
163 : }
164 :
165 : private:
166 : Assembler* assembler_;
167 : int old_constant_pool_available_;
168 :
169 : DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
170 : };
171 :
172 :
173 254606 : class AllowExternalCallThatCantCauseGC: public FrameScope {
174 : public:
175 : explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
176 254606 : : FrameScope(masm, StackFrame::NONE) { }
177 : };
178 :
179 :
180 : class NoCurrentFrameScope {
181 : public:
182 137654 : explicit NoCurrentFrameScope(MacroAssembler* masm)
183 : : masm_(masm), saved_(masm->has_frame()) {
184 : masm->set_has_frame(false);
185 : }
186 :
187 : ~NoCurrentFrameScope() {
188 : masm_->set_has_frame(saved_);
189 : }
190 :
191 : private:
192 : MacroAssembler* masm_;
193 : bool saved_;
194 : };
195 :
196 :
197 : // Support for "structured" code comments.
198 : #ifdef DEBUG
199 :
200 : class Comment {
201 : public:
202 : Comment(Assembler* assembler, const char* msg);
203 : ~Comment();
204 :
205 : private:
206 : Assembler* assembler_;
207 : const char* msg_;
208 : };
209 :
210 : #else
211 :
212 : class Comment {
213 : public:
214 : Comment(Assembler*, const char*) {}
215 : };
216 :
217 : #endif // DEBUG
218 :
219 :
220 : // Wrapper class for passing expected and actual parameter counts as
221 : // either registers or immediate values. Used to make sure that the
222 : // caller provides exactly the expected number of parameters to the
223 : // callee.
224 : class ParameterCount BASE_EMBEDDED {
225 : public:
226 6845 : explicit ParameterCount(Register reg) : reg_(reg), immediate_(0) {}
227 17807 : explicit ParameterCount(int imm) : reg_(no_reg), immediate_(imm) {}
228 :
229 : bool is_reg() const { return !reg_.is(no_reg); }
230 : bool is_immediate() const { return !is_reg(); }
231 :
232 : Register reg() const {
233 : DCHECK(is_reg());
234 : return reg_;
235 : }
236 : int immediate() const {
237 : DCHECK(is_immediate());
238 : return immediate_;
239 : }
240 :
241 : private:
242 : const Register reg_;
243 : const int immediate_;
244 :
245 : DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
246 : };
247 :
248 :
249 : class AllocationUtils {
250 : public:
251 105548 : static ExternalReference GetAllocationTopReference(
252 : Isolate* isolate, AllocationFlags flags) {
253 105548 : if ((flags & PRETENURE) != 0) {
254 104 : return ExternalReference::old_space_allocation_top_address(isolate);
255 : }
256 105444 : return ExternalReference::new_space_allocation_top_address(isolate);
257 : }
258 :
259 :
260 47953 : static ExternalReference GetAllocationLimitReference(
261 : Isolate* isolate, AllocationFlags flags) {
262 47953 : if ((flags & PRETENURE) != 0) {
263 8 : return ExternalReference::old_space_allocation_limit_address(isolate);
264 : }
265 47945 : return ExternalReference::new_space_allocation_limit_address(isolate);
266 : }
267 : };
268 :
269 :
270 : } // namespace internal
271 : } // namespace v8
272 :
273 : #endif // V8_MACRO_ASSEMBLER_H_
|