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