• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "src/arm64/macro-assembler-arm64-inl.h"
45 #elif V8_TARGET_ARCH_ARM
46 #include "src/arm/constants-arm.h"
47 #include "src/arm/macro-assembler-arm.h"
48 #elif V8_TARGET_ARCH_PPC
49 #include "src/ppc/constants-ppc.h"
50 #include "src/ppc/macro-assembler-ppc.h"
51 #elif V8_TARGET_ARCH_MIPS
52 #include "src/mips/constants-mips.h"
53 #include "src/mips/macro-assembler-mips.h"
54 #elif V8_TARGET_ARCH_MIPS64
55 #include "src/mips64/constants-mips64.h"
56 #include "src/mips64/macro-assembler-mips64.h"
57 #elif V8_TARGET_ARCH_S390
58 #include "src/s390/constants-s390.h"
59 #include "src/s390/macro-assembler-s390.h"
60 #elif V8_TARGET_ARCH_X87
61 #include "src/x87/macro-assembler-x87.h"
62 #else
63 #error Unsupported target architecture.
64 #endif
65 
66 namespace v8 {
67 namespace internal {
68 
69 class FrameScope {
70  public:
FrameScope(MacroAssembler * masm,StackFrame::Type type)71   explicit FrameScope(MacroAssembler* masm, StackFrame::Type type)
72       : masm_(masm), type_(type), old_has_frame_(masm->has_frame()) {
73     masm->set_has_frame(true);
74     if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) {
75       masm->EnterFrame(type);
76     }
77   }
78 
~FrameScope()79   ~FrameScope() {
80     if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
81       masm_->LeaveFrame(type_);
82     }
83     masm_->set_has_frame(old_has_frame_);
84   }
85 
86   // Normally we generate the leave-frame code when this object goes
87   // out of scope.  Sometimes we may need to generate the code somewhere else
88   // in addition.  Calling this will achieve that, but the object stays in
89   // scope, the MacroAssembler is still marked as being in a frame scope, and
90   // the code will be generated again when it goes out of scope.
GenerateLeaveFrame()91   void GenerateLeaveFrame() {
92     DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
93     masm_->LeaveFrame(type_);
94   }
95 
96  private:
97   MacroAssembler* masm_;
98   StackFrame::Type type_;
99   bool old_has_frame_;
100 };
101 
102 class FrameAndConstantPoolScope {
103  public:
FrameAndConstantPoolScope(MacroAssembler * masm,StackFrame::Type type)104   FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
105       : masm_(masm),
106         type_(type),
107         old_has_frame_(masm->has_frame()),
108         old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
109                                      masm->is_constant_pool_available()) {
110     masm->set_has_frame(true);
111     if (FLAG_enable_embedded_constant_pool) {
112       masm->set_constant_pool_available(true);
113     }
114     if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
115       masm->EnterFrame(type, !old_constant_pool_available_);
116     }
117   }
118 
~FrameAndConstantPoolScope()119   ~FrameAndConstantPoolScope() {
120     masm_->LeaveFrame(type_);
121     masm_->set_has_frame(old_has_frame_);
122     if (FLAG_enable_embedded_constant_pool) {
123       masm_->set_constant_pool_available(old_constant_pool_available_);
124     }
125   }
126 
127   // Normally we generate the leave-frame code when this object goes
128   // out of scope.  Sometimes we may need to generate the code somewhere else
129   // in addition.  Calling this will achieve that, but the object stays in
130   // scope, the MacroAssembler is still marked as being in a frame scope, and
131   // the code will be generated again when it goes out of scope.
GenerateLeaveFrame()132   void GenerateLeaveFrame() {
133     DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
134     masm_->LeaveFrame(type_);
135   }
136 
137  private:
138   MacroAssembler* masm_;
139   StackFrame::Type type_;
140   bool old_has_frame_;
141   bool old_constant_pool_available_;
142 
143   DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
144 };
145 
146 // Class for scoping the the unavailability of constant pool access.
147 class ConstantPoolUnavailableScope {
148  public:
ConstantPoolUnavailableScope(MacroAssembler * masm)149   explicit ConstantPoolUnavailableScope(MacroAssembler* masm)
150       : masm_(masm),
151         old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
152                                      masm->is_constant_pool_available()) {
153     if (FLAG_enable_embedded_constant_pool) {
154       masm_->set_constant_pool_available(false);
155     }
156   }
~ConstantPoolUnavailableScope()157   ~ConstantPoolUnavailableScope() {
158     if (FLAG_enable_embedded_constant_pool) {
159       masm_->set_constant_pool_available(old_constant_pool_available_);
160     }
161   }
162 
163  private:
164   MacroAssembler* masm_;
165   int old_constant_pool_available_;
166 
167   DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
168 };
169 
170 
171 class AllowExternalCallThatCantCauseGC: public FrameScope {
172  public:
AllowExternalCallThatCantCauseGC(MacroAssembler * masm)173   explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
174       : FrameScope(masm, StackFrame::NONE) { }
175 };
176 
177 
178 class NoCurrentFrameScope {
179  public:
NoCurrentFrameScope(MacroAssembler * masm)180   explicit NoCurrentFrameScope(MacroAssembler* masm)
181       : masm_(masm), saved_(masm->has_frame()) {
182     masm->set_has_frame(false);
183   }
184 
~NoCurrentFrameScope()185   ~NoCurrentFrameScope() {
186     masm_->set_has_frame(saved_);
187   }
188 
189  private:
190   MacroAssembler* masm_;
191   bool saved_;
192 };
193 
194 
195 // Support for "structured" code comments.
196 #ifdef DEBUG
197 
198 class Comment {
199  public:
200   Comment(MacroAssembler* masm, const char* msg);
201   ~Comment();
202 
203  private:
204   MacroAssembler* masm_;
205   const char* msg_;
206 };
207 
208 #else
209 
210 class Comment {
211  public:
Comment(MacroAssembler *,const char *)212   Comment(MacroAssembler*, const char*)  {}
213 };
214 
215 #endif  // DEBUG
216 
217 
218 // Wrapper class for passing expected and actual parameter counts as
219 // either registers or immediate values. Used to make sure that the
220 // caller provides exactly the expected number of parameters to the
221 // callee.
222 class ParameterCount BASE_EMBEDDED {
223  public:
ParameterCount(Register reg)224   explicit ParameterCount(Register reg) : reg_(reg), immediate_(0) {}
ParameterCount(int imm)225   explicit ParameterCount(int imm) : reg_(no_reg), immediate_(imm) {}
226 
is_reg()227   bool is_reg() const { return !reg_.is(no_reg); }
is_immediate()228   bool is_immediate() const { return !is_reg(); }
229 
reg()230   Register reg() const {
231     DCHECK(is_reg());
232     return reg_;
233   }
immediate()234   int immediate() const {
235     DCHECK(is_immediate());
236     return immediate_;
237   }
238 
239  private:
240   const Register reg_;
241   const int immediate_;
242 
243   DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
244 };
245 
246 
247 class AllocationUtils {
248  public:
GetAllocationTopReference(Isolate * isolate,AllocationFlags flags)249   static ExternalReference GetAllocationTopReference(
250       Isolate* isolate, AllocationFlags flags) {
251     if ((flags & PRETENURE) != 0) {
252       return ExternalReference::old_space_allocation_top_address(isolate);
253     }
254     return ExternalReference::new_space_allocation_top_address(isolate);
255   }
256 
257 
GetAllocationLimitReference(Isolate * isolate,AllocationFlags flags)258   static ExternalReference GetAllocationLimitReference(
259       Isolate* isolate, AllocationFlags flags) {
260     if ((flags & PRETENURE) != 0) {
261       return ExternalReference::old_space_allocation_limit_address(isolate);
262     }
263     return ExternalReference::new_space_allocation_limit_address(isolate);
264   }
265 };
266 
267 
268 }  // namespace internal
269 }  // namespace v8
270 
271 #endif  // V8_MACRO_ASSEMBLER_H_
272