v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
maglev-safepoint-table.h
Go to the documentation of this file.
1// Copyright 2022 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_MAGLEV_SAFEPOINT_TABLE_H_
6#define V8_CODEGEN_MAGLEV_SAFEPOINT_TABLE_H_
7
8#include <cstdint>
9
10#include "src/base/bit-field.h"
15#include "src/zone/zone.h"
16
17namespace v8 {
18namespace internal {
19
20class GcSafeCode;
21
23 public:
24 static constexpr int kNoDeoptIndex = -1;
25 static constexpr int kNoTrampolinePC = -1;
26
28
38
39 bool operator==(const MaglevSafepointEntry& other) const {
40 return this->SafepointEntryBase::operator==(other) &&
41 num_tagged_slots_ == other.num_tagged_slots_ &&
42 num_extra_spill_slots_ == other.num_extra_spill_slots_ &&
43 tagged_register_indexes_ == other.tagged_register_indexes_;
44 }
45
46 uint32_t num_tagged_slots() const { return num_tagged_slots_; }
49
51
52 private:
53 uint32_t num_tagged_slots_ = 0;
56};
57
58// A wrapper class for accessing the safepoint table embedded into the
59// InstructionStream object.
61 public:
62 // The isolate and pc arguments are used for figuring out whether pc
63 // belongs to the embedded or un-embedded code blob.
64 explicit MaglevSafepointTable(Isolate* isolate, Address pc,
65 Tagged<Code> code);
68
69 int length() const { return length_; }
70
71 int byte_size() const { return kHeaderSize + length_ * entry_size(); }
72
74
75 uint32_t stack_slots() { return stack_slots_; }
76
77 MaglevSafepointEntry GetEntry(int index) const {
78 DCHECK_GT(length_, index);
79 Address entry_ptr =
80 safepoint_table_address_ + kHeaderSize + index * entry_size();
81
82 int pc = read_bytes(&entry_ptr, pc_size());
84 int trampoline_pc = MaglevSafepointEntry::kNoTrampolinePC;
85 if (has_deopt_data()) {
86 static_assert(MaglevSafepointEntry::kNoDeoptIndex == -1);
87 static_assert(MaglevSafepointEntry::kNoTrampolinePC == -1);
88 // `-1` to restore the original value, see also
89 // MaglevSafepointTableBuilder::Emit.
90 deopt_index = read_bytes(&entry_ptr, deopt_index_size()) - 1;
91 trampoline_pc = read_bytes(&entry_ptr, pc_size()) - 1;
92 DCHECK(deopt_index >= 0 ||
94 DCHECK(trampoline_pc >= 0 ||
96 }
97 uint8_t num_extra_spill_slots = read_byte(&entry_ptr);
98 int tagged_register_indexes =
99 read_bytes(&entry_ptr, register_indexes_size());
100
101 return MaglevSafepointEntry(pc, deopt_index, num_tagged_slots_,
102 num_extra_spill_slots, tagged_register_indexes,
103 trampoline_pc);
104 }
105
106 // Returns the entry for the given pc.
108 static MaglevSafepointEntry FindEntry(Isolate* isolate,
110
111 void Print(std::ostream&) const;
112
113 private:
115
116 // Layout information.
117#define FIELD_LIST(V) \
118 V(kStackSlotsOffset, sizeof(SafepointTableStackSlotsField_t)) \
119 V(kLengthOffset, kIntSize) \
120 V(kEntryConfigurationOffset, kUInt32Size) \
121 /* The number of tagged/untagged slots is constant for the whole code so \
122 just store it in the header. */ \
123 V(kNumTaggedSlotsOffset, kUInt32Size) \
124 V(kHeaderSize, 0)
125
127#undef FIELD_LIST
128
129 static_assert(kStackSlotsOffset == kSafepointTableStackSlotsOffset);
135
136 MaglevSafepointTable(Address instruction_start,
137 Address safepoint_table_address);
139 int entry_size() const {
140 int deopt_data_size = has_deopt_data() ? pc_size() + deopt_index_size() : 0;
141 const int num_pushed_registers_size = 1;
142 return pc_size() + deopt_data_size + num_pushed_registers_size +
144 }
155 }
157 static int read_bytes(Address* ptr, int bytes) {
158 uint32_t result = 0;
159 for (int b = 0; b < bytes; ++b) {
160 result |= uint32_t{read_byte(ptr)} << (8 * b);
161 }
162 return static_cast<int>(result);
163 }
165 static uint8_t read_byte(Address* ptr) {
166 uint8_t result = *reinterpret_cast<uint8_t*>(*ptr);
167 ++*ptr;
168 return result;
169 }
170
174
175 // Safepoint table layout.
178 const int length_;
179 const uint32_t entry_configuration_;
180 const uint32_t num_tagged_slots_;
183 friend class MaglevSafepointEntry;
184};
187 private:
189 int pc;
190 int deopt_index = MaglevSafepointEntry::kNoDeoptIndex;
191 int trampoline = MaglevSafepointEntry::kNoTrampolinePC;
192 uint8_t num_extra_spill_slots = 0;
193 uint32_t tagged_register_indexes = 0;
194 explicit EntryBuilder(int pc) : pc(pc) {}
195 };
196
197 public:
198 explicit MaglevSafepointTableBuilder(Zone* zone, uint32_t num_tagged_slots)
199 : num_tagged_slots_(num_tagged_slots), entries_(zone) {}
203 delete;
205 class Safepoint {
206 public:
207 void DefineTaggedRegister(int reg_code) {
208 DCHECK_LT(reg_code,
209 kBitsPerByte * sizeof(EntryBuilder::tagged_register_indexes));
210 entry_->tagged_register_indexes |= 1u << reg_code;
212 void SetNumExtraSpillSlots(uint8_t num_slots) {
213 entry_->num_extra_spill_slots = num_slots;
214 }
215
216 private:
218 explicit Safepoint(EntryBuilder* entry) : entry_(entry) {}
219 EntryBuilder* const entry_;
220 };
221
222 // Define a new safepoint for the current position in the body.
223 Safepoint DefineSafepoint(Assembler* assembler);
224
225 // Emit the safepoint table after the body.
226 V8_EXPORT_PRIVATE void Emit(Assembler* assembler, int stack_slots);
227
228 // Find the Deoptimization Info with pc offset {pc} and update its
229 // trampoline field. Calling this function ensures that the safepoint
230 // table contains the trampoline PC {trampoline} that replaced the
231 // return PC {pc} on the stack.
232 int UpdateDeoptimizationInfo(int pc, int trampoline, int start,
233 int deopt_index);
234
235 private:
236 const uint32_t num_tagged_slots_;
238};
239
240} // namespace internal
241} // namespace v8
242
243#endif // V8_CODEGEN_MAGLEV_SAFEPOINT_TABLE_H_
#define DISALLOW_GARBAGE_COLLECTION(name)
static constexpr T decode(U value)
Definition bit-field.h:66
MaglevSafepointEntry(int pc, int deopt_index, uint32_t num_tagged_slots, uint8_t num_extra_spill_slots, uint32_t tagged_register_indexes, int trampoline_pc)
bool operator==(const MaglevSafepointEntry &other) const
static int read_bytes(Address *ptr, int bytes)
static uint8_t read_byte(Address *ptr)
MaglevSafepointEntry FindEntry(Address pc) const
MaglevSafepointTable & operator=(const MaglevSafepointTable &)=delete
MaglevSafepointTable(Isolate *isolate, Address pc, Tagged< Code > code)
MaglevSafepointEntry GetEntry(int index) const
const SafepointTableStackSlotsField_t stack_slots_
MaglevSafepointTable(const MaglevSafepointTable &)=delete
bool operator==(const SafepointEntryBase &other) const
int start
DisallowGarbageCollection no_gc_
HeapEntry * entry_
ZoneVector< RpoNumber > & result
std::vector< EntryBuilder > entries_
int pc_offset
#define FIELD_LIST(V)
constexpr int kBitsPerByte
Definition globals.h:682
uint32_t SafepointTableStackSlotsField_t
constexpr int kSafepointTableStackSlotsOffset
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO)
Definition utils.h:242