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