11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_CODEGEN_TURBO_ASSEMBLER_H_ 61cb0ef41Sopenharmony_ci#define V8_CODEGEN_TURBO_ASSEMBLER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <memory> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "src/base/template-utils.h" 111cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/assembler-arch.h" 131cb0ef41Sopenharmony_ci#include "src/roots/roots.h" 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cinamespace v8 { 161cb0ef41Sopenharmony_cinamespace internal { 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci// Common base class for platform-specific TurboAssemblers containing 191cb0ef41Sopenharmony_ci// platform-independent bits. 201cb0ef41Sopenharmony_ci// You will encounter two subclasses, TurboAssembler (derives from 211cb0ef41Sopenharmony_ci// TurboAssemblerBase), and MacroAssembler (derives from TurboAssembler). The 221cb0ef41Sopenharmony_ci// main difference is that MacroAssembler is allowed to access the isolate, and 231cb0ef41Sopenharmony_ci// TurboAssembler accesses the isolate in a very limited way. TurboAssembler 241cb0ef41Sopenharmony_ci// contains all the functionality that is used by Turbofan, and does not expect 251cb0ef41Sopenharmony_ci// to be running on the main thread. 261cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE TurboAssemblerBase : public Assembler { 271cb0ef41Sopenharmony_ci public: 281cb0ef41Sopenharmony_ci // Constructors are declared public to inherit them in derived classes 291cb0ef41Sopenharmony_ci // with `using` directive. 301cb0ef41Sopenharmony_ci TurboAssemblerBase(Isolate* isolate, CodeObjectRequired create_code_object, 311cb0ef41Sopenharmony_ci std::unique_ptr<AssemblerBuffer> buffer = {}) 321cb0ef41Sopenharmony_ci : TurboAssemblerBase(isolate, AssemblerOptions::Default(isolate), 331cb0ef41Sopenharmony_ci create_code_object, std::move(buffer)) {} 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci TurboAssemblerBase(Isolate* isolate, const AssemblerOptions& options, 361cb0ef41Sopenharmony_ci CodeObjectRequired create_code_object, 371cb0ef41Sopenharmony_ci std::unique_ptr<AssemblerBuffer> buffer = {}); 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci Isolate* isolate() const { 401cb0ef41Sopenharmony_ci return isolate_; 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci Handle<HeapObject> CodeObject() const { 441cb0ef41Sopenharmony_ci DCHECK(!code_object_.is_null()); 451cb0ef41Sopenharmony_ci return code_object_; 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci bool root_array_available() const { return root_array_available_; } 491cb0ef41Sopenharmony_ci void set_root_array_available(bool v) { root_array_available_ = v; } 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci bool trap_on_abort() const { return trap_on_abort_; } 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci bool should_abort_hard() const { return hard_abort_; } 541cb0ef41Sopenharmony_ci void set_abort_hard(bool v) { hard_abort_ = v; } 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci void set_builtin(Builtin builtin) { maybe_builtin_ = builtin; } 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci void set_has_frame(bool v) { has_frame_ = v; } 591cb0ef41Sopenharmony_ci bool has_frame() const { return has_frame_; } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci // Loads the given constant or external reference without embedding its direct 621cb0ef41Sopenharmony_ci // pointer. The produced code is isolate-independent. 631cb0ef41Sopenharmony_ci void IndirectLoadConstant(Register destination, Handle<HeapObject> object); 641cb0ef41Sopenharmony_ci void IndirectLoadExternalReference(Register destination, 651cb0ef41Sopenharmony_ci ExternalReference reference); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci Address BuiltinEntry(Builtin builtin); 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci virtual void LoadFromConstantsTable(Register destination, 701cb0ef41Sopenharmony_ci int constant_index) = 0; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci // Corresponds to: destination = kRootRegister + offset. 731cb0ef41Sopenharmony_ci virtual void LoadRootRegisterOffset(Register destination, 741cb0ef41Sopenharmony_ci intptr_t offset) = 0; 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci // Corresponds to: destination = [kRootRegister + offset]. 771cb0ef41Sopenharmony_ci virtual void LoadRootRelative(Register destination, int32_t offset) = 0; 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci virtual void LoadRoot(Register destination, RootIndex index) = 0; 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci static int32_t RootRegisterOffsetForRootIndex(RootIndex root_index); 821cb0ef41Sopenharmony_ci static int32_t RootRegisterOffsetForBuiltin(Builtin builtin); 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci // Returns the root-relative offset to reference.address(). 851cb0ef41Sopenharmony_ci static intptr_t RootRegisterOffsetForExternalReference( 861cb0ef41Sopenharmony_ci Isolate* isolate, const ExternalReference& reference); 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci // Returns the root-relative offset to the external reference table entry, 891cb0ef41Sopenharmony_ci // which itself contains reference.address(). 901cb0ef41Sopenharmony_ci static int32_t RootRegisterOffsetForExternalReferenceTableEntry( 911cb0ef41Sopenharmony_ci Isolate* isolate, const ExternalReference& reference); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci // An address is addressable through kRootRegister if it is located within 941cb0ef41Sopenharmony_ci // isolate->root_register_addressable_region(). 951cb0ef41Sopenharmony_ci static bool IsAddressableThroughRootRegister( 961cb0ef41Sopenharmony_ci Isolate* isolate, const ExternalReference& reference); 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci#if defined(V8_TARGET_OS_WIN) || defined(V8_TARGET_OS_MACOS) 991cb0ef41Sopenharmony_ci // Minimum page size. We must touch memory once per page when expanding the 1001cb0ef41Sopenharmony_ci // stack, to avoid access violations. 1011cb0ef41Sopenharmony_ci static constexpr int kStackPageSize = 4 * KB; 1021cb0ef41Sopenharmony_ci#endif 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci V8_INLINE std::string CommentForOffHeapTrampoline(const char* prefix, 1051cb0ef41Sopenharmony_ci Builtin builtin) { 1061cb0ef41Sopenharmony_ci if (!FLAG_code_comments) return ""; 1071cb0ef41Sopenharmony_ci std::ostringstream str; 1081cb0ef41Sopenharmony_ci str << "Inlined Trampoline for " << prefix << " to " 1091cb0ef41Sopenharmony_ci << Builtins::name(builtin); 1101cb0ef41Sopenharmony_ci return str.str(); 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci V8_INLINE void RecordCommentForOffHeapTrampoline(Builtin builtin) { 1141cb0ef41Sopenharmony_ci if (!FLAG_code_comments) return; 1151cb0ef41Sopenharmony_ci std::ostringstream str; 1161cb0ef41Sopenharmony_ci str << "[ Inlined Trampoline to " << Builtins::name(builtin); 1171cb0ef41Sopenharmony_ci RecordComment(str.str().c_str()); 1181cb0ef41Sopenharmony_ci } 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci enum class RecordWriteCallMode { kDefault, kWasm }; 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci protected: 1231cb0ef41Sopenharmony_ci Isolate* const isolate_ = nullptr; 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci // This handle will be patched with the code object on installation. 1261cb0ef41Sopenharmony_ci Handle<HeapObject> code_object_; 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci // Whether kRootRegister has been initialized. 1291cb0ef41Sopenharmony_ci bool root_array_available_ = true; 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci // Immediately trap instead of calling {Abort} when debug code fails. 1321cb0ef41Sopenharmony_ci bool trap_on_abort_ = FLAG_trap_on_abort; 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci // Emit a C call to abort instead of a runtime call. 1351cb0ef41Sopenharmony_ci bool hard_abort_ = false; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci // May be set while generating builtins. 1381cb0ef41Sopenharmony_ci Builtin maybe_builtin_ = Builtin::kNoBuiltinId; 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci bool has_frame_ = false; 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci int comment_depth_ = 0; 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci DISALLOW_IMPLICIT_CONSTRUCTORS(TurboAssemblerBase); 1451cb0ef41Sopenharmony_ci}; 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci// Avoids emitting calls to the {Builtin::kAbort} builtin when emitting 1481cb0ef41Sopenharmony_ci// debug code during the lifetime of this scope object. 1491cb0ef41Sopenharmony_ciclass V8_NODISCARD HardAbortScope { 1501cb0ef41Sopenharmony_ci public: 1511cb0ef41Sopenharmony_ci explicit HardAbortScope(TurboAssemblerBase* assembler) 1521cb0ef41Sopenharmony_ci : assembler_(assembler), old_value_(assembler->should_abort_hard()) { 1531cb0ef41Sopenharmony_ci assembler_->set_abort_hard(true); 1541cb0ef41Sopenharmony_ci } 1551cb0ef41Sopenharmony_ci ~HardAbortScope() { assembler_->set_abort_hard(old_value_); } 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci private: 1581cb0ef41Sopenharmony_ci TurboAssemblerBase* assembler_; 1591cb0ef41Sopenharmony_ci bool old_value_; 1601cb0ef41Sopenharmony_ci}; 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci} // namespace internal 1631cb0ef41Sopenharmony_ci} // namespace v8 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci#endif // V8_CODEGEN_TURBO_ASSEMBLER_H_ 166