Commit 7ac3b55a authored by Victor Gomes's avatar Victor Gomes Committed by V8 LUCI CQ

[baseline][x64] Remove initial relocation when compiling on heap

This is still incomplete, but already able to pass all tests on x64.
Sparkplug (on pointer compression) only generates two relocation types:
FULL_EMBEDDED_OBJECT and RUNTIME_ENTRY.

Bug: v8:11872
Change-Id: I6aefbbc9690511a06b2a4a942c48fef85d536bef
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3009221
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75605}
parent 819c3ae2
...@@ -409,6 +409,10 @@ class V8_EXPORT_PRIVATE AssemblerBase : public Malloced { ...@@ -409,6 +409,10 @@ class V8_EXPORT_PRIVATE AssemblerBase : public Malloced {
CodeCommentsWriter code_comments_writer_; CodeCommentsWriter code_comments_writer_;
// Relocation information when code allocated directly on heap.
std::vector<std::pair<uint32_t, Address>> saved_handles_for_raw_object_ptr_;
std::vector<std::pair<uint32_t, uint32_t>> saved_offsets_for_runtime_entries_;
private: private:
// Before we copy code into the code space, we sometimes cannot encode // Before we copy code into the code space, we sometimes cannot encode
// call/jump code targets as we normally would, as the difference between the // call/jump code targets as we normally would, as the difference between the
......
...@@ -40,7 +40,14 @@ void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) { ...@@ -40,7 +40,14 @@ void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
DCHECK(RelocInfo::IsRuntimeEntry(rmode)); DCHECK(RelocInfo::IsRuntimeEntry(rmode));
DCHECK_NE(options().code_range_start, 0); DCHECK_NE(options().code_range_start, 0);
RecordRelocInfo(rmode); RecordRelocInfo(rmode);
emitl(static_cast<uint32_t>(entry - options().code_range_start)); uint32_t offset = static_cast<uint32_t>(entry - options().code_range_start);
if (IsOnHeap()) {
saved_offsets_for_runtime_entries_.push_back(
std::make_pair(pc_offset(), offset));
emitl(relative_target_offset(entry, reinterpret_cast<Address>(pc_)));
} else {
emitl(offset);
}
} }
void Assembler::emit(Immediate x) { void Assembler::emit(Immediate x) {
...@@ -53,6 +60,15 @@ void Assembler::emit(Immediate x) { ...@@ -53,6 +60,15 @@ void Assembler::emit(Immediate x) {
void Assembler::emit(Immediate64 x) { void Assembler::emit(Immediate64 x) {
if (!RelocInfo::IsNone(x.rmode_)) { if (!RelocInfo::IsNone(x.rmode_)) {
RecordRelocInfo(x.rmode_); RecordRelocInfo(x.rmode_);
if (x.rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT && IsOnHeap()) {
Address handle_address = reinterpret_cast<Address>(&x.value_);
Handle<HeapObject> object = Handle<HeapObject>::cast(
ReadUnalignedValue<Handle<Object>>(handle_address));
saved_handles_for_raw_object_ptr_.push_back(
std::make_pair(pc_offset(), x.value_));
emitq(static_cast<uint64_t>(object->ptr()));
return;
}
} }
emitq(static_cast<uint64_t>(x.value_)); emitq(static_cast<uint64_t>(x.value_));
} }
...@@ -234,13 +250,18 @@ Address Assembler::target_address_at(Address pc, Address constant_pool) { ...@@ -234,13 +250,18 @@ Address Assembler::target_address_at(Address pc, Address constant_pool) {
void Assembler::set_target_address_at(Address pc, Address constant_pool, void Assembler::set_target_address_at(Address pc, Address constant_pool,
Address target, Address target,
ICacheFlushMode icache_flush_mode) { ICacheFlushMode icache_flush_mode) {
DCHECK(is_int32(target - pc - 4)); WriteUnalignedValue(pc, relative_target_offset(target, pc));
WriteUnalignedValue(pc, static_cast<int32_t>(target - pc - 4));
if (icache_flush_mode != SKIP_ICACHE_FLUSH) { if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
FlushInstructionCache(pc, sizeof(int32_t)); FlushInstructionCache(pc, sizeof(int32_t));
} }
} }
int32_t Assembler::relative_target_offset(Address target, Address pc) {
Address offset = target - pc - 4;
DCHECK(is_int32(offset));
return static_cast<int32_t>(offset);
}
void Assembler::deserialization_set_target_internal_reference_at( void Assembler::deserialization_set_target_internal_reference_at(
Address pc, Address target, RelocInfo::Mode mode) { Address pc, Address target, RelocInfo::Mode mode) {
WriteUnalignedValue(pc, target); WriteUnalignedValue(pc, target);
......
...@@ -536,6 +536,8 @@ bool Assembler::is_optimizable_farjmp(int idx) { ...@@ -536,6 +536,8 @@ bool Assembler::is_optimizable_farjmp(int idx) {
void Assembler::GrowBuffer() { void Assembler::GrowBuffer() {
DCHECK(buffer_overflow()); DCHECK(buffer_overflow());
bool previously_on_heap = buffer_->IsOnHeap();
// Compute new buffer size. // Compute new buffer size.
DCHECK_EQ(buffer_start_, buffer_->start()); DCHECK_EQ(buffer_start_, buffer_->start());
int old_size = buffer_->size(); int old_size = buffer_->size();
...@@ -573,6 +575,17 @@ void Assembler::GrowBuffer() { ...@@ -573,6 +575,17 @@ void Assembler::GrowBuffer() {
WriteUnalignedValue(p, ReadUnalignedValue<intptr_t>(p) + pc_delta); WriteUnalignedValue(p, ReadUnalignedValue<intptr_t>(p) + pc_delta);
} }
// Patch on-heap references to handles.
if (previously_on_heap && !buffer_->IsOnHeap()) {
Address base = reinterpret_cast<Address>(buffer_->start());
for (auto p : saved_handles_for_raw_object_ptr_) {
WriteUnalignedValue(base + p.first, p.second);
}
for (auto p : saved_offsets_for_runtime_entries_) {
WriteUnalignedValue<uint32_t>(base + p.first, p.second);
}
}
DCHECK(!buffer_overflow()); DCHECK(!buffer_overflow());
} }
......
...@@ -438,6 +438,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase { ...@@ -438,6 +438,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
static inline void set_target_address_at( static inline void set_target_address_at(
Address pc, Address constant_pool, Address target, Address pc, Address constant_pool, Address target,
ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED); ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
static inline int32_t relative_target_offset(Address target, Address pc);
// This sets the branch destination (which is in the instruction on x64). // This sets the branch destination (which is in the instruction on x64).
// This is for calls and branches within generated code. // This is for calls and branches within generated code.
......
...@@ -296,7 +296,6 @@ void Factory::CodeBuilder::FinalizeOnHeapCode(Handle<Code> code, ...@@ -296,7 +296,6 @@ void Factory::CodeBuilder::FinalizeOnHeapCode(Handle<Code> code,
DCHECK(!heap->code_lo_space()->Contains(*code)); DCHECK(!heap->code_lo_space()->Contains(*code));
code->CopyRelocInfoToByteArray(reloc_info, code_desc_); code->CopyRelocInfoToByteArray(reloc_info, code_desc_);
code->RelocateFromDesc(reloc_info, heap, code_desc_);
int old_object_size = Code::SizeFor(code_desc_.origin->buffer_size()); int old_object_size = Code::SizeFor(code_desc_.origin->buffer_size());
int new_object_size = int new_object_size =
......
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