blob: b6830450e7f971e2af6ee4fb3f0300ac48b05d34 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_MACRO_ASSEMBLER_H_
6#define V8_MACRO_ASSEMBLER_H_
7
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/assembler.h"
9
Steve Blocka7e24c12009-10-30 11:49:00 +000010
11// Helper types to make boolean flag easier to read at call-site.
12enum InvokeFlag {
13 CALL_FUNCTION,
14 JUMP_FUNCTION
15};
16
17
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018// Flags used for the AllocateInNewSpace functions.
19enum AllocationFlags {
20 // No special flags.
21 NO_ALLOCATION_FLAGS = 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022 // The content of the result register already contains the allocation top in
23 // new space.
Ben Murdochc5610432016-08-08 18:44:38 +010024 RESULT_CONTAINS_TOP = 1 << 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025 // Specify that the requested size of the space to allocate is specified in
26 // words instead of bytes.
Ben Murdochc5610432016-08-08 18:44:38 +010027 SIZE_IN_WORDS = 1 << 1,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028 // Align the allocation to a multiple of kDoubleSize
Ben Murdochc5610432016-08-08 18:44:38 +010029 DOUBLE_ALIGNMENT = 1 << 2,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030 // Directly allocate in old space
Ben Murdochc5610432016-08-08 18:44:38 +010031 PRETENURE = 1 << 3,
32 // Allocation folding dominator
33 ALLOCATION_FOLDING_DOMINATOR = 1 << 4,
34 // Folded allocation
35 ALLOCATION_FOLDED = 1 << 5
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036};
37
Steve Blocka7e24c12009-10-30 11:49:00 +000038#if V8_TARGET_ARCH_IA32
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039#include "src/ia32/assembler-ia32.h"
40#include "src/ia32/assembler-ia32-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041#include "src/ia32/macro-assembler-ia32.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042#elif V8_TARGET_ARCH_X64
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043#include "src/x64/assembler-x64.h"
44#include "src/x64/assembler-x64-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045#include "src/x64/macro-assembler-x64.h"
46#elif V8_TARGET_ARCH_ARM64
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047#include "src/arm64/assembler-arm64.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048#include "src/arm64/assembler-arm64-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049#include "src/arm64/constants-arm64.h"
50#include "src/arm64/macro-assembler-arm64.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051#include "src/arm64/macro-assembler-arm64-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000052#elif V8_TARGET_ARCH_ARM
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053#include "src/arm/assembler-arm.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054#include "src/arm/assembler-arm-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055#include "src/arm/constants-arm.h"
56#include "src/arm/macro-assembler-arm.h"
57#elif V8_TARGET_ARCH_PPC
58#include "src/ppc/assembler-ppc.h"
59#include "src/ppc/assembler-ppc-inl.h"
60#include "src/ppc/constants-ppc.h"
61#include "src/ppc/macro-assembler-ppc.h"
Andrei Popescu31002712010-02-23 13:46:05 +000062#elif V8_TARGET_ARCH_MIPS
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063#include "src/mips/assembler-mips.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000064#include "src/mips/assembler-mips-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065#include "src/mips/constants-mips.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066#include "src/mips/macro-assembler-mips.h"
67#elif V8_TARGET_ARCH_MIPS64
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068#include "src/mips64/assembler-mips64.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069#include "src/mips64/assembler-mips64-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070#include "src/mips64/constants-mips64.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071#include "src/mips64/macro-assembler-mips64.h"
Ben Murdochda12d292016-06-02 14:46:10 +010072#elif V8_TARGET_ARCH_S390
73#include "src/s390/assembler-s390.h"
74#include "src/s390/assembler-s390-inl.h"
75#include "src/s390/constants-s390.h"
76#include "src/s390/macro-assembler-s390.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077#elif V8_TARGET_ARCH_X87
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078#include "src/x87/assembler-x87.h"
79#include "src/x87/assembler-x87-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080#include "src/x87/macro-assembler-x87.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000081#else
82#error Unsupported target architecture.
83#endif
84
Kristian Monsen80d68ea2010-09-08 11:05:35 +010085namespace v8 {
86namespace internal {
87
Ben Murdoch3ef787d2012-04-12 10:51:47 +010088class FrameScope {
89 public:
90 explicit FrameScope(MacroAssembler* masm, StackFrame::Type type)
91 : masm_(masm), type_(type), old_has_frame_(masm->has_frame()) {
92 masm->set_has_frame(true);
93 if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) {
94 masm->EnterFrame(type);
95 }
96 }
97
98 ~FrameScope() {
99 if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
100 masm_->LeaveFrame(type_);
101 }
102 masm_->set_has_frame(old_has_frame_);
103 }
104
105 // Normally we generate the leave-frame code when this object goes
106 // out of scope. Sometimes we may need to generate the code somewhere else
107 // in addition. Calling this will achieve that, but the object stays in
108 // scope, the MacroAssembler is still marked as being in a frame scope, and
109 // the code will be generated again when it goes out of scope.
110 void GenerateLeaveFrame() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100112 masm_->LeaveFrame(type_);
113 }
114
115 private:
116 MacroAssembler* masm_;
117 StackFrame::Type type_;
118 bool old_has_frame_;
119};
120
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400121class FrameAndConstantPoolScope {
122 public:
123 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
124 : masm_(masm),
125 type_(type),
126 old_has_frame_(masm->has_frame()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
128 masm->is_constant_pool_available()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400129 masm->set_has_frame(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130 if (FLAG_enable_embedded_constant_pool) {
131 masm->set_constant_pool_available(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400132 }
133 if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
134 masm->EnterFrame(type, !old_constant_pool_available_);
135 }
136 }
137
138 ~FrameAndConstantPoolScope() {
139 masm_->LeaveFrame(type_);
140 masm_->set_has_frame(old_has_frame_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 if (FLAG_enable_embedded_constant_pool) {
142 masm_->set_constant_pool_available(old_constant_pool_available_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400143 }
144 }
145
146 // Normally we generate the leave-frame code when this object goes
147 // out of scope. Sometimes we may need to generate the code somewhere else
148 // in addition. Calling this will achieve that, but the object stays in
149 // scope, the MacroAssembler is still marked as being in a frame scope, and
150 // the code will be generated again when it goes out of scope.
151 void GenerateLeaveFrame() {
152 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
153 masm_->LeaveFrame(type_);
154 }
155
156 private:
157 MacroAssembler* masm_;
158 StackFrame::Type type_;
159 bool old_has_frame_;
160 bool old_constant_pool_available_;
161
162 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
163};
164
165// Class for scoping the the unavailability of constant pool access.
166class ConstantPoolUnavailableScope {
167 public:
168 explicit ConstantPoolUnavailableScope(MacroAssembler* masm)
169 : masm_(masm),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
171 masm->is_constant_pool_available()) {
172 if (FLAG_enable_embedded_constant_pool) {
173 masm_->set_constant_pool_available(false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400174 }
175 }
176 ~ConstantPoolUnavailableScope() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177 if (FLAG_enable_embedded_constant_pool) {
178 masm_->set_constant_pool_available(old_constant_pool_available_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400179 }
180 }
181
182 private:
183 MacroAssembler* masm_;
184 int old_constant_pool_available_;
185
186 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
187};
188
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100189
190class AllowExternalCallThatCantCauseGC: public FrameScope {
191 public:
192 explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
193 : FrameScope(masm, StackFrame::NONE) { }
194};
195
196
197class NoCurrentFrameScope {
198 public:
199 explicit NoCurrentFrameScope(MacroAssembler* masm)
200 : masm_(masm), saved_(masm->has_frame()) {
201 masm->set_has_frame(false);
202 }
203
204 ~NoCurrentFrameScope() {
205 masm_->set_has_frame(saved_);
206 }
207
208 private:
209 MacroAssembler* masm_;
210 bool saved_;
211};
212
213
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100214// Support for "structured" code comments.
215#ifdef DEBUG
216
217class Comment {
218 public:
219 Comment(MacroAssembler* masm, const char* msg);
220 ~Comment();
221
222 private:
223 MacroAssembler* masm_;
224 const char* msg_;
225};
226
227#else
228
229class Comment {
230 public:
231 Comment(MacroAssembler*, const char*) {}
232};
233
234#endif // DEBUG
235
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237// Wrapper class for passing expected and actual parameter counts as
238// either registers or immediate values. Used to make sure that the
239// caller provides exactly the expected number of parameters to the
240// callee.
241class ParameterCount BASE_EMBEDDED {
242 public:
243 explicit ParameterCount(Register reg) : reg_(reg), immediate_(0) {}
244 explicit ParameterCount(int imm) : reg_(no_reg), immediate_(imm) {}
245
246 bool is_reg() const { return !reg_.is(no_reg); }
247 bool is_immediate() const { return !is_reg(); }
248
249 Register reg() const {
250 DCHECK(is_reg());
251 return reg_;
252 }
253 int immediate() const {
254 DCHECK(is_immediate());
255 return immediate_;
256 }
257
258 private:
259 const Register reg_;
260 const int immediate_;
261
262 DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
263};
264
265
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266class AllocationUtils {
267 public:
268 static ExternalReference GetAllocationTopReference(
269 Isolate* isolate, AllocationFlags flags) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270 if ((flags & PRETENURE) != 0) {
271 return ExternalReference::old_space_allocation_top_address(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 }
273 return ExternalReference::new_space_allocation_top_address(isolate);
274 }
275
276
277 static ExternalReference GetAllocationLimitReference(
278 Isolate* isolate, AllocationFlags flags) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 if ((flags & PRETENURE) != 0) {
280 return ExternalReference::old_space_allocation_limit_address(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 }
282 return ExternalReference::new_space_allocation_limit_address(isolate);
283 }
284};
285
286
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287} // namespace internal
288} // namespace v8
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100289
Steve Blocka7e24c12009-10-30 11:49:00 +0000290#endif // V8_MACRO_ASSEMBLER_H_