Commit 76356780 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Add a maglev-specific safepoint mechanism

Maglev groups all its tagged spill slots together, and the number of
them doesn't change. This means that the generality of the existing
safepoint mechanism is massive overkill for maglev code.

This patch adds a maglev-specific safepoint table, which is the
safepoint of a code object if-and-only-if that code object has maglev
code. This safepoint stores the number of tagged and untagged slots
once, globally, and individual entries are just used for deopts and for
storing the state of pushed registers (this is currently unused, but
will be used in the future for pushing registers in deferred calls).

Bug: v8:7700
Change-Id: I15f84a6e957357825e84e33238f8a36f2e0b3012
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3747858
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81564}
parent c04fba93
......@@ -2779,6 +2779,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/machine-type.h",
"src/codegen/macro-assembler-inl.h",
"src/codegen/macro-assembler.h",
"src/codegen/maglev-safepoint-table.h",
"src/codegen/optimized-compilation-info.h",
"src/codegen/pending-optimization-table.h",
"src/codegen/register-arch.h",
......@@ -2788,6 +2789,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/reglist-base.h",
"src/codegen/reglist.h",
"src/codegen/reloc-info.h",
"src/codegen/safepoint-table-base.h",
"src/codegen/safepoint-table.h",
"src/codegen/script-details.h",
"src/codegen/signature.h",
......@@ -4288,6 +4290,7 @@ v8_source_set("v8_base_without_compiler") {
"src/codegen/handler-table.cc",
"src/codegen/interface-descriptors.cc",
"src/codegen/machine-type.cc",
"src/codegen/maglev-safepoint-table.cc",
"src/codegen/optimized-compilation-info.cc",
"src/codegen/pending-optimization-table.cc",
"src/codegen/register-configuration.cc",
......
This diff is collapsed.
// Copyright 2022 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_MAGLEV_SAFEPOINT_TABLE_H_
#define V8_CODEGEN_MAGLEV_SAFEPOINT_TABLE_H_
#include <cstdint>
#include "src/base/bit-field.h"
#include "src/codegen/safepoint-table-base.h"
#include "src/common/assert-scope.h"
#include "src/utils/allocation.h"
#include "src/zone/zone-chunk-list.h"
#include "src/zone/zone.h"
namespace v8 {
namespace internal {
class MaglevSafepointEntry : public SafepointEntryBase {
public:
static constexpr int kNoDeoptIndex = -1;
static constexpr int kNoTrampolinePC = -1;
MaglevSafepointEntry() = default;
MaglevSafepointEntry(int pc, int deopt_index, uint32_t num_tagged_slots,
uint32_t num_untagged_slots,
uint8_t num_pushed_registers,
uint32_t tagged_register_indexes, int trampoline_pc)
: SafepointEntryBase(pc, deopt_index, trampoline_pc),
num_tagged_slots_(num_tagged_slots),
num_untagged_slots_(num_untagged_slots),
num_pushed_registers_(num_pushed_registers),
tagged_register_indexes_(tagged_register_indexes) {
DCHECK(is_initialized());
}
bool operator==(const MaglevSafepointEntry& other) const {
return this->SafepointEntryBase::operator==(other) &&
num_tagged_slots_ == other.num_tagged_slots_ &&
num_untagged_slots_ == other.num_untagged_slots_ &&
num_pushed_registers_ == other.num_pushed_registers_ &&
tagged_register_indexes_ == other.tagged_register_indexes_;
}
uint32_t num_tagged_slots() const { return num_tagged_slots_; }
uint32_t num_untagged_slots() const { return num_untagged_slots_; }
uint8_t num_pushed_registers() const { return num_pushed_registers_; }
uint32_t tagged_register_indexes() const { return tagged_register_indexes_; }
private:
uint32_t num_tagged_slots_ = 0;
uint32_t num_untagged_slots_ = 0;
uint8_t num_pushed_registers_ = 0;
uint32_t tagged_register_indexes_ = 0;
};
// A wrapper class for accessing the safepoint table embedded into the Code
// object.
class MaglevSafepointTable {
public:
// The isolate and pc arguments are used for figuring out whether pc
// belongs to the embedded or un-embedded code blob.
explicit MaglevSafepointTable(Isolate* isolate, Address pc, Code code);
MaglevSafepointTable(const MaglevSafepointTable&) = delete;
MaglevSafepointTable& operator=(const MaglevSafepointTable&) = delete;
int length() const { return length_; }
int byte_size() const { return kHeaderSize + length_ * entry_size(); }
int find_return_pc(int pc_offset);
MaglevSafepointEntry GetEntry(int index) const {
DCHECK_GT(length_, index);
Address entry_ptr =
safepoint_table_address_ + kHeaderSize + index * entry_size();
int pc = read_bytes(&entry_ptr, pc_size());
int deopt_index = MaglevSafepointEntry::kNoDeoptIndex;
int trampoline_pc = MaglevSafepointEntry::kNoTrampolinePC;
if (has_deopt_data()) {
static_assert(MaglevSafepointEntry::kNoDeoptIndex == -1);
static_assert(MaglevSafepointEntry::kNoTrampolinePC == -1);
// `-1` to restore the original value, see also
// MaglevSafepointTableBuilder::Emit.
deopt_index = read_bytes(&entry_ptr, deopt_index_size()) - 1;
trampoline_pc = read_bytes(&entry_ptr, pc_size()) - 1;
DCHECK(deopt_index >= 0 ||
deopt_index == MaglevSafepointEntry::kNoDeoptIndex);
DCHECK(trampoline_pc >= 0 ||
trampoline_pc == MaglevSafepointEntry::kNoTrampolinePC);
}
uint8_t num_pushed_registers = read_byte(&entry_ptr);
int tagged_register_indexes =
read_bytes(&entry_ptr, register_indexes_size());
return MaglevSafepointEntry(pc, deopt_index, num_tagged_slots_,
num_untagged_slots_, num_pushed_registers,
tagged_register_indexes, trampoline_pc);
}
// Returns the entry for the given pc.
MaglevSafepointEntry FindEntry(Address pc) const;
void Print(std::ostream&) const;
private:
// Layout information.
static constexpr int kLengthOffset = 0;
static constexpr int kEntryConfigurationOffset = kLengthOffset + kIntSize;
// The number of tagged/untagged slots is constant for the whole code so just
// store it in the header.
static constexpr int kNumTaggedSlotsOffset =
kEntryConfigurationOffset + kUInt32Size;
static constexpr int kNumUntaggedSlotsOffset =
kNumTaggedSlotsOffset + kUInt32Size;
static constexpr int kHeaderSize = kNumUntaggedSlotsOffset + kUInt32Size;
using HasDeoptDataField = base::BitField<bool, 0, 1>;
using RegisterIndexesSizeField = HasDeoptDataField::Next<int, 3>;
using PcSizeField = RegisterIndexesSizeField::Next<int, 3>;
using DeoptIndexSizeField = PcSizeField::Next<int, 3>;
MaglevSafepointTable(Address instruction_start,
Address safepoint_table_address);
int entry_size() const {
int deopt_data_size = has_deopt_data() ? pc_size() + deopt_index_size() : 0;
const int num_pushed_registers_size = 1;
return pc_size() + deopt_data_size + num_pushed_registers_size +
register_indexes_size();
}
bool has_deopt_data() const {
return HasDeoptDataField::decode(entry_configuration_);
}
int pc_size() const { return PcSizeField::decode(entry_configuration_); }
int deopt_index_size() const {
return DeoptIndexSizeField::decode(entry_configuration_);
}
int register_indexes_size() const {
return RegisterIndexesSizeField::decode(entry_configuration_);
}
static int read_bytes(Address* ptr, int bytes) {
uint32_t result = 0;
for (int b = 0; b < bytes; ++b) {
result |= uint32_t{read_byte(ptr)} << (8 * b);
}
return static_cast<int>(result);
}
static uint8_t read_byte(Address* ptr) {
uint8_t result = *reinterpret_cast<uint8_t*>(*ptr);
++*ptr;
return result;
}
DISALLOW_GARBAGE_COLLECTION(no_gc_)
const Address instruction_start_;
// Safepoint table layout.
const Address safepoint_table_address_;
const int length_;
const uint32_t entry_configuration_;
const uint32_t num_tagged_slots_;
const uint32_t num_untagged_slots_;
friend class MaglevSafepointTableBuilder;
friend class MaglevSafepointEntry;
};
class MaglevSafepointTableBuilder : public SafepointTableBuilderBase {
private:
struct EntryBuilder {
int pc;
int deopt_index = MaglevSafepointEntry::kNoDeoptIndex;
int trampoline = MaglevSafepointEntry::kNoTrampolinePC;
uint8_t num_pushed_registers = 0;
uint32_t tagged_register_indexes = 0;
explicit EntryBuilder(int pc) : pc(pc) {}
};
public:
explicit MaglevSafepointTableBuilder(Zone* zone, uint32_t num_tagged_slots,
uint32_t num_untagged_slots)
: num_tagged_slots_(num_tagged_slots),
num_untagged_slots_(num_untagged_slots),
entries_(zone) {}
MaglevSafepointTableBuilder(const MaglevSafepointTableBuilder&) = delete;
MaglevSafepointTableBuilder& operator=(const MaglevSafepointTableBuilder&) =
delete;
class Safepoint {
public:
void DefineTaggedRegister(int reg_code) {
DCHECK_LT(reg_code,
kBitsPerByte * sizeof(EntryBuilder::tagged_register_indexes));
entry_->tagged_register_indexes |= 1u << reg_code;
}
void SetNumPushedRegisters(uint8_t num_registers) {
entry_->num_pushed_registers = num_registers;
}
private:
friend class MaglevSafepointTableBuilder;
explicit Safepoint(EntryBuilder* entry) : entry_(entry) {}
EntryBuilder* const entry_;
};
// Define a new safepoint for the current position in the body.
Safepoint DefineSafepoint(Assembler* assembler);
// Emit the safepoint table after the body.
V8_EXPORT_PRIVATE void Emit(Assembler* assembler);
// Find the Deoptimization Info with pc offset {pc} and update its
// trampoline field. Calling this function ensures that the safepoint
// table contains the trampoline PC {trampoline} that replaced the
// return PC {pc} on the stack.
int UpdateDeoptimizationInfo(int pc, int trampoline, int start,
int deopt_index);
private:
// Remove consecutive identical entries.
void RemoveDuplicates();
const uint32_t num_tagged_slots_;
const uint32_t num_untagged_slots_;
ZoneChunkList<EntryBuilder> entries_;
};
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_MAGLEV_SAFEPOINT_TABLE_H_
// Copyright 2022 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_SAFEPOINT_TABLE_BASE_H_
#define V8_CODEGEN_SAFEPOINT_TABLE_BASE_H_
#include <cstdint>
#include "src/base/logging.h"
namespace v8 {
namespace internal {
class SafepointEntryBase {
public:
static constexpr int kNoDeoptIndex = -1;
static constexpr int kNoTrampolinePC = -1;
SafepointEntryBase() = default;
SafepointEntryBase(int pc, int deopt_index, int trampoline_pc)
: pc_(pc), deopt_index_(deopt_index), trampoline_pc_(trampoline_pc) {
DCHECK(is_initialized());
}
bool is_initialized() const { return pc_ != 0; }
int pc() const {
DCHECK(is_initialized());
return pc_;
}
int trampoline_pc() const { return trampoline_pc_; }
bool has_deoptimization_index() const {
return deopt_index_ != kNoDeoptIndex;
}
int deoptimization_index() const {
DCHECK(has_deoptimization_index());
return deopt_index_;
}
void Reset() { pc_ = 0; }
protected:
bool operator==(const SafepointEntryBase& other) const {
return pc_ == other.pc_ && deopt_index_ == other.deopt_index_ &&
trampoline_pc_ == other.trampoline_pc_;
}
private:
int pc_ = 0;
int deopt_index_ = kNoDeoptIndex;
int trampoline_pc_ = kNoTrampolinePC;
};
class SafepointTableBuilderBase {
public:
bool emitted() const {
return safepoint_table_offset_ != kNoSafepointTableOffset;
}
int safepoint_table_offset() const {
DCHECK(emitted());
return safepoint_table_offset_;
}
protected:
void set_safepoint_table_offset(int offset) {
DCHECK(!emitted());
safepoint_table_offset_ = offset;
DCHECK(emitted());
}
private:
static constexpr int kNoSafepointTableOffset = -1;
int safepoint_table_offset_ = kNoSafepointTableOffset;
};
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_SAFEPOINT_TABLE_BASE_H_
......@@ -166,7 +166,7 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int tagged_slots_size) {
// Make sure the safepoint table is properly aligned. Pad with nops.
assembler->Align(Code::kMetadataAlignment);
assembler->RecordComment(";;; Safepoint table.");
safepoint_table_offset_ = assembler->pc_offset();
set_safepoint_table_offset(assembler->pc_offset());
// Compute the required sizes of the fields.
int used_register_indexes = 0;
......@@ -203,10 +203,10 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int tagged_slots_size) {
// Add a CHECK to ensure we never overflow the space in the bitfield, even for
// huge functions which might not be covered by tests.
CHECK(SafepointTable::RegisterIndexesSizeField::is_valid(
register_indexes_size) &&
SafepointTable::PcSizeField::is_valid(pc_size) &&
SafepointTable::DeoptIndexSizeField::is_valid(deopt_index_size) &&
SafepointTable::TaggedSlotsBytesField::is_valid(tagged_slots_bytes));
register_indexes_size));
CHECK(SafepointTable::PcSizeField::is_valid(pc_size));
CHECK(SafepointTable::DeoptIndexSizeField::is_valid(deopt_index_size));
CHECK(SafepointTable::TaggedSlotsBytesField::is_valid(tagged_slots_bytes));
uint32_t entry_configuration =
SafepointTable::HasDeoptDataField::encode(has_deopt_data) |
......
......@@ -6,12 +6,10 @@
#define V8_CODEGEN_SAFEPOINT_TABLE_H_
#include "src/base/bit-field.h"
#include "src/base/iterator.h"
#include "src/base/memory.h"
#include "src/codegen/safepoint-table-base.h"
#include "src/common/assert-scope.h"
#include "src/utils/allocation.h"
#include "src/utils/bit-vector.h"
#include "src/utils/utils.h"
#include "src/zone/zone-chunk-list.h"
#include "src/zone/zone.h"
......@@ -22,49 +20,22 @@ namespace wasm {
class WasmCode;
} // namespace wasm
class SafepointEntry {
class SafepointEntry : public SafepointEntryBase {
public:
static constexpr int kNoDeoptIndex = -1;
static constexpr int kNoTrampolinePC = -1;
SafepointEntry() = default;
SafepointEntry(int pc, int deopt_index, uint32_t tagged_register_indexes,
base::Vector<uint8_t> tagged_slots, int trampoline_pc)
: pc_(pc),
deopt_index_(deopt_index),
: SafepointEntryBase(pc, deopt_index, trampoline_pc),
tagged_register_indexes_(tagged_register_indexes),
tagged_slots_(tagged_slots),
trampoline_pc_(trampoline_pc) {
tagged_slots_(tagged_slots) {
DCHECK(is_initialized());
}
bool is_initialized() const { return tagged_slots_.begin() != nullptr; }
bool operator==(const SafepointEntry& other) const {
return pc_ == other.pc_ && deopt_index_ == other.deopt_index_ &&
return this->SafepointEntryBase::operator==(other) &&
tagged_register_indexes_ == other.tagged_register_indexes_ &&
tagged_slots_ == other.tagged_slots_ &&
trampoline_pc_ == other.trampoline_pc_;
}
void Reset() {
*this = SafepointEntry{};
DCHECK(!is_initialized());
}
int pc() const { return pc_; }
int trampoline_pc() const { return trampoline_pc_; }
bool has_deoptimization_index() const {
DCHECK(is_initialized());
return deopt_index_ != kNoDeoptIndex;
}
int deoptimization_index() const {
DCHECK(is_initialized() && has_deoptimization_index());
return deopt_index_;
tagged_slots_ == other.tagged_slots_;
}
uint32_t tagged_register_indexes() const {
......@@ -74,15 +45,13 @@ class SafepointEntry {
base::Vector<const uint8_t> tagged_slots() const {
DCHECK(is_initialized());
DCHECK_NOT_NULL(tagged_slots_.data());
return tagged_slots_;
}
private:
int pc_ = -1;
int deopt_index_ = kNoDeoptIndex;
uint32_t tagged_register_indexes_ = 0;
base::Vector<uint8_t> tagged_slots_;
int trampoline_pc_ = kNoTrampolinePC;
};
// A wrapper class for accessing the safepoint table embedded into the Code
......@@ -203,7 +172,7 @@ class SafepointTable {
friend class SafepointEntry;
};
class SafepointTableBuilder {
class SafepointTableBuilder : public SafepointTableBuilderBase {
private:
struct EntryBuilder {
int pc;
......@@ -221,15 +190,6 @@ class SafepointTableBuilder {
SafepointTableBuilder(const SafepointTableBuilder&) = delete;
SafepointTableBuilder& operator=(const SafepointTableBuilder&) = delete;
bool emitted() const {
return safepoint_table_offset_ != kNoSafepointTableOffset;
}
int safepoint_table_offset() const {
DCHECK(emitted());
return safepoint_table_offset_;
}
class Safepoint {
public:
void DefineTaggedStackSlot(int index) {
......@@ -286,8 +246,6 @@ class SafepointTableBuilder {
: min_stack_index_;
}
static constexpr int kNoSafepointTableOffset = -1;
// Tracks the min/max stack slot index over all entries. We need the minimum
// index when encoding the actual table since we shift all unused lower
// indices out of the encoding. Tracking the indices during safepoint
......@@ -298,8 +256,7 @@ class SafepointTableBuilder {
int min_stack_index_ = std::numeric_limits<int>::max();
ZoneChunkList<EntryBuilder> entries_;
int safepoint_table_offset_ = kNoSafepointTableOffset;
Zone* const zone_;
Zone* zone_;
};
} // namespace internal
......
......@@ -371,7 +371,7 @@ Assembler::Assembler(const AssemblerOptions& options,
}
void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
SafepointTableBuilder* safepoint_table_builder,
SafepointTableBuilderBase* safepoint_table_builder,
int handler_table_offset) {
// As a crutch to avoid having to add manual Align calls wherever we use a
// raw workflow to create Code objects (mostly in tests), add another Align
......@@ -408,6 +408,7 @@ void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
(safepoint_table_builder == kNoSafepointTable)
? handler_table_offset2
: safepoint_table_builder->safepoint_table_offset();
const int reloc_info_offset =
static_cast<int>(reloc_info_writer.pos() - buffer_->start());
CodeDesc::Initialize(desc, this, safepoint_table_offset,
......
......@@ -59,6 +59,7 @@ namespace v8 {
namespace internal {
class SafepointTableBuilder;
class MaglevSafepointTableBuilder;
// Utility functions
......@@ -424,9 +425,10 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// GetCode emits any pending (non-emitted) code and fills the descriptor desc.
static constexpr int kNoHandlerTable = 0;
static constexpr SafepointTableBuilder* kNoSafepointTable = nullptr;
static constexpr SafepointTableBuilderBase* kNoSafepointTable = nullptr;
void GetCode(Isolate* isolate, CodeDesc* desc,
SafepointTableBuilder* safepoint_table_builder,
SafepointTableBuilderBase* safepoint_table_builder,
int handler_table_offset);
// Convenience wrapper for code without safepoint or handler tables.
......@@ -2554,6 +2556,9 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
int WriteCodeComments();
void GetCode(Isolate* isolate, CodeDesc* desc, int safepoint_table_offset,
int handler_table_offset);
friend class EnsureSpace;
friend class RegExpMacroAssemblerX64;
......
......@@ -265,9 +265,16 @@ class ActivationsFinder : public ThreadVisitor {
code.marked_for_deoptimization()) {
codes_->erase(code);
// Obtain the trampoline to the deoptimizer call.
SafepointEntry safepoint =
code.GetSafepointEntry(isolate, it.frame()->pc());
int trampoline_pc = safepoint.trampoline_pc();
int trampoline_pc;
if (code.is_maglevved()) {
MaglevSafepointEntry safepoint =
code.GetMaglevSafepointEntry(isolate, it.frame()->pc());
trampoline_pc = safepoint.trampoline_pc();
} else {
SafepointEntry safepoint =
code.GetSafepointEntry(isolate, it.frame()->pc());
trampoline_pc = safepoint.trampoline_pc();
}
DCHECK_IMPLIES(code == topmost_, safe_to_deopt_);
static_assert(SafepointEntry::kNoTrampolinePC == -1);
CHECK_GE(trampoline_pc, 0);
......@@ -311,11 +318,18 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(NativeContext native_context) {
JSFunction function =
static_cast<OptimizedFrame*>(it.frame())->function();
TraceFoundActivation(isolate, function);
SafepointEntry safepoint =
code.GetSafepointEntry(isolate, it.frame()->pc());
bool safe_if_deopt_triggered;
if (code.is_maglevved()) {
MaglevSafepointEntry safepoint =
code.GetMaglevSafepointEntry(isolate, it.frame()->pc());
safe_if_deopt_triggered = safepoint.has_deoptimization_index();
} else {
SafepointEntry safepoint =
code.GetSafepointEntry(isolate, it.frame()->pc());
safe_if_deopt_triggered = safepoint.has_deoptimization_index();
}
// Deopt is checked when we are patching addresses on stack.
bool safe_if_deopt_triggered = safepoint.has_deoptimization_index();
bool is_builtin_code = code.kind() == CodeKind::BUILTIN;
DCHECK(topmost_optimized_code.is_null() || safe_if_deopt_triggered ||
is_builtin_code);
......
......@@ -20,7 +20,11 @@ class InnerPointerToCodeCache {
struct InnerPointerToCodeCacheEntry {
Address inner_pointer;
CodeLookupResult code;
SafepointEntry safepoint_entry;
union {
SafepointEntry safepoint_entry;
MaglevSafepointEntry maglev_safepoint_entry;
};
InnerPointerToCodeCacheEntry() : safepoint_entry() {}
};
static void FlushCallback(v8::Isolate* isolate, v8::GCType type,
......
This diff is collapsed.
......@@ -9,7 +9,7 @@
#include "src/codegen/label.h"
#include "src/codegen/machine-type.h"
#include "src/codegen/macro-assembler.h"
#include "src/codegen/safepoint-table.h"
#include "src/codegen/maglev-safepoint-table.h"
#include "src/common/globals.h"
#include "src/compiler/backend/instruction.h"
#include "src/compiler/js-heap-broker.h"
......@@ -33,7 +33,7 @@ class DeferredCodeInfo {
class MaglevCodeGenState {
public:
MaglevCodeGenState(MaglevCompilationInfo* compilation_info,
SafepointTableBuilder* safepoint_table_builder)
MaglevSafepointTableBuilder* safepoint_table_builder)
: compilation_info_(compilation_info),
safepoint_table_builder_(safepoint_table_builder),
masm_(isolate(), CodeObjectRequired::kNo) {}
......@@ -55,8 +55,6 @@ class MaglevCodeGenState {
const std::vector<LazyDeoptInfo*>& lazy_deopts() const {
return lazy_deopts_;
}
inline void DefineSafepointStackSlots(
SafepointTableBuilder::Safepoint& safepoint) const;
inline void DefineLazyDeoptPoint(LazyDeoptInfo* info);
compiler::NativeContextRef native_context() const {
......@@ -69,7 +67,7 @@ class MaglevCodeGenState {
}
MacroAssembler* masm() { return &masm_; }
int stack_slots() const { return untagged_slots_ + tagged_slots_; }
SafepointTableBuilder* safepoint_table_builder() const {
MaglevSafepointTableBuilder* safepoint_table_builder() const {
return safepoint_table_builder_;
}
MaglevCompilationInfo* compilation_info() const { return compilation_info_; }
......@@ -115,7 +113,7 @@ class MaglevCodeGenState {
}
MaglevCompilationInfo* const compilation_info_;
SafepointTableBuilder* const safepoint_table_builder_;
MaglevSafepointTableBuilder* const safepoint_table_builder_;
MacroAssembler masm_;
std::vector<DeferredCodeInfo*> deferred_code_;
......@@ -156,19 +154,10 @@ inline DoubleRegister ToDoubleRegister(const ValueLocation& location) {
return ToDoubleRegister(location.operand());
}
inline void MaglevCodeGenState::DefineSafepointStackSlots(
SafepointTableBuilder::Safepoint& safepoint) const {
for (int stack_slot = 0; stack_slot < tagged_slots_; stack_slot++) {
safepoint.DefineTaggedStackSlot(GetSafepointIndexForStackSlot(stack_slot));
}
}
inline void MaglevCodeGenState::DefineLazyDeoptPoint(LazyDeoptInfo* info) {
info->deopting_call_return_pc = masm()->pc_offset_for_safepoint();
PushLazyDeopt(info);
SafepointTableBuilder::Safepoint safepoint =
safepoint_table_builder()->DefineSafepoint(masm());
DefineSafepointStackSlots(safepoint);
safepoint_table_builder()->DefineSafepoint(masm());
}
} // namespace maglev
......
......@@ -104,11 +104,8 @@ class MaglevCodeGeneratingNodeProcessor {
Immediate(graph->untagged_stack_slots() * kSystemPointerSize));
}
// We don't emit proper safepoint data yet; instead, define a single
// safepoint at the end of the code object.
SafepointTableBuilder::Safepoint safepoint =
safepoint_table_builder()->DefineSafepoint(masm());
code_gen_state_->DefineSafepointStackSlots(safepoint);
// Define a single safepoint at the end of the code object.
safepoint_table_builder()->DefineSafepoint(masm());
}
void PostProcessGraph(MaglevCompilationInfo*, Graph*) {}
......@@ -334,7 +331,7 @@ class MaglevCodeGeneratingNodeProcessor {
MaglevGraphLabeller* graph_labeller() const {
return code_gen_state_->graph_labeller();
}
SafepointTableBuilder* safepoint_table_builder() const {
MaglevSafepointTableBuilder* safepoint_table_builder() const {
return code_gen_state_->safepoint_table_builder();
}
......@@ -355,7 +352,9 @@ class MaglevCodeGeneratorImpl final {
static constexpr int kOptimizedOutConstantIndex = 0;
MaglevCodeGeneratorImpl(MaglevCompilationInfo* compilation_info, Graph* graph)
: safepoint_table_builder_(compilation_info->zone()),
: safepoint_table_builder_(compilation_info->zone(),
graph->tagged_stack_slots(),
graph->untagged_stack_slots()),
translation_array_builder_(compilation_info->zone()),
code_gen_state_(compilation_info, safepoint_table_builder()),
processor_(compilation_info, &code_gen_state_),
......@@ -656,8 +655,7 @@ class MaglevCodeGeneratorImpl final {
// Final alignment before starting on the metadata section.
masm()->Align(Code::kMetadataAlignment);
safepoint_table_builder()->Emit(masm(),
stack_slot_count_with_fixed_frame());
safepoint_table_builder()->Emit(masm());
}
MaybeHandle<Code> BuildCodeObject() {
......@@ -757,7 +755,7 @@ class MaglevCodeGeneratorImpl final {
return code_gen_state_.compilation_info()->isolate();
}
MacroAssembler* masm() { return code_gen_state_.masm(); }
SafepointTableBuilder* safepoint_table_builder() {
MaglevSafepointTableBuilder* safepoint_table_builder() {
return &safepoint_table_builder_;
}
TranslationArrayBuilder* translation_array_builder() {
......@@ -773,7 +771,7 @@ class MaglevCodeGeneratorImpl final {
return *res.entry;
}
SafepointTableBuilder safepoint_table_builder_;
MaglevSafepointTableBuilder safepoint_table_builder_;
TranslationArrayBuilder translation_array_builder_;
MaglevCodeGenState code_gen_state_;
GraphProcessor<MaglevCodeGeneratingNodeProcessor> processor_;
......
......@@ -215,10 +215,18 @@ void Code::RelocateFromDesc(ByteArray reloc_info, Heap* heap,
}
SafepointEntry Code::GetSafepointEntry(Isolate* isolate, Address pc) {
DCHECK(!is_maglevved());
SafepointTable table(isolate, pc, *this);
return table.FindEntry(pc);
}
MaglevSafepointEntry Code::GetMaglevSafepointEntry(Isolate* isolate,
Address pc) {
DCHECK(is_maglevved());
MaglevSafepointTable table(isolate, pc, *this);
return table.FindEntry(pc);
}
Address Code::OffHeapInstructionStart(Isolate* isolate, Address pc) const {
DCHECK(is_off_heap_trampoline());
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
......@@ -591,8 +599,13 @@ void Code::Disassemble(const char* name, std::ostream& os, Isolate* isolate,
os << "\n";
if (uses_safepoint_table()) {
SafepointTable table(isolate, current_pc, *this);
table.Print(os);
if (is_maglevved()) {
MaglevSafepointTable table(isolate, current_pc, *this);
table.Print(os);
} else {
SafepointTable table(isolate, current_pc, *this);
table.Print(os);
}
os << "\n";
}
......
......@@ -8,6 +8,7 @@
#include "src/base/bit-field.h"
#include "src/builtins/builtins.h"
#include "src/codegen/handler-table.h"
#include "src/codegen/maglev-safepoint-table.h"
#include "src/deoptimizer/translation-array.h"
#include "src/objects/code-kind.h"
#include "src/objects/contexts.h"
......@@ -508,6 +509,9 @@ class Code : public HeapObject {
// Get the safepoint entry for the given pc.
SafepointEntry GetSafepointEntry(Isolate* isolate, Address pc);
// Get the maglev safepoint entry for the given pc.
MaglevSafepointEntry GetMaglevSafepointEntry(Isolate* isolate, Address pc);
// The entire code object including its header is copied verbatim to the
// snapshot so that it can be written in one, fast, memcpy during
// deserialization. The deserializer will overwrite some pointers, rather
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment