blob: fd2aa7c31459fe493ffaf27182715992b46e5715 [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,
22 // Return the pointer to the allocated already tagged as a heap object.
23 TAG_OBJECT = 1 << 0,
24 // The content of the result register already contains the allocation top in
25 // new space.
26 RESULT_CONTAINS_TOP = 1 << 1,
27 // Specify that the requested size of the space to allocate is specified in
28 // words instead of bytes.
29 SIZE_IN_WORDS = 1 << 2,
30 // Align the allocation to a multiple of kDoubleSize
31 DOUBLE_ALIGNMENT = 1 << 3,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 // Directly allocate in old space
33 PRETENURE = 1 << 4,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034};
35
36
Steve Blocka7e24c12009-10-30 11:49:00 +000037#if V8_TARGET_ARCH_IA32
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038#include "src/ia32/assembler-ia32.h"
39#include "src/ia32/assembler-ia32-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040#include "src/ia32/macro-assembler-ia32.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#elif V8_TARGET_ARCH_X64
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042#include "src/x64/assembler-x64.h"
43#include "src/x64/assembler-x64-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044#include "src/x64/macro-assembler-x64.h"
45#elif V8_TARGET_ARCH_ARM64
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046#include "src/arm64/assembler-arm64.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047#include "src/arm64/assembler-arm64-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048#include "src/arm64/constants-arm64.h"
49#include "src/arm64/macro-assembler-arm64.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050#include "src/arm64/macro-assembler-arm64-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000051#elif V8_TARGET_ARCH_ARM
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052#include "src/arm/assembler-arm.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053#include "src/arm/assembler-arm-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054#include "src/arm/constants-arm.h"
55#include "src/arm/macro-assembler-arm.h"
56#elif V8_TARGET_ARCH_PPC
57#include "src/ppc/assembler-ppc.h"
58#include "src/ppc/assembler-ppc-inl.h"
59#include "src/ppc/constants-ppc.h"
60#include "src/ppc/macro-assembler-ppc.h"
Andrei Popescu31002712010-02-23 13:46:05 +000061#elif V8_TARGET_ARCH_MIPS
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062#include "src/mips/assembler-mips.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063#include "src/mips/assembler-mips-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064#include "src/mips/constants-mips.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065#include "src/mips/macro-assembler-mips.h"
66#elif V8_TARGET_ARCH_MIPS64
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067#include "src/mips64/assembler-mips64.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068#include "src/mips64/assembler-mips64-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069#include "src/mips64/constants-mips64.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070#include "src/mips64/macro-assembler-mips64.h"
71#elif V8_TARGET_ARCH_X87
Ben Murdochb8a8cc12014-11-26 15:28:44 +000072#include "src/x87/assembler-x87.h"
73#include "src/x87/assembler-x87-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074#include "src/x87/macro-assembler-x87.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000075#else
76#error Unsupported target architecture.
77#endif
78
Kristian Monsen80d68ea2010-09-08 11:05:35 +010079namespace v8 {
80namespace internal {
81
Ben Murdoch3ef787d2012-04-12 10:51:47 +010082class FrameScope {
83 public:
84 explicit FrameScope(MacroAssembler* masm, StackFrame::Type type)
85 : masm_(masm), type_(type), old_has_frame_(masm->has_frame()) {
86 masm->set_has_frame(true);
87 if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) {
88 masm->EnterFrame(type);
89 }
90 }
91
92 ~FrameScope() {
93 if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
94 masm_->LeaveFrame(type_);
95 }
96 masm_->set_has_frame(old_has_frame_);
97 }
98
99 // Normally we generate the leave-frame code when this object goes
100 // out of scope. Sometimes we may need to generate the code somewhere else
101 // in addition. Calling this will achieve that, but the object stays in
102 // scope, the MacroAssembler is still marked as being in a frame scope, and
103 // the code will be generated again when it goes out of scope.
104 void GenerateLeaveFrame() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100106 masm_->LeaveFrame(type_);
107 }
108
109 private:
110 MacroAssembler* masm_;
111 StackFrame::Type type_;
112 bool old_has_frame_;
113};
114
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115class FrameAndConstantPoolScope {
116 public:
117 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
118 : masm_(masm),
119 type_(type),
120 old_has_frame_(masm->has_frame()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121 old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
122 masm->is_constant_pool_available()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123 masm->set_has_frame(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 if (FLAG_enable_embedded_constant_pool) {
125 masm->set_constant_pool_available(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126 }
127 if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
128 masm->EnterFrame(type, !old_constant_pool_available_);
129 }
130 }
131
132 ~FrameAndConstantPoolScope() {
133 masm_->LeaveFrame(type_);
134 masm_->set_has_frame(old_has_frame_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135 if (FLAG_enable_embedded_constant_pool) {
136 masm_->set_constant_pool_available(old_constant_pool_available_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400137 }
138 }
139
140 // Normally we generate the leave-frame code when this object goes
141 // out of scope. Sometimes we may need to generate the code somewhere else
142 // in addition. Calling this will achieve that, but the object stays in
143 // scope, the MacroAssembler is still marked as being in a frame scope, and
144 // the code will be generated again when it goes out of scope.
145 void GenerateLeaveFrame() {
146 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
147 masm_->LeaveFrame(type_);
148 }
149
150 private:
151 MacroAssembler* masm_;
152 StackFrame::Type type_;
153 bool old_has_frame_;
154 bool old_constant_pool_available_;
155
156 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
157};
158
159// Class for scoping the the unavailability of constant pool access.
160class ConstantPoolUnavailableScope {
161 public:
162 explicit ConstantPoolUnavailableScope(MacroAssembler* masm)
163 : masm_(masm),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
165 masm->is_constant_pool_available()) {
166 if (FLAG_enable_embedded_constant_pool) {
167 masm_->set_constant_pool_available(false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400168 }
169 }
170 ~ConstantPoolUnavailableScope() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 if (FLAG_enable_embedded_constant_pool) {
172 masm_->set_constant_pool_available(old_constant_pool_available_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173 }
174 }
175
176 private:
177 MacroAssembler* masm_;
178 int old_constant_pool_available_;
179
180 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
181};
182
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100183
184class AllowExternalCallThatCantCauseGC: public FrameScope {
185 public:
186 explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
187 : FrameScope(masm, StackFrame::NONE) { }
188};
189
190
191class NoCurrentFrameScope {
192 public:
193 explicit NoCurrentFrameScope(MacroAssembler* masm)
194 : masm_(masm), saved_(masm->has_frame()) {
195 masm->set_has_frame(false);
196 }
197
198 ~NoCurrentFrameScope() {
199 masm_->set_has_frame(saved_);
200 }
201
202 private:
203 MacroAssembler* masm_;
204 bool saved_;
205};
206
207
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100208// Support for "structured" code comments.
209#ifdef DEBUG
210
211class Comment {
212 public:
213 Comment(MacroAssembler* masm, const char* msg);
214 ~Comment();
215
216 private:
217 MacroAssembler* masm_;
218 const char* msg_;
219};
220
221#else
222
223class Comment {
224 public:
225 Comment(MacroAssembler*, const char*) {}
226};
227
228#endif // DEBUG
229
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231// Wrapper class for passing expected and actual parameter counts as
232// either registers or immediate values. Used to make sure that the
233// caller provides exactly the expected number of parameters to the
234// callee.
235class ParameterCount BASE_EMBEDDED {
236 public:
237 explicit ParameterCount(Register reg) : reg_(reg), immediate_(0) {}
238 explicit ParameterCount(int imm) : reg_(no_reg), immediate_(imm) {}
239
240 bool is_reg() const { return !reg_.is(no_reg); }
241 bool is_immediate() const { return !is_reg(); }
242
243 Register reg() const {
244 DCHECK(is_reg());
245 return reg_;
246 }
247 int immediate() const {
248 DCHECK(is_immediate());
249 return immediate_;
250 }
251
252 private:
253 const Register reg_;
254 const int immediate_;
255
256 DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
257};
258
259
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260class AllocationUtils {
261 public:
262 static ExternalReference GetAllocationTopReference(
263 Isolate* isolate, AllocationFlags flags) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264 if ((flags & PRETENURE) != 0) {
265 return ExternalReference::old_space_allocation_top_address(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 }
267 return ExternalReference::new_space_allocation_top_address(isolate);
268 }
269
270
271 static ExternalReference GetAllocationLimitReference(
272 Isolate* isolate, AllocationFlags flags) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000273 if ((flags & PRETENURE) != 0) {
274 return ExternalReference::old_space_allocation_limit_address(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 }
276 return ExternalReference::new_space_allocation_limit_address(isolate);
277 }
278};
279
280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281} // namespace internal
282} // namespace v8
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100283
Steve Blocka7e24c12009-10-30 11:49:00 +0000284#endif // V8_MACRO_ASSEMBLER_H_