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
9// Helper types to make boolean flag easier to read at call-site.
10enum InvokeFlag {
11  CALL_FUNCTION,
12  JUMP_FUNCTION
13};
14
15
16// 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
37// Invalid depth in prototype chain.
38const int kInvalidProtoDepth = -1;
39
40#if V8_TARGET_ARCH_IA32
41#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"
46#elif V8_TARGET_ARCH_X64
47#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"
60#elif V8_TARGET_ARCH_ARM
61#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
67#elif V8_TARGET_ARCH_MIPS
68#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"
87#else
88#error Unsupported target architecture.
89#endif
90
91namespace v8 {
92namespace internal {
93
94class 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() {
117    DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
118    masm_->LeaveFrame(type_);
119  }
120
121 private:
122  MacroAssembler* masm_;
123  StackFrame::Type type_;
124  bool old_has_frame_;
125};
126
127
128class AllowExternalCallThatCantCauseGC: public FrameScope {
129 public:
130  explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
131      : FrameScope(masm, StackFrame::NONE) { }
132};
133
134
135class NoCurrentFrameScope {
136 public:
137  explicit NoCurrentFrameScope(MacroAssembler* masm)
138      : masm_(masm), saved_(masm->has_frame()) {
139    masm->set_has_frame(false);
140  }
141
142  ~NoCurrentFrameScope() {
143    masm_->set_has_frame(saved_);
144  }
145
146 private:
147  MacroAssembler* masm_;
148  bool saved_;
149};
150
151
152// Support for "structured" code comments.
153#ifdef DEBUG
154
155class Comment {
156 public:
157  Comment(MacroAssembler* masm, const char* msg);
158  ~Comment();
159
160 private:
161  MacroAssembler* masm_;
162  const char* msg_;
163};
164
165#else
166
167class Comment {
168 public:
169  Comment(MacroAssembler*, const char*)  {}
170};
171
172#endif  // DEBUG
173
174
175class AllocationUtils {
176 public:
177  static ExternalReference GetAllocationTopReference(
178      Isolate* isolate, AllocationFlags flags) {
179    if ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) {
180      return ExternalReference::old_pointer_space_allocation_top_address(
181          isolate);
182    } else if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
183      return ExternalReference::old_data_space_allocation_top_address(isolate);
184    }
185    return ExternalReference::new_space_allocation_top_address(isolate);
186  }
187
188
189  static ExternalReference GetAllocationLimitReference(
190      Isolate* isolate, AllocationFlags flags) {
191    if ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) {
192      return ExternalReference::old_pointer_space_allocation_limit_address(
193          isolate);
194    } else if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
195      return ExternalReference::old_data_space_allocation_limit_address(
196          isolate);
197    }
198    return ExternalReference::new_space_allocation_limit_address(isolate);
199  }
200};
201
202
203} }  // namespace v8::internal
204
205#endif  // V8_MACRO_ASSEMBLER_H_
206