Line data Source code
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/frames.h"
9 : #include "src/heap/heap.h"
10 : #include "src/turbo-assembler.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 : // This is the only place allowed to include the platform-specific headers.
36 : #define INCLUDED_FROM_MACRO_ASSEMBLER_H
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 : #elif V8_TARGET_ARCH_ARM
45 : #include "src/arm/constants-arm.h"
46 : #include "src/arm/macro-assembler-arm.h"
47 : #elif V8_TARGET_ARCH_PPC
48 : #include "src/ppc/constants-ppc.h"
49 : #include "src/ppc/macro-assembler-ppc.h"
50 : #elif V8_TARGET_ARCH_MIPS
51 : #include "src/mips/constants-mips.h"
52 : #include "src/mips/macro-assembler-mips.h"
53 : #elif V8_TARGET_ARCH_MIPS64
54 : #include "src/mips64/constants-mips64.h"
55 : #include "src/mips64/macro-assembler-mips64.h"
56 : #elif V8_TARGET_ARCH_S390
57 : #include "src/s390/constants-s390.h"
58 : #include "src/s390/macro-assembler-s390.h"
59 : #else
60 : #error Unsupported target architecture.
61 : #endif
62 : #undef INCLUDED_FROM_MACRO_ASSEMBLER_H
63 :
64 : namespace v8 {
65 : namespace internal {
66 :
67 : // Simulators only support C calls with up to kMaxCParameters parameters.
68 : static constexpr int kMaxCParameters = 9;
69 :
70 : class FrameScope {
71 : public:
72 : explicit FrameScope(TurboAssembler* tasm, StackFrame::Type type)
73 2901301 : : tasm_(tasm), type_(type), old_has_frame_(tasm->has_frame()) {
74 : tasm->set_has_frame(true);
75 336 : if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) {
76 1680 : tasm->EnterFrame(type);
77 : }
78 : }
79 :
80 5969868 : ~FrameScope() {
81 2984934 : if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
82 1680 : tasm_->LeaveFrame(type_);
83 : }
84 2984934 : tasm_->set_has_frame(old_has_frame_);
85 2984934 : }
86 :
87 : // Normally we generate the leave-frame code when this object goes
88 : // out of scope. Sometimes we may need to generate the code somewhere else
89 : // in addition. Calling this will achieve that, but the object stays in
90 : // scope, the MacroAssembler is still marked as being in a frame scope, and
91 : // the code will be generated again when it goes out of scope.
92 : void GenerateLeaveFrame() {
93 : DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
94 56 : tasm_->LeaveFrame(type_);
95 : }
96 :
97 : private:
98 : TurboAssembler* tasm_;
99 : StackFrame::Type type_;
100 : bool old_has_frame_;
101 : };
102 :
103 : class FrameAndConstantPoolScope {
104 : public:
105 : FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
106 : : masm_(masm),
107 : type_(type),
108 : old_has_frame_(masm->has_frame()),
109 : old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
110 : masm->is_constant_pool_available()) {
111 : masm->set_has_frame(true);
112 : if (FLAG_enable_embedded_constant_pool) {
113 : masm->set_constant_pool_available(true);
114 : }
115 : if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
116 : masm->EnterFrame(type, !old_constant_pool_available_);
117 : }
118 : }
119 :
120 : ~FrameAndConstantPoolScope() {
121 : masm_->LeaveFrame(type_);
122 : masm_->set_has_frame(old_has_frame_);
123 : if (FLAG_enable_embedded_constant_pool) {
124 : masm_->set_constant_pool_available(old_constant_pool_available_);
125 : }
126 : }
127 :
128 : // Normally we generate the leave-frame code when this object goes
129 : // out of scope. Sometimes we may need to generate the code somewhere else
130 : // in addition. Calling this will achieve that, but the object stays in
131 : // scope, the MacroAssembler is still marked as being in a frame scope, and
132 : // the code will be generated again when it goes out of scope.
133 : void GenerateLeaveFrame() {
134 : DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
135 : masm_->LeaveFrame(type_);
136 : }
137 :
138 : private:
139 : MacroAssembler* masm_;
140 : StackFrame::Type type_;
141 : bool old_has_frame_;
142 : bool old_constant_pool_available_;
143 :
144 : DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
145 : };
146 :
147 : // Class for scoping the the unavailability of constant pool access.
148 : class ConstantPoolUnavailableScope {
149 : public:
150 : explicit ConstantPoolUnavailableScope(Assembler* assembler)
151 : : assembler_(assembler),
152 : old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
153 : assembler->is_constant_pool_available()) {
154 : if (FLAG_enable_embedded_constant_pool) {
155 : assembler->set_constant_pool_available(false);
156 : }
157 : }
158 : ~ConstantPoolUnavailableScope() {
159 : if (FLAG_enable_embedded_constant_pool) {
160 : assembler_->set_constant_pool_available(old_constant_pool_available_);
161 : }
162 : }
163 :
164 : private:
165 : Assembler* assembler_;
166 : int old_constant_pool_available_;
167 :
168 : DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
169 : };
170 :
171 :
172 89723 : class AllowExternalCallThatCantCauseGC: public FrameScope {
173 : public:
174 : explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
175 : : FrameScope(masm, StackFrame::NONE) { }
176 : };
177 :
178 : // Prevent the use of the RootArray during the lifetime of this
179 : // scope object.
180 : class NoRootArrayScope {
181 : public:
182 : explicit NoRootArrayScope(TurboAssembler* masm)
183 82173 : : masm_(masm), old_value_(masm->root_array_available()) {
184 : masm->set_root_array_available(false);
185 : }
186 :
187 164346 : ~NoRootArrayScope() { masm_->set_root_array_available(old_value_); }
188 :
189 : private:
190 : TurboAssembler* masm_;
191 : bool old_value_;
192 : };
193 :
194 : // Wrapper class for passing expected and actual parameter counts as
195 : // either registers or immediate values. Used to make sure that the
196 : // caller provides exactly the expected number of parameters to the
197 : // callee.
198 : class ParameterCount {
199 : public:
200 1736 : explicit ParameterCount(Register reg) : reg_(reg), immediate_(0) {}
201 : explicit ParameterCount(uint16_t imm) : reg_(no_reg), immediate_(imm) {}
202 :
203 : bool is_reg() const { return reg_.is_valid(); }
204 : bool is_immediate() const { return !is_reg(); }
205 :
206 : Register reg() const {
207 : DCHECK(is_reg());
208 : return reg_;
209 : }
210 : uint16_t immediate() const {
211 : DCHECK(is_immediate());
212 : return immediate_;
213 : }
214 :
215 : private:
216 : const Register reg_;
217 : const uint16_t immediate_;
218 :
219 : DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
220 : };
221 :
222 : } // namespace internal
223 : } // namespace v8
224 :
225 : #endif // V8_MACRO_ASSEMBLER_H_
|