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_CODEGEN_MACRO_ASSEMBLER_H_ 6 #define V8_CODEGEN_MACRO_ASSEMBLER_H_ 7 8 #include "src/codegen/turbo-assembler.h" 9 #include "src/execution/frames.h" 10 #include "src/heap/heap.h" 11 12 // Helper types to make boolean flag easier to read at call-site. 13 enum class InvokeType { kCall, kJump }; 14 15 // Flags used for the AllocateInNewSpace functions. 16 enum AllocationFlags { 17 // No special flags. 18 NO_ALLOCATION_FLAGS = 0, 19 // The content of the result register already contains the allocation top in 20 // new space. 21 RESULT_CONTAINS_TOP = 1 << 0, 22 // Specify that the requested size of the space to allocate is specified in 23 // words instead of bytes. 24 SIZE_IN_WORDS = 1 << 1, 25 // Align the allocation to a multiple of kDoubleSize 26 DOUBLE_ALIGNMENT = 1 << 2, 27 // Directly allocate in old space 28 PRETENURE = 1 << 3, 29 }; 30 31 enum class JumpMode { 32 kJump, // Does a direct jump to the given address 33 kPushAndReturn // Pushes the given address as the current return address and 34 // does a return 35 }; 36 37 enum class SmiCheck { kOmit, kInline }; 38 39 // This is the only place allowed to include the platform-specific headers. 40 #define INCLUDED_FROM_MACRO_ASSEMBLER_H 41 #if V8_TARGET_ARCH_IA32 42 #include "src/codegen/ia32/macro-assembler-ia32.h" 43 #elif V8_TARGET_ARCH_X64 44 #include "src/codegen/x64/macro-assembler-x64.h" 45 #elif V8_TARGET_ARCH_ARM64 46 #include "src/codegen/arm64/constants-arm64.h" 47 #include "src/codegen/arm64/macro-assembler-arm64.h" 48 #elif V8_TARGET_ARCH_ARM 49 #include "src/codegen/arm/constants-arm.h" 50 #include "src/codegen/arm/macro-assembler-arm.h" 51 #elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 52 #include "src/codegen/ppc/constants-ppc.h" 53 #include "src/codegen/ppc/macro-assembler-ppc.h" 54 #elif V8_TARGET_ARCH_MIPS 55 #include "src/codegen/mips/constants-mips.h" 56 #include "src/codegen/mips/macro-assembler-mips.h" 57 #elif V8_TARGET_ARCH_MIPS64 58 #include "src/codegen/mips64/constants-mips64.h" 59 #include "src/codegen/mips64/macro-assembler-mips64.h" 60 #elif V8_TARGET_ARCH_LOONG64 61 #include "src/codegen/loong64/constants-loong64.h" 62 #include "src/codegen/loong64/macro-assembler-loong64.h" 63 #elif V8_TARGET_ARCH_S390 64 #include "src/codegen/s390/constants-s390.h" 65 #include "src/codegen/s390/macro-assembler-s390.h" 66 #elif V8_TARGET_ARCH_RISCV64 67 #include "src/codegen/riscv64/constants-riscv64.h" 68 #include "src/codegen/riscv64/macro-assembler-riscv64.h" 69 #else 70 #error Unsupported target architecture. 71 #endif 72 #undef INCLUDED_FROM_MACRO_ASSEMBLER_H 73 74 namespace v8 { 75 namespace internal { 76 77 // Maximum number of parameters supported in calls to C/C++. The C++ standard 78 // defines a limit of 256 parameters but in simulator builds we provide only 79 // limited support. 80 #ifdef USE_SIMULATOR 81 static constexpr int kMaxCParameters = 20; 82 #else 83 static constexpr int kMaxCParameters = 256; 84 #endif 85 86 class V8_NODISCARD FrameScope { 87 public: FrameScope(TurboAssembler * tasm,StackFrame::Type type)88 explicit FrameScope(TurboAssembler* tasm, StackFrame::Type type) 89 : 90 #ifdef V8_CODE_COMMENTS 91 comment_(tasm, frame_name(type)), 92 #endif 93 tasm_(tasm), 94 type_(type), 95 old_has_frame_(tasm->has_frame()) { 96 tasm->set_has_frame(true); 97 if (type != StackFrame::MANUAL && type_ != StackFrame::NO_FRAME_TYPE) { 98 tasm->EnterFrame(type); 99 } 100 } 101 ~FrameScope()102 ~FrameScope() { 103 if (type_ != StackFrame::MANUAL && type_ != StackFrame::NO_FRAME_TYPE) { 104 tasm_->LeaveFrame(type_); 105 } 106 tasm_->set_has_frame(old_has_frame_); 107 } 108 109 private: 110 #ifdef V8_CODE_COMMENTS frame_name(StackFrame::Type type)111 const char* frame_name(StackFrame::Type type) { 112 switch (type) { 113 case StackFrame::NO_FRAME_TYPE: 114 return "Frame: NO_FRAME_TYPE"; 115 case StackFrame::MANUAL: 116 return "Frame: MANUAL"; 117 #define FRAME_TYPE_CASE(type, field) \ 118 case StackFrame::type: \ 119 return "Frame: " #type; 120 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) 121 #undef FRAME_TYPE_CASE 122 case StackFrame::NUMBER_OF_TYPES: 123 break; 124 } 125 return "Frame"; 126 } 127 128 Assembler::CodeComment comment_; 129 #endif // V8_CODE_COMMENTS 130 131 TurboAssembler* tasm_; 132 StackFrame::Type const type_; 133 bool const old_has_frame_; 134 }; 135 136 class V8_NODISCARD FrameAndConstantPoolScope { 137 public: FrameAndConstantPoolScope(MacroAssembler * masm,StackFrame::Type type)138 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type) 139 : masm_(masm), 140 type_(type), 141 old_has_frame_(masm->has_frame()), 142 old_constant_pool_available_(FLAG_enable_embedded_constant_pool && 143 masm->is_constant_pool_available()) { 144 masm->set_has_frame(true); 145 if (FLAG_enable_embedded_constant_pool) { 146 masm->set_constant_pool_available(true); 147 } 148 if (type_ != StackFrame::MANUAL && type_ != StackFrame::NO_FRAME_TYPE) { 149 masm->EnterFrame(type, !old_constant_pool_available_); 150 } 151 } 152 ~FrameAndConstantPoolScope()153 ~FrameAndConstantPoolScope() { 154 masm_->LeaveFrame(type_); 155 masm_->set_has_frame(old_has_frame_); 156 if (FLAG_enable_embedded_constant_pool) { 157 masm_->set_constant_pool_available(old_constant_pool_available_); 158 } 159 } 160 161 private: 162 MacroAssembler* masm_; 163 StackFrame::Type type_; 164 bool old_has_frame_; 165 bool old_constant_pool_available_; 166 167 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope); 168 }; 169 170 // Class for scoping the the unavailability of constant pool access. 171 class V8_NODISCARD ConstantPoolUnavailableScope { 172 public: ConstantPoolUnavailableScope(Assembler * assembler)173 explicit ConstantPoolUnavailableScope(Assembler* assembler) 174 : assembler_(assembler), 175 old_constant_pool_available_(FLAG_enable_embedded_constant_pool && 176 assembler->is_constant_pool_available()) { 177 if (FLAG_enable_embedded_constant_pool) { 178 assembler->set_constant_pool_available(false); 179 } 180 } ~ConstantPoolUnavailableScope()181 ~ConstantPoolUnavailableScope() { 182 if (FLAG_enable_embedded_constant_pool) { 183 assembler_->set_constant_pool_available(old_constant_pool_available_); 184 } 185 } 186 187 private: 188 Assembler* assembler_; 189 int old_constant_pool_available_; 190 191 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope); 192 }; 193 194 class V8_NODISCARD AllowExternalCallThatCantCauseGC : public FrameScope { 195 public: AllowExternalCallThatCantCauseGC(MacroAssembler * masm)196 explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm) 197 : FrameScope(masm, StackFrame::NO_FRAME_TYPE) {} 198 }; 199 200 // Prevent the use of the RootArray during the lifetime of this 201 // scope object. 202 class V8_NODISCARD NoRootArrayScope { 203 public: NoRootArrayScope(TurboAssembler * masm)204 explicit NoRootArrayScope(TurboAssembler* masm) 205 : masm_(masm), old_value_(masm->root_array_available()) { 206 masm->set_root_array_available(false); 207 } 208 ~NoRootArrayScope()209 ~NoRootArrayScope() { masm_->set_root_array_available(old_value_); } 210 211 private: 212 TurboAssembler* masm_; 213 bool old_value_; 214 }; 215 216 } // namespace internal 217 } // namespace v8 218 219 #endif // V8_CODEGEN_MACRO_ASSEMBLER_H_ 220