[arm64] Fix handling of handles in assembler

Previously, the handle's location was used as a proxy for the heap
object, i.e, we put the handle into the constant pool, to avoid the
need for GC visiting the constant pool entries during code generation.
The handle locations are replaced by the corresponding heap object
when the code is copied to the heap.

This CL changes the handling in the assembler: Instead of putting
in the handle location (which is a machine word) we put in a small
index number into a table. This will be useful for putting 32bit
constants into the constant pool.

This new approach also has the advantage that ordering the
constant pool entries by value produces a deterministic order
after this change.

Change-Id: Id47d56d487a0b64d1d1504a47937c8779ee02b13
Bug: v8:7703
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1648094
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62144}
This commit is contained in:
Sigurd Schneider 2019-06-13 14:01:37 +02:00 committed by Commit Bot
parent e79e81cdf5
commit 66412e0f55
7 changed files with 54 additions and 28 deletions

View File

@ -503,10 +503,24 @@ Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
}
}
Handle<HeapObject> Assembler::compressed_embedded_object_handle_at(Address pc) {
AssemblerBase::EmbeddedObjectIndex
Assembler::embedded_object_index_referenced_from(Address pc) {
Instruction* instr = reinterpret_cast<Instruction*>(pc);
CHECK(!instr->IsLdrLiteralX());
return GetCompressedEmbeddedObject(ReadUnalignedValue<int32_t>(pc));
CHECK(instr->IsLdrLiteralX());
STATIC_ASSERT(sizeof(EmbeddedObjectIndex) == sizeof(intptr_t));
return Memory<EmbeddedObjectIndex>(target_pointer_address_at(pc));
}
void Assembler::set_embedded_object_index_referenced_from(
Address pc, EmbeddedObjectIndex data) {
Instruction* instr = reinterpret_cast<Instruction*>(pc);
CHECK(instr->IsLdrLiteralX());
Memory<EmbeddedObjectIndex>(target_pointer_address_at(pc)) = data;
}
Handle<HeapObject> Assembler::target_object_handle_at(Address pc) {
return GetEmbeddedObject(
Assembler::embedded_object_index_referenced_from(pc));
}
Address Assembler::runtime_entry_at(Address pc) {
@ -637,8 +651,7 @@ HeapObject RelocInfo::target_object_no_host(Isolate* isolate) {
Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
if (IsFullEmbeddedObject(rmode_)) {
return Handle<HeapObject>(reinterpret_cast<Address*>(
Assembler::target_address_at(pc_, constant_pool_)));
return origin->target_object_handle_at(pc_);
} else {
DCHECK(IsCodeTarget(rmode_));
return origin->code_target_object_handle_at(pc_);

View File

@ -548,14 +548,16 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
case HeapObjectRequest::kHeapNumber: {
Handle<HeapObject> object = isolate->factory()->NewHeapNumber(
request.heap_number(), AllocationType::kOld);
set_target_address_at(pc, 0 /* unused */, object.address());
EmbeddedObjectIndex index = AddEmbeddedObject(object);
set_embedded_object_index_referenced_from(pc, index);
break;
}
case HeapObjectRequest::kStringConstant: {
const StringConstantBase* str = request.string();
CHECK_NOT_NULL(str);
set_target_address_at(pc, 0 /* unused */,
str->AllocateStringConstant(isolate).address());
EmbeddedObjectIndex index =
AddEmbeddedObject(str->AllocateStringConstant(isolate));
set_embedded_object_index_referenced_from(pc, index);
break;
}
}
@ -4484,6 +4486,10 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data,
RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode));
// These modes do not need an entry in the constant pool.
} else if (constant_pool_mode == NEEDS_POOL_ENTRY) {
if (RelocInfo::IsEmbeddedObjectMode(rmode)) {
Handle<HeapObject> handle(reinterpret_cast<Address*>(data));
data = AddEmbeddedObject(handle);
}
if (!constpool_.RecordEntry(data, rmode)) return;
}
// For modes that cannot use the constant pool, a different sequence of

View File

@ -314,8 +314,11 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Returns the handle for the code object called at 'pc'.
// This might need to be temporarily encoded as an offset into code_targets_.
inline Handle<Code> code_target_object_handle_at(Address pc);
inline Handle<HeapObject> compressed_embedded_object_handle_at(Address pc);
inline EmbeddedObjectIndex embedded_object_index_referenced_from(Address pc);
inline void set_embedded_object_index_referenced_from(
Address p, EmbeddedObjectIndex index);
// Returns the handle for the heap object referenced at 'pc'.
inline Handle<HeapObject> target_object_handle_at(Address pc);
// Returns the target address for a runtime function for the call encoded
// at 'pc'.

View File

@ -226,16 +226,17 @@ int AssemblerBase::AddCodeTarget(Handle<Code> target) {
}
}
int AssemblerBase::AddCompressedEmbeddedObject(Handle<HeapObject> object) {
int current = static_cast<int>(compressed_embedded_objects_.size());
compressed_embedded_objects_.push_back(object);
AssemblerBase::EmbeddedObjectIndex AssemblerBase::AddEmbeddedObject(
Handle<HeapObject> object) {
EmbeddedObjectIndex current = embedded_objects_.size();
embedded_objects_.push_back(object);
return current;
}
Handle<HeapObject> AssemblerBase::GetCompressedEmbeddedObject(
intptr_t index) const {
DCHECK_LT(static_cast<size_t>(index), compressed_embedded_objects_.size());
return compressed_embedded_objects_[index];
Handle<HeapObject> AssemblerBase::GetEmbeddedObject(
EmbeddedObjectIndex index) const {
DCHECK_LT(index, embedded_objects_.size());
return embedded_objects_[index];
}
Handle<Code> AssemblerBase::GetCodeTarget(intptr_t code_target_index) const {

View File

@ -272,8 +272,11 @@ class V8_EXPORT_PRIVATE AssemblerBase : public Malloced {
int AddCodeTarget(Handle<Code> target);
Handle<Code> GetCodeTarget(intptr_t code_target_index) const;
int AddCompressedEmbeddedObject(Handle<HeapObject> object);
Handle<HeapObject> GetCompressedEmbeddedObject(intptr_t index) const;
// Add 'object' to the {embedded_objects_} vector and return the index at
// which it is stored.
using EmbeddedObjectIndex = size_t;
EmbeddedObjectIndex AddEmbeddedObject(Handle<HeapObject> object);
Handle<HeapObject> GetEmbeddedObject(EmbeddedObjectIndex index) const;
// The buffer into which code and relocation info are generated.
std::unique_ptr<AssemblerBuffer> buffer_;
@ -321,12 +324,11 @@ class V8_EXPORT_PRIVATE AssemblerBase : public Malloced {
// the code handle in the vector instead.
std::vector<Handle<Code>> code_targets_;
// When pointer compression is enabled, we need to store indexes to this
// table in the code until we are ready to copy the code and embed the real
// object pointers. We don't need to do the same thing for non-compressed
// embedded objects, because we've got enough space (kPointerSize) in the
// code stream to just embed the address of the object handle.
std::vector<Handle<HeapObject>> compressed_embedded_objects_;
// If an assembler needs a small number to refer to a heap object handle
// (for example, because there are only 32bit available on a 64bit arch), the
// assembler adds the object into this vector using AddEmbeddedObject, and
// may then refer to the heap object using the handle's index in this vector.
std::vector<Handle<HeapObject>> embedded_objects_;
const AssemblerOptions options_;
uint64_t enabled_cpu_features_;

View File

@ -246,7 +246,7 @@ Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
}
Handle<HeapObject> Assembler::compressed_embedded_object_handle_at(Address pc) {
return GetCompressedEmbeddedObject(ReadUnalignedValue<int32_t>(pc));
return GetEmbeddedObject(ReadUnalignedValue<uint32_t>(pc));
}
Address Assembler::runtime_entry_at(Address pc) {

View File

@ -1468,8 +1468,9 @@ void TurboAssembler::Move(Register result, Handle<HeapObject> object,
}
}
if (RelocInfo::IsCompressedEmbeddedObject(rmode)) {
int compressed_embedded_object_index = AddCompressedEmbeddedObject(object);
movl(result, Immediate(compressed_embedded_object_index, rmode));
EmbeddedObjectIndex index = AddEmbeddedObject(object);
DCHECK(is_uint32(index));
movl(result, Immediate(static_cast<int>(index), rmode));
} else {
DCHECK(RelocInfo::IsFullEmbeddedObject(rmode));
movq(result, Immediate64(object.address(), rmode));