• 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