blob: 2501f806c9496671b45f3da4c178a85725a95ef7 [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
8
9// Helper types to make boolean flag easier to read at call-site.
10enum InvokeFlag {
11 CALL_FUNCTION,
12 JUMP_FUNCTION
13};
14
15
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016// Flags used for the AllocateInNewSpace functions.
17enum AllocationFlags {
18 // No special flags.
19 NO_ALLOCATION_FLAGS = 0,
20 // Return the pointer to the allocated already tagged as a heap object.
21 TAG_OBJECT = 1 << 0,
22 // The content of the result register already contains the allocation top in
23 // new space.
24 RESULT_CONTAINS_TOP = 1 << 1,
25 // Specify that the requested size of the space to allocate is specified in
26 // words instead of bytes.
27 SIZE_IN_WORDS = 1 << 2,
28 // Align the allocation to a multiple of kDoubleSize
29 DOUBLE_ALIGNMENT = 1 << 3,
30 // Directly allocate in old pointer space
31 PRETENURE_OLD_POINTER_SPACE = 1 << 4,
32 // Directly allocate in old data space
33 PRETENURE_OLD_DATA_SPACE = 1 << 5
34};
35
36
Andrei Popescu402d9372010-02-26 13:31:12 +000037// Invalid depth in prototype chain.
38const int kInvalidProtoDepth = -1;
Steve Blocka7e24c12009-10-30 11:49:00 +000039
40#if V8_TARGET_ARCH_IA32
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041#include "src/assembler.h"
42#include "src/ia32/assembler-ia32.h"
43#include "src/ia32/assembler-ia32-inl.h"
44#include "src/code.h" // NOLINT, must be after assembler_*.h
45#include "src/ia32/macro-assembler-ia32.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000046#elif V8_TARGET_ARCH_X64
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047#include "src/assembler.h"
48#include "src/x64/assembler-x64.h"
49#include "src/x64/assembler-x64-inl.h"
50#include "src/code.h" // NOLINT, must be after assembler_*.h
51#include "src/x64/macro-assembler-x64.h"
52#elif V8_TARGET_ARCH_ARM64
53#include "src/arm64/constants-arm64.h"
54#include "src/assembler.h"
55#include "src/arm64/assembler-arm64.h" // NOLINT
56#include "src/arm64/assembler-arm64-inl.h"
57#include "src/code.h" // NOLINT, must be after assembler_*.h
58#include "src/arm64/macro-assembler-arm64.h" // NOLINT
59#include "src/arm64/macro-assembler-arm64-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000060#elif V8_TARGET_ARCH_ARM
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061#include "src/arm/constants-arm.h"
62#include "src/assembler.h"
63#include "src/arm/assembler-arm.h" // NOLINT
64#include "src/arm/assembler-arm-inl.h"
65#include "src/code.h" // NOLINT, must be after assembler_*.h
66#include "src/arm/macro-assembler-arm.h" // NOLINT
Andrei Popescu31002712010-02-23 13:46:05 +000067#elif V8_TARGET_ARCH_MIPS
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068#include "src/mips/constants-mips.h"
69#include "src/assembler.h" // NOLINT
70#include "src/mips/assembler-mips.h" // NOLINT
71#include "src/mips/assembler-mips-inl.h"
72#include "src/code.h" // NOLINT, must be after assembler_*.h
73#include "src/mips/macro-assembler-mips.h"
74#elif V8_TARGET_ARCH_MIPS64
75#include "src/mips64/constants-mips64.h"
76#include "src/assembler.h" // NOLINT
77#include "src/mips64/assembler-mips64.h" // NOLINT
78#include "src/mips64/assembler-mips64-inl.h"
79#include "src/code.h" // NOLINT, must be after assembler_*.h
80#include "src/mips64/macro-assembler-mips64.h"
81#elif V8_TARGET_ARCH_X87
82#include "src/assembler.h"
83#include "src/x87/assembler-x87.h"
84#include "src/x87/assembler-x87-inl.h"
85#include "src/code.h" // NOLINT, must be after assembler_*.h
86#include "src/x87/macro-assembler-x87.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000087#else
88#error Unsupported target architecture.
89#endif
90
Kristian Monsen80d68ea2010-09-08 11:05:35 +010091namespace v8 {
92namespace internal {
93
Ben Murdoch3ef787d2012-04-12 10:51:47 +010094class FrameScope {
95 public:
96 explicit FrameScope(MacroAssembler* masm, StackFrame::Type type)
97 : masm_(masm), type_(type), old_has_frame_(masm->has_frame()) {
98 masm->set_has_frame(true);
99 if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) {
100 masm->EnterFrame(type);
101 }
102 }
103
104 ~FrameScope() {
105 if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
106 masm_->LeaveFrame(type_);
107 }
108 masm_->set_has_frame(old_has_frame_);
109 }
110
111 // Normally we generate the leave-frame code when this object goes
112 // out of scope. Sometimes we may need to generate the code somewhere else
113 // in addition. Calling this will achieve that, but the object stays in
114 // scope, the MacroAssembler is still marked as being in a frame scope, and
115 // the code will be generated again when it goes out of scope.
116 void GenerateLeaveFrame() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100118 masm_->LeaveFrame(type_);
119 }
120
121 private:
122 MacroAssembler* masm_;
123 StackFrame::Type type_;
124 bool old_has_frame_;
125};
126
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400127class FrameAndConstantPoolScope {
128 public:
129 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
130 : masm_(masm),
131 type_(type),
132 old_has_frame_(masm->has_frame()),
133 old_constant_pool_available_(FLAG_enable_ool_constant_pool &&
134 masm->is_ool_constant_pool_available()) {
135 masm->set_has_frame(true);
136 if (FLAG_enable_ool_constant_pool) {
137 masm->set_ool_constant_pool_available(true);
138 }
139 if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
140 masm->EnterFrame(type, !old_constant_pool_available_);
141 }
142 }
143
144 ~FrameAndConstantPoolScope() {
145 masm_->LeaveFrame(type_);
146 masm_->set_has_frame(old_has_frame_);
147 if (FLAG_enable_ool_constant_pool) {
148 masm_->set_ool_constant_pool_available(old_constant_pool_available_);
149 }
150 }
151
152 // Normally we generate the leave-frame code when this object goes
153 // out of scope. Sometimes we may need to generate the code somewhere else
154 // in addition. Calling this will achieve that, but the object stays in
155 // scope, the MacroAssembler is still marked as being in a frame scope, and
156 // the code will be generated again when it goes out of scope.
157 void GenerateLeaveFrame() {
158 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
159 masm_->LeaveFrame(type_);
160 }
161
162 private:
163 MacroAssembler* masm_;
164 StackFrame::Type type_;
165 bool old_has_frame_;
166 bool old_constant_pool_available_;
167
168 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
169};
170
171// Class for scoping the the unavailability of constant pool access.
172class ConstantPoolUnavailableScope {
173 public:
174 explicit ConstantPoolUnavailableScope(MacroAssembler* masm)
175 : masm_(masm),
176 old_constant_pool_available_(FLAG_enable_ool_constant_pool &&
177 masm->is_ool_constant_pool_available()) {
178 if (FLAG_enable_ool_constant_pool) {
179 masm_->set_ool_constant_pool_available(false);
180 }
181 }
182 ~ConstantPoolUnavailableScope() {
183 if (FLAG_enable_ool_constant_pool) {
184 masm_->set_ool_constant_pool_available(old_constant_pool_available_);
185 }
186 }
187
188 private:
189 MacroAssembler* masm_;
190 int old_constant_pool_available_;
191
192 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
193};
194
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100195
196class AllowExternalCallThatCantCauseGC: public FrameScope {
197 public:
198 explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
199 : FrameScope(masm, StackFrame::NONE) { }
200};
201
202
203class NoCurrentFrameScope {
204 public:
205 explicit NoCurrentFrameScope(MacroAssembler* masm)
206 : masm_(masm), saved_(masm->has_frame()) {
207 masm->set_has_frame(false);
208 }
209
210 ~NoCurrentFrameScope() {
211 masm_->set_has_frame(saved_);
212 }
213
214 private:
215 MacroAssembler* masm_;
216 bool saved_;
217};
218
219
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100220// Support for "structured" code comments.
221#ifdef DEBUG
222
223class Comment {
224 public:
225 Comment(MacroAssembler* masm, const char* msg);
226 ~Comment();
227
228 private:
229 MacroAssembler* masm_;
230 const char* msg_;
231};
232
233#else
234
235class Comment {
236 public:
237 Comment(MacroAssembler*, const char*) {}
238};
239
240#endif // DEBUG
241
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242
243class AllocationUtils {
244 public:
245 static ExternalReference GetAllocationTopReference(
246 Isolate* isolate, AllocationFlags flags) {
247 if ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) {
248 return ExternalReference::old_pointer_space_allocation_top_address(
249 isolate);
250 } else if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
251 return ExternalReference::old_data_space_allocation_top_address(isolate);
252 }
253 return ExternalReference::new_space_allocation_top_address(isolate);
254 }
255
256
257 static ExternalReference GetAllocationLimitReference(
258 Isolate* isolate, AllocationFlags flags) {
259 if ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) {
260 return ExternalReference::old_pointer_space_allocation_limit_address(
261 isolate);
262 } else if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
263 return ExternalReference::old_data_space_allocation_limit_address(
264 isolate);
265 }
266 return ExternalReference::new_space_allocation_limit_address(isolate);
267 }
268};
269
270
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100271} } // namespace v8::internal
272
Steve Blocka7e24c12009-10-30 11:49:00 +0000273#endif // V8_MACRO_ASSEMBLER_H_