summaryrefslogtreecommitdiff
path: root/deps/v8/src/codegen/turbo-assembler.h
blob: 88ec873425ce7fcd8020b1f9a5a7ebaafa11def9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_CODEGEN_TURBO_ASSEMBLER_H_
#define V8_CODEGEN_TURBO_ASSEMBLER_H_

#include <memory>

#include "src/base/template-utils.h"
#include "src/builtins/builtins.h"
#include "src/codegen/assembler-arch.h"
#include "src/roots/roots.h"

namespace v8 {
namespace internal {

// Common base class for platform-specific TurboAssemblers containing
// platform-independent bits.
// You will encounter two subclasses, TurboAssembler (derives from
// TurboAssemblerBase), and MacroAssembler (derives from TurboAssembler). The
// main difference is that MacroAssembler is allowed to access the isolate, and
// TurboAssembler accesses the isolate in a very limited way. TurboAssembler
// contains all the functionality that is used by Turbofan, and does not expect
// to be running on the main thread.
class V8_EXPORT_PRIVATE TurboAssemblerBase : public Assembler {
 public:
  // Constructors are declared public to inherit them in derived classes
  // with `using` directive.
  TurboAssemblerBase(Isolate* isolate, CodeObjectRequired create_code_object,
                     std::unique_ptr<AssemblerBuffer> buffer = {})
      : TurboAssemblerBase(isolate, AssemblerOptions::Default(isolate),
                           create_code_object, std::move(buffer)) {}

  TurboAssemblerBase(Isolate* isolate, const AssemblerOptions& options,
                     CodeObjectRequired create_code_object,
                     std::unique_ptr<AssemblerBuffer> buffer = {});

  Isolate* isolate() const {
    return isolate_;
  }

  Handle<HeapObject> CodeObject() const {
    DCHECK(!code_object_.is_null());
    return code_object_;
  }

  bool root_array_available() const { return root_array_available_; }
  void set_root_array_available(bool v) { root_array_available_ = v; }

  bool trap_on_abort() const { return trap_on_abort_; }

  bool should_abort_hard() const { return hard_abort_; }
  void set_abort_hard(bool v) { hard_abort_ = v; }

  void set_builtin(Builtin builtin) { maybe_builtin_ = builtin; }

  void set_has_frame(bool v) { has_frame_ = v; }
  bool has_frame() const { return has_frame_; }

  // Loads the given constant or external reference without embedding its direct
  // pointer. The produced code is isolate-independent.
  void IndirectLoadConstant(Register destination, Handle<HeapObject> object);
  void IndirectLoadExternalReference(Register destination,
                                     ExternalReference reference);

  Address BuiltinEntry(Builtin builtin);

  virtual void LoadFromConstantsTable(Register destination,
                                      int constant_index) = 0;

  // Corresponds to: destination = kRootRegister + offset.
  virtual void LoadRootRegisterOffset(Register destination,
                                      intptr_t offset) = 0;

  // Corresponds to: destination = [kRootRegister + offset].
  virtual void LoadRootRelative(Register destination, int32_t offset) = 0;

  virtual void LoadRoot(Register destination, RootIndex index) = 0;

  static int32_t RootRegisterOffsetForRootIndex(RootIndex root_index);
  static int32_t RootRegisterOffsetForBuiltin(Builtin builtin);

  // Returns the root-relative offset to reference.address().
  static intptr_t RootRegisterOffsetForExternalReference(
      Isolate* isolate, const ExternalReference& reference);

  // Returns the root-relative offset to the external reference table entry,
  // which itself contains reference.address().
  static int32_t RootRegisterOffsetForExternalReferenceTableEntry(
      Isolate* isolate, const ExternalReference& reference);

  // An address is addressable through kRootRegister if it is located within
  // isolate->root_register_addressable_region().
  static bool IsAddressableThroughRootRegister(
      Isolate* isolate, const ExternalReference& reference);

#if defined(V8_TARGET_OS_WIN) || defined(V8_TARGET_OS_MACOS)
  // Minimum page size. We must touch memory once per page when expanding the
  // stack, to avoid access violations.
  static constexpr int kStackPageSize = 4 * KB;
#endif

  V8_INLINE std::string CommentForOffHeapTrampoline(const char* prefix,
                                                    Builtin builtin) {
    if (!v8_flags.code_comments) return "";
    std::ostringstream str;
    str << "Inlined  Trampoline for " << prefix << " to "
        << Builtins::name(builtin);
    return str.str();
  }

  enum class RecordWriteCallMode { kDefault, kWasm };

 protected:
  Isolate* const isolate_ = nullptr;

  // This handle will be patched with the code object on installation.
  Handle<HeapObject> code_object_;

  // Whether kRootRegister has been initialized.
  bool root_array_available_ = true;

  // Immediately trap instead of calling {Abort} when debug code fails.
  bool trap_on_abort_ = v8_flags.trap_on_abort;

  // Emit a C call to abort instead of a runtime call.
  bool hard_abort_ = false;

  // May be set while generating builtins.
  Builtin maybe_builtin_ = Builtin::kNoBuiltinId;

  bool has_frame_ = false;

  int comment_depth_ = 0;

  DISALLOW_IMPLICIT_CONSTRUCTORS(TurboAssemblerBase);
};

// Avoids emitting calls to the {Builtin::kAbort} builtin when emitting
// debug code during the lifetime of this scope object.
class V8_NODISCARD HardAbortScope {
 public:
  explicit HardAbortScope(TurboAssemblerBase* assembler)
      : assembler_(assembler), old_value_(assembler->should_abort_hard()) {
    assembler_->set_abort_hard(true);
  }
  ~HardAbortScope() { assembler_->set_abort_hard(old_value_); }

 private:
  TurboAssemblerBase* assembler_;
  bool old_value_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_CODEGEN_TURBO_ASSEMBLER_H_