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. 13enum class InvokeType { kCall, kJump }; 14 15// Flags used for the AllocateInNewSpace functions. 16enum 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 31enum 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 37enum 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 74namespace v8 { 75namespace 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 81static constexpr int kMaxCParameters = 20; 82#else 83static constexpr int kMaxCParameters = 256; 84#endif 85 86class V8_NODISCARD FrameScope { 87 public: 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 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 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 136class V8_NODISCARD FrameAndConstantPoolScope { 137 public: 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 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. 171class V8_NODISCARD ConstantPoolUnavailableScope { 172 public: 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 } 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 194class V8_NODISCARD AllowExternalCallThatCantCauseGC : public FrameScope { 195 public: 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. 202class V8_NODISCARD NoRootArrayScope { 203 public: 204 explicit NoRootArrayScope(TurboAssembler* masm) 205 : masm_(masm), old_value_(masm->root_array_available()) { 206 masm->set_root_array_available(false); 207 } 208 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