Reland "[ptr-compr] New RelocInfo for compressed pointers."

Failure addressed by not exposing the new test to the jitless environment.
(jgruber@ on TBR).

New enum RelocInfo::COMPRESSED_EMBEDDED_OBJECT created to support
compressed pointers in generated code. Enum name EMBEDDED_OBJECT
changed to FULL_EMBEDDED_OBJECT.

RelocInfo::[set_]target_object() abstract away the difference between
FULL_EMBEDDED_OBJECT and COMPRESSED_EMBEDDED_OBJECT.

Compressed embedded objects can only be created at this time on
x64 with pointer compression turned on. Arm64 constant pools don't
support compressed objects at this time.

NOPRESUBMIT=true

Bug: v8:7703
TBR: jgruber@chromium.org
Change-Id: Ifff53b041bab09b4b8c3e16085e5df4aa2b99f4f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1588461
Reviewed-by: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61104}
This commit is contained in:
Mike Stanton 2019-04-30 08:57:15 +02:00 committed by Commit Bot
parent da5b9a55ae
commit ed319e841c
38 changed files with 314 additions and 116 deletions

View File

@ -100,13 +100,17 @@ int RelocInfo::target_address_size() {
}
HeapObject RelocInfo::target_object() {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
DCHECK(IsCodeTarget(rmode_) || rmode_ == FULL_EMBEDDED_OBJECT);
return HeapObject::cast(
Object(Assembler::target_address_at(pc_, constant_pool_)));
}
HeapObject RelocInfo::target_object_no_host(Isolate* isolate) {
return target_object();
}
Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
if (IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT) {
if (IsCodeTarget(rmode_) || rmode_ == FULL_EMBEDDED_OBJECT) {
return Handle<HeapObject>(reinterpret_cast<Address*>(
Assembler::target_address_at(pc_, constant_pool_)));
}
@ -117,7 +121,7 @@ Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
void RelocInfo::set_target_object(Heap* heap, HeapObject target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
DCHECK(IsCodeTarget(rmode_) || rmode_ == FULL_EMBEDDED_OBJECT);
Assembler::set_target_address_at(pc_, constant_pool_, target->ptr(),
icache_flush_mode);
if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) {
@ -167,7 +171,7 @@ Address RelocInfo::target_off_heap_target() {
}
void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
DCHECK(IsFullEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_) || IsOffHeapTarget(rmode_));
if (IsInternalReference(rmode_)) {

View File

@ -351,7 +351,7 @@ uint32_t RelocInfo::wasm_call_tag() const {
Operand::Operand(Handle<HeapObject> handle) {
rm_ = no_reg;
value_.immediate = static_cast<intptr_t>(handle.address());
rmode_ = RelocInfo::EMBEDDED_OBJECT;
rmode_ = RelocInfo::FULL_EMBEDDED_OBJECT;
}
@ -387,14 +387,14 @@ Operand::Operand(Register rm, ShiftOp shift_op, Register rs) {
Operand Operand::EmbeddedNumber(double value) {
int32_t smi;
if (DoubleToSmiInteger(value, &smi)) return Operand(Smi::FromInt(smi));
Operand result(0, RelocInfo::EMBEDDED_OBJECT);
Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
result.is_heap_object_request_ = true;
result.value_.heap_object_request = HeapObjectRequest(value);
return result;
}
Operand Operand::EmbeddedStringConstant(const StringConstantBase* str) {
Operand result(0, RelocInfo::EMBEDDED_OBJECT);
Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
result.is_heap_object_request_ = true;
result.value_.heap_object_request = HeapObjectRequest(str);
return result;

View File

@ -156,8 +156,8 @@ class V8_EXPORT_PRIVATE Operand {
bool IsHeapObjectRequest() const {
DCHECK_IMPLIES(is_heap_object_request_, IsImmediate());
DCHECK_IMPLIES(is_heap_object_request_,
rmode_ == RelocInfo::EMBEDDED_OBJECT ||
rmode_ == RelocInfo::CODE_TARGET);
rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT ||
rmode_ == RelocInfo::CODE_TARGET);
return is_heap_object_request_;
}

View File

@ -297,7 +297,7 @@ Operand::Operand(Register reg, Extend extend, unsigned shift_amount)
bool Operand::IsHeapObjectRequest() const {
DCHECK_IMPLIES(heap_object_request_.has_value(), reg_.Is(NoReg));
DCHECK_IMPLIES(heap_object_request_.has_value(),
immediate_.rmode() == RelocInfo::EMBEDDED_OBJECT ||
immediate_.rmode() == RelocInfo::FULL_EMBEDDED_OBJECT ||
immediate_.rmode() == RelocInfo::CODE_TARGET);
return heap_object_request_.has_value();
}
@ -339,9 +339,9 @@ Operand Operand::ToExtendedRegister() const {
Immediate Operand::immediate_for_heap_object_request() const {
DCHECK((heap_object_request().kind() == HeapObjectRequest::kHeapNumber &&
immediate_.rmode() == RelocInfo::EMBEDDED_OBJECT) ||
immediate_.rmode() == RelocInfo::FULL_EMBEDDED_OBJECT) ||
(heap_object_request().kind() == HeapObjectRequest::kStringConstant &&
immediate_.rmode() == RelocInfo::EMBEDDED_OBJECT));
immediate_.rmode() == RelocInfo::FULL_EMBEDDED_OBJECT));
return immediate_;
}
@ -554,6 +554,12 @@ Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
}
}
Handle<HeapObject> Assembler::compressed_embedded_object_handle_at(Address pc) {
Instruction* instr = reinterpret_cast<Instruction*>(pc);
CHECK(!instr->IsLdrLiteralX());
return GetCompressedEmbeddedObject(ReadUnalignedValue<int32_t>(pc));
}
Address Assembler::runtime_entry_at(Address pc) {
Instruction* instr = reinterpret_cast<Instruction*>(pc);
if (instr->IsLdrLiteralX()) {
@ -686,13 +692,17 @@ Address RelocInfo::constant_pool_entry_address() {
}
HeapObject RelocInfo::target_object() {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
DCHECK(IsCodeTarget(rmode_) || IsFullEmbeddedObject(rmode_));
return HeapObject::cast(
Object(Assembler::target_address_at(pc_, constant_pool_)));
}
HeapObject RelocInfo::target_object_no_host(Isolate* isolate) {
return target_object();
}
Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
if (rmode_ == EMBEDDED_OBJECT) {
if (IsFullEmbeddedObject(rmode_)) {
return Handle<HeapObject>(reinterpret_cast<Address*>(
Assembler::target_address_at(pc_, constant_pool_)));
} else {
@ -704,7 +714,7 @@ Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
void RelocInfo::set_target_object(Heap* heap, HeapObject target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
DCHECK(IsCodeTarget(rmode_) || IsFullEmbeddedObject(rmode_));
Assembler::set_target_address_at(pc_, constant_pool_, target->ptr(),
icache_flush_mode);
if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) {
@ -755,7 +765,7 @@ Address RelocInfo::target_off_heap_target() {
}
void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
DCHECK(IsFullEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_) || IsOffHeapTarget(rmode_));
if (IsInternalReference(rmode_)) {

View File

@ -292,7 +292,7 @@ bool AreConsecutive(const VRegister& reg1, const VRegister& reg2,
void Immediate::InitializeHandle(Handle<HeapObject> handle) {
value_ = static_cast<intptr_t>(handle.address());
rmode_ = RelocInfo::EMBEDDED_OBJECT;
rmode_ = RelocInfo::FULL_EMBEDDED_OBJECT;
}
@ -1709,14 +1709,14 @@ Operand Operand::EmbeddedNumber(double number) {
if (DoubleToSmiInteger(number, &smi)) {
return Operand(Immediate(Smi::FromInt(smi)));
}
Operand result(0, RelocInfo::EMBEDDED_OBJECT);
Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
result.heap_object_request_.emplace(number);
DCHECK(result.IsHeapObjectRequest());
return result;
}
Operand Operand::EmbeddedStringConstant(const StringConstantBase* str) {
Operand result(0, RelocInfo::EMBEDDED_OBJECT);
Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
result.heap_object_request_.emplace(str);
DCHECK(result.IsHeapObjectRequest());
return result;

View File

@ -338,6 +338,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// 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);
// Returns the target address for a runtime function for the call encoded
// at 'pc'.
// Runtime entries can be temporarily encoded as the offset between the

View File

@ -291,7 +291,8 @@ void TurboAssembler::Mov(const Register& rd, const Operand& operand,
ExternalReference reference = bit_cast<ExternalReference>(addr);
IndirectLoadExternalReference(rd, reference);
return;
} else if (operand.ImmediateRMode() == RelocInfo::EMBEDDED_OBJECT) {
} else if (operand.ImmediateRMode() ==
RelocInfo::FULL_EMBEDDED_OBJECT) {
Handle<HeapObject> x(
reinterpret_cast<Address*>(operand.ImmediateValue()));
IndirectLoadConstant(rd, x);

View File

@ -258,18 +258,30 @@ int AssemblerBase::AddCodeTarget(Handle<Code> target) {
}
}
int AssemblerBase::AddCompressedEmbeddedObject(Handle<HeapObject> object) {
DCHECK(!options().v8_agnostic_code);
int current = static_cast<int>(compressed_embedded_objects_.size());
compressed_embedded_objects_.push_back(object);
return current;
}
Handle<HeapObject> AssemblerBase::GetCompressedEmbeddedObject(
intptr_t index) const {
DCHECK(!options().v8_agnostic_code);
DCHECK_LT(static_cast<size_t>(index), compressed_embedded_objects_.size());
return compressed_embedded_objects_[index];
}
Handle<Code> AssemblerBase::GetCodeTarget(intptr_t code_target_index) const {
DCHECK(!options().v8_agnostic_code);
DCHECK_LE(0, code_target_index);
DCHECK_LT(code_target_index, code_targets_.size());
DCHECK_LT(static_cast<size_t>(code_target_index), code_targets_.size());
return code_targets_[code_target_index];
}
void AssemblerBase::UpdateCodeTarget(intptr_t code_target_index,
Handle<Code> code) {
DCHECK(!options().v8_agnostic_code);
DCHECK_LE(0, code_target_index);
DCHECK_LT(code_target_index, code_targets_.size());
DCHECK_LT(static_cast<size_t>(code_target_index), code_targets_.size());
code_targets_[code_target_index] = code;
}

View File

@ -280,6 +280,9 @@ class V8_EXPORT_PRIVATE AssemblerBase : public Malloced {
// Update to the code target at {code_target_index} to {target}.
void UpdateCodeTarget(intptr_t code_target_index, Handle<Code> target);
int AddCompressedEmbeddedObject(Handle<HeapObject> object);
Handle<HeapObject> GetCompressedEmbeddedObject(intptr_t index) const;
// The buffer into which code and relocation info are generated.
std::unique_ptr<AssemblerBuffer> buffer_;
// Cached from {buffer_->start()}, for faster access.
@ -326,6 +329,13 @@ 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_;
const AssemblerOptions options_;
uint64_t enabled_cpu_features_;
bool emit_debug_code_;

View File

@ -240,7 +240,8 @@ void SetupIsolateDelegate::ReplacePlaceholders(Isolate* isolate) {
CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
static const int kRelocMask =
RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET);
HeapIterator iterator(isolate->heap());
for (HeapObject obj = iterator.next(); !obj.is_null();
@ -259,7 +260,7 @@ void SetupIsolateDelegate::ReplacePlaceholders(Isolate* isolate) {
rinfo->set_target_address(new_target->raw_instruction_start(),
UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
} else {
DCHECK(RelocInfo::IsEmbeddedObject(rinfo->rmode()));
DCHECK(RelocInfo::IsEmbeddedObjectMode(rinfo->rmode()));
Object object = rinfo->target_object();
if (!object->IsCode()) continue;
Code target = Code::cast(object);

View File

@ -1022,11 +1022,10 @@ void PipelineCompilationJob::RegisterWeakObjectsInOptimizedCode(
std::vector<Handle<Map>> retained_maps;
{
DisallowHeapAllocation no_gc;
int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
int const mode_mask = RelocInfo::EmbeddedObjectModeMask();
for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT &&
code->IsWeakObjectInOptimizedCode(it.rinfo()->target_object())) {
DCHECK(RelocInfo::IsEmbeddedObjectMode(it.rinfo()->rmode()));
if (code->IsWeakObjectInOptimizedCode(it.rinfo()->target_object())) {
Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()),
isolate);
if (object->IsMap()) {

View File

@ -220,12 +220,14 @@ static void PrintRelocInfo(StringBuilder* out, Isolate* isolate,
} else if (rmode == RelocInfo::DEOPT_ID) {
out->AddFormatted(" ;; debug: deopt index %d",
static_cast<int>(relocinfo->data()));
} else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
} else if (RelocInfo::IsEmbeddedObjectMode(rmode)) {
HeapStringAllocator allocator;
StringStream accumulator(&allocator);
relocinfo->target_object()->ShortPrint(&accumulator);
std::unique_ptr<char[]> obj_name = accumulator.ToCString();
out->AddFormatted(" ;; object: %s", obj_name.get());
const bool is_compressed = RelocInfo::IsCompressedEmbeddedObject(rmode);
out->AddFormatted(" ;; %sobject: %s",
is_compressed ? "(compressed) " : "", obj_name.get());
} else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
const char* reference_name =
ref_encoder ? ref_encoder->NameOfAddress(
@ -362,7 +364,13 @@ static int DecodeIt(Isolate* isolate, ExternalReferenceEncoder* ref_encoder,
const CodeReference& host = code;
Address constant_pool =
host.is_null() ? kNullAddress : host.constant_pool();
RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], Code(), constant_pool);
Code code_pointer;
if (!host.is_null() && host.is_js()) {
code_pointer = *host.as_js_code();
}
RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], code_pointer,
constant_pool);
bool first_reloc_info = (i == 0);
PrintRelocInfo(&out, isolate, ref_encoder, os, code, &relocinfo,

View File

@ -174,7 +174,7 @@ class ConcurrentMarkingVisitor final
ObjectSlot end) final {}
void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) final {
DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
DCHECK(RelocInfo::IsEmbeddedObjectMode(rinfo->rmode()));
HeapObject object = rinfo->target_object();
RecordRelocSlot(host, rinfo, object);
if (!marking_state_.IsBlackOrGrey(object)) {

View File

@ -3773,7 +3773,8 @@ class SlotVerifyingVisitor : public ObjectVisitor {
void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) override {
Object target = rinfo->target_object();
if (ShouldHaveBeenRecorded(host, MaybeObject::FromObject(target))) {
CHECK(InTypedSet(EMBEDDED_OBJECT_SLOT, rinfo->pc()) ||
CHECK(InTypedSet(FULL_EMBEDDED_OBJECT_SLOT, rinfo->pc()) ||
InTypedSet(COMPRESSED_EMBEDDED_OBJECT_SLOT, rinfo->pc()) ||
(rinfo->IsInConstantPool() &&
InTypedSet(OBJECT_SLOT, rinfo->constant_pool_entry_address())));
}
@ -5816,8 +5817,8 @@ Code Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) {
}
void Heap::WriteBarrierForCodeSlow(Code code) {
for (RelocIterator it(code, RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT));
!it.done(); it.next()) {
for (RelocIterator it(code, RelocInfo::EmbeddedObjectModeMask()); !it.done();
it.next()) {
GenerationalBarrierForCode(code, it.rinfo(), it.rinfo()->target_object());
MarkingBarrierForCode(code, it.rinfo(), it.rinfo()->target_object());
}
@ -5874,7 +5875,10 @@ void Heap::GenerationalBarrierForCodeSlow(Code host, RelocInfo* rinfo,
if (RelocInfo::IsCodeTargetMode(rmode)) {
slot_type = CODE_ENTRY_SLOT;
} else {
DCHECK(RelocInfo::IsEmbeddedObject(rmode));
// Constant pools don't currently support compressed objects, as
// their values are all pointer sized (though this could change
// therefore we have a DCHECK).
DCHECK(RelocInfo::IsFullEmbeddedObject(rmode));
slot_type = OBJECT_SLOT;
}
}

View File

@ -331,7 +331,7 @@ template <FixedArrayVisitationMode fixed_array_mode,
void MarkingVisitor<fixed_array_mode, retaining_path_mode,
MarkingState>::VisitEmbeddedPointer(Code host,
RelocInfo* rinfo) {
DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
DCHECK(RelocInfo::IsEmbeddedObjectMode(rinfo->rmode()));
HeapObject object = HeapObject::cast(rinfo->target_object());
collector_->RecordRelocSlot(host, rinfo, object);
if (!marking_state()->IsBlackOrGrey(object)) {

View File

@ -213,7 +213,7 @@ class FullMarkingVerifier : public MarkingVerifier {
}
void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) override {
DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
DCHECK(RelocInfo::IsEmbeddedObjectMode(rinfo->rmode()));
if (!host->IsWeakObject(rinfo->target_object())) {
HeapObject object = rinfo->target_object();
VerifyHeapObjectImpl(object);
@ -1145,7 +1145,7 @@ class RecordMigratedSlotVisitor : public ObjectVisitor {
inline void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) override {
DCHECK_EQ(host, rinfo->host());
DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
DCHECK(RelocInfo::IsEmbeddedObjectMode(rinfo->rmode()));
HeapObject object = HeapObject::cast(rinfo->target_object());
GenerationalBarrierForCode(host, rinfo, object);
collector_->RecordRelocSlot(host, rinfo, object);
@ -2412,7 +2412,9 @@ MarkCompactCollector::PrepareRecordRelocSlot(Code host, RelocInfo* rinfo,
if (RelocInfo::IsCodeTargetMode(rmode)) {
slot_type = CODE_ENTRY_SLOT;
} else {
DCHECK(RelocInfo::IsEmbeddedObject(rmode));
// Constant pools don't support compressed values at this time
// (this may change, therefore use a DCHECK).
DCHECK(RelocInfo::IsFullEmbeddedObject(rmode));
slot_type = OBJECT_SLOT;
}
}

View File

@ -1024,15 +1024,13 @@ void ObjectStatsCollectorImpl::RecordVirtualCodeDetails(Code code) {
ObjectStats::OPTIMIZED_CODE_LITERALS_TYPE);
}
}
int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
int const mode_mask = RelocInfo::EmbeddedObjectModeMask();
for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
Object target = it.rinfo()->target_object();
if (target->IsFixedArrayExact()) {
RecordVirtualObjectsForConstantPoolOrEmbeddedObjects(
code, HeapObject::cast(target), ObjectStats::EMBEDDED_OBJECT_TYPE);
}
DCHECK(RelocInfo::IsEmbeddedObjectMode(it.rinfo()->rmode()));
Object target = it.rinfo()->target_object();
if (target->IsFixedArrayExact()) {
RecordVirtualObjectsForConstantPoolOrEmbeddedObjects(
code, HeapObject::cast(target), ObjectStats::EMBEDDED_OBJECT_TYPE);
}
}
}

View File

@ -281,8 +281,12 @@ class UpdateTypedSlotHelper {
case CODE_ENTRY_SLOT: {
return UpdateCodeEntry(addr, callback);
}
case EMBEDDED_OBJECT_SLOT: {
RelocInfo rinfo(addr, RelocInfo::EMBEDDED_OBJECT, 0, Code());
case COMPRESSED_EMBEDDED_OBJECT_SLOT: {
RelocInfo rinfo(addr, RelocInfo::COMPRESSED_EMBEDDED_OBJECT, 0, Code());
return UpdateEmbeddedPointer(heap, &rinfo, callback);
}
case FULL_EMBEDDED_OBJECT_SLOT: {
RelocInfo rinfo(addr, RelocInfo::FULL_EMBEDDED_OBJECT, 0, Code());
return UpdateEmbeddedPointer(heap, &rinfo, callback);
}
case OBJECT_SLOT: {
@ -332,8 +336,8 @@ class UpdateTypedSlotHelper {
template <typename Callback>
static SlotCallbackResult UpdateEmbeddedPointer(Heap* heap, RelocInfo* rinfo,
Callback callback) {
DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
HeapObject old_target = rinfo->target_object();
DCHECK(RelocInfo::IsEmbeddedObjectMode(rinfo->rmode()));
HeapObject old_target = rinfo->target_object_no_host(heap->isolate());
HeapObject new_target = old_target;
SlotCallbackResult result = callback(FullMaybeObjectSlot(&new_target));
DCHECK(!HasWeakHeapObjectTag(new_target));
@ -347,8 +351,10 @@ class UpdateTypedSlotHelper {
inline SlotType SlotTypeForRelocInfoMode(RelocInfo::Mode rmode) {
if (RelocInfo::IsCodeTargetMode(rmode)) {
return CODE_TARGET_SLOT;
} else if (RelocInfo::IsEmbeddedObject(rmode)) {
return EMBEDDED_OBJECT_SLOT;
} else if (RelocInfo::IsFullEmbeddedObject(rmode)) {
return FULL_EMBEDDED_OBJECT_SLOT;
} else if (RelocInfo::IsCompressedEmbeddedObject(rmode)) {
return COMPRESSED_EMBEDDED_OBJECT_SLOT;
}
UNREACHABLE();
}

View File

@ -387,7 +387,8 @@ class SlotSet : public Malloced {
};
enum SlotType {
EMBEDDED_OBJECT_SLOT,
FULL_EMBEDDED_OBJECT_SLOT,
COMPRESSED_EMBEDDED_OBJECT_SLOT,
OBJECT_SLOT,
CODE_TARGET_SLOT,
CODE_ENTRY_SLOT,

View File

@ -90,19 +90,23 @@ int RelocInfo::target_address_size() {
}
HeapObject RelocInfo::target_object() {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
DCHECK(IsCodeTarget(rmode_) || rmode_ == FULL_EMBEDDED_OBJECT);
return HeapObject::cast(Object(ReadUnalignedValue<Address>(pc_)));
}
HeapObject RelocInfo::target_object_no_host(Isolate* isolate) {
return target_object();
}
Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
DCHECK(IsCodeTarget(rmode_) || rmode_ == FULL_EMBEDDED_OBJECT);
return Handle<HeapObject>::cast(ReadUnalignedValue<Handle<Object>>(pc_));
}
void RelocInfo::set_target_object(Heap* heap, HeapObject target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
DCHECK(IsCodeTarget(rmode_) || rmode_ == FULL_EMBEDDED_OBJECT);
WriteUnalignedValue(pc_, target->ptr());
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
FlushInstructionCache(pc_, sizeof(Address));
@ -157,7 +161,7 @@ Address RelocInfo::target_off_heap_target() {
}
void RelocInfo::WipeOut() {
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
if (IsFullEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_)) {
WriteUnalignedValue(pc_, kNullAddress);
} else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) ||
@ -182,7 +186,7 @@ void Assembler::emit_q(uint64_t x) {
}
void Assembler::emit(Handle<HeapObject> handle) {
emit(handle.address(), RelocInfo::EMBEDDED_OBJECT);
emit(handle.address(), RelocInfo::FULL_EMBEDDED_OBJECT);
}
void Assembler::emit(uint32_t x, RelocInfo::Mode rmode) {

View File

@ -63,14 +63,14 @@ namespace internal {
Immediate Immediate::EmbeddedNumber(double value) {
int32_t smi;
if (DoubleToSmiInteger(value, &smi)) return Immediate(Smi::FromInt(smi));
Immediate result(0, RelocInfo::EMBEDDED_OBJECT);
Immediate result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
result.is_heap_object_request_ = true;
result.value_.heap_object_request = HeapObjectRequest(value);
return result;
}
Immediate Immediate::EmbeddedStringConstant(const StringConstantBase* str) {
Immediate result(0, RelocInfo::EMBEDDED_OBJECT);
Immediate result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
result.is_heap_object_request_ = true;
result.value_.heap_object_request = HeapObjectRequest(str);
return result;
@ -3269,7 +3269,7 @@ void Assembler::emit_operand(int code, Operand adr) {
DCHECK(!options().isolate_independent_code ||
adr.rmode_ != RelocInfo::CODE_TARGET);
DCHECK(!options().isolate_independent_code ||
adr.rmode_ != RelocInfo::EMBEDDED_OBJECT);
adr.rmode_ != RelocInfo::FULL_EMBEDDED_OBJECT);
DCHECK(!options().isolate_independent_code ||
adr.rmode_ != RelocInfo::EXTERNAL_REFERENCE);

View File

@ -113,7 +113,7 @@ class Immediate {
inline explicit Immediate(const ExternalReference& ext)
: Immediate(ext.address(), RelocInfo::EXTERNAL_REFERENCE) {}
inline explicit Immediate(Handle<HeapObject> handle)
: Immediate(handle.address(), RelocInfo::EMBEDDED_OBJECT) {}
: Immediate(handle.address(), RelocInfo::FULL_EMBEDDED_OBJECT) {}
inline explicit Immediate(Smi value)
: Immediate(static_cast<intptr_t>(value.ptr())) {}
@ -126,7 +126,7 @@ class Immediate {
bool is_heap_object_request() const {
DCHECK_IMPLIES(is_heap_object_request_,
rmode_ == RelocInfo::EMBEDDED_OBJECT ||
rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT ||
rmode_ == RelocInfo::CODE_TARGET);
return is_heap_object_request_;
}
@ -142,7 +142,8 @@ class Immediate {
}
bool is_embedded_object() const {
return !is_heap_object_request() && rmode() == RelocInfo::EMBEDDED_OBJECT;
return !is_heap_object_request() &&
rmode() == RelocInfo::FULL_EMBEDDED_OBJECT;
}
Handle<HeapObject> embedded_object() const {

View File

@ -604,7 +604,8 @@ class Code::BodyDescriptor final : public BodyDescriptorBase {
static constexpr int kRelocModeMask =
RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |

View File

@ -63,12 +63,10 @@ int Code::ExecutableInstructionSize() const { return safepoint_table_offset(); }
void Code::ClearEmbeddedObjects(Heap* heap) {
HeapObject undefined = ReadOnlyRoots(heap).undefined_value();
int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
int mode_mask = RelocInfo::EmbeddedObjectModeMask();
for (RelocIterator it(*this, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
it.rinfo()->set_target_object(heap, undefined, SKIP_WRITE_BARRIER);
}
DCHECK(RelocInfo::IsEmbeddedObjectMode(it.rinfo()->rmode()));
it.rinfo()->set_target_object(heap, undefined, SKIP_WRITE_BARRIER);
}
set_embedded_objects_cleared(true);
}
@ -107,7 +105,7 @@ void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) {
const int mode_mask = RelocInfo::PostCodegenRelocationMask();
for (RelocIterator it(*this, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
if (RelocInfo::IsEmbeddedObjectMode(mode)) {
Handle<HeapObject> p = it.rinfo()->target_object_handle(origin);
it.rinfo()->set_target_object(heap, *p, UPDATE_WRITE_BARRIER,
SKIP_ICACHE_FLUSH);
@ -302,7 +300,8 @@ bool Code::IsIsolateIndependent(Isolate* isolate) {
STATIC_ASSERT(mode_mask ==
(RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |

View File

@ -149,7 +149,7 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) {
static_cast<uint32_t>(rinfo->pc() - reinterpret_cast<Address>(last_pc_));
// The two most common modes are given small tags, and usually fit in a byte.
if (rmode == RelocInfo::EMBEDDED_OBJECT) {
if (rmode == RelocInfo::FULL_EMBEDDED_OBJECT) {
WriteShortTaggedPC(pc_delta, kEmbeddedObjectTag);
} else if (rmode == RelocInfo::CODE_TARGET) {
WriteShortTaggedPC(pc_delta, kCodeTargetTag);
@ -233,7 +233,7 @@ void RelocIterator::next() {
int tag = AdvanceGetTag();
if (tag == kEmbeddedObjectTag) {
ReadShortTaggedPC();
if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
if (SetMode(RelocInfo::FULL_EMBEDDED_OBJECT)) return;
} else if (tag == kCodeTargetTag) {
ReadShortTaggedPC();
if (SetMode(RelocInfo::CODE_TARGET)) return;
@ -377,13 +377,14 @@ bool RelocInfo::HasTargetAddressAddress() const {
// non-intel platforms now that wasm code is no longer on the heap.
#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
static constexpr int kTargetAddressAddressModeMask =
ModeMask(CODE_TARGET) | ModeMask(EMBEDDED_OBJECT) |
ModeMask(EXTERNAL_REFERENCE) | ModeMask(OFF_HEAP_TARGET) |
ModeMask(RUNTIME_ENTRY) | ModeMask(WASM_CALL) | ModeMask(WASM_STUB_CALL);
ModeMask(CODE_TARGET) | ModeMask(FULL_EMBEDDED_OBJECT) |
ModeMask(COMPRESSED_EMBEDDED_OBJECT) | ModeMask(EXTERNAL_REFERENCE) |
ModeMask(OFF_HEAP_TARGET) | ModeMask(RUNTIME_ENTRY) |
ModeMask(WASM_CALL) | ModeMask(WASM_STUB_CALL);
#else
static constexpr int kTargetAddressAddressModeMask =
ModeMask(CODE_TARGET) | ModeMask(RELATIVE_CODE_TARGET) |
ModeMask(EMBEDDED_OBJECT) | ModeMask(EXTERNAL_REFERENCE) |
ModeMask(FULL_EMBEDDED_OBJECT) | ModeMask(EXTERNAL_REFERENCE) |
ModeMask(OFF_HEAP_TARGET) | ModeMask(RUNTIME_ENTRY) | ModeMask(WASM_CALL);
#endif
return (ModeMask(rmode_) & kTargetAddressAddressModeMask) != 0;
@ -404,8 +405,10 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
switch (rmode) {
case NONE:
return "no reloc";
case EMBEDDED_OBJECT:
return "embedded object";
case COMPRESSED_EMBEDDED_OBJECT:
return "compressed embedded object";
case FULL_EMBEDDED_OBJECT:
return "full embedded object";
case CODE_TARGET:
return "code target";
case RELATIVE_CODE_TARGET:
@ -450,8 +453,10 @@ void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT
} else if (rmode_ == DEOPT_REASON) {
os << " ("
<< DeoptimizeReasonToString(static_cast<DeoptimizeReason>(data_)) << ")";
} else if (rmode_ == EMBEDDED_OBJECT) {
} else if (rmode_ == FULL_EMBEDDED_OBJECT) {
os << " (" << Brief(target_object()) << ")";
} else if (rmode_ == COMPRESSED_EMBEDDED_OBJECT) {
os << " (" << Brief(target_object()) << " compressed)";
} else if (rmode_ == EXTERNAL_REFERENCE) {
if (isolate) {
ExternalReferenceEncoder ref_encoder(isolate);
@ -488,7 +493,8 @@ void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT
#ifdef VERIFY_HEAP
void RelocInfo::Verify(Isolate* isolate) {
switch (rmode_) {
case EMBEDDED_OBJECT:
case COMPRESSED_EMBEDDED_OBJECT:
case FULL_EMBEDDED_OBJECT:
Object::VerifyPointer(isolate, target_object());
break;
case CODE_TARGET:

View File

@ -56,7 +56,8 @@ class RelocInfo {
CODE_TARGET,
RELATIVE_CODE_TARGET, // LAST_CODE_TARGET_MODE
EMBEDDED_OBJECT, // LAST_GCED_ENUM
COMPRESSED_EMBEDDED_OBJECT,
FULL_EMBEDDED_OBJECT, // LAST_GCED_ENUM
WASM_CALL, // FIRST_SHAREABLE_RELOC_MODE
WASM_STUB_CALL,
@ -93,7 +94,9 @@ class RelocInfo {
LAST_CODE_TARGET_MODE = RELATIVE_CODE_TARGET,
FIRST_REAL_RELOC_MODE = CODE_TARGET,
LAST_REAL_RELOC_MODE = VENEER_POOL,
LAST_GCED_ENUM = EMBEDDED_OBJECT,
FIRST_EMBEDDED_OBJECT_RELOC_MODE = COMPRESSED_EMBEDDED_OBJECT,
LAST_EMBEDDED_OBJECT_RELOC_MODE = FULL_EMBEDDED_OBJECT,
LAST_GCED_ENUM = LAST_EMBEDDED_OBJECT_RELOC_MODE,
FIRST_SHAREABLE_RELOC_MODE = WASM_CALL,
};
@ -107,7 +110,10 @@ class RelocInfo {
rmode_(rmode),
data_(data),
host_(host),
constant_pool_(constant_pool) {}
constant_pool_(constant_pool) {
DCHECK_IMPLIES(!COMPRESS_POINTERS_BOOL,
rmode != COMPRESSED_EMBEDDED_OBJECT);
}
static constexpr bool IsRealRelocMode(Mode mode) {
return mode >= FIRST_REAL_RELOC_MODE && mode <= LAST_REAL_RELOC_MODE;
@ -129,8 +135,15 @@ class RelocInfo {
static constexpr bool IsRelativeCodeTarget(Mode mode) {
return mode == RELATIVE_CODE_TARGET;
}
static constexpr bool IsEmbeddedObject(Mode mode) {
return mode == EMBEDDED_OBJECT;
static constexpr bool IsFullEmbeddedObject(Mode mode) {
return mode == FULL_EMBEDDED_OBJECT;
}
static constexpr bool IsCompressedEmbeddedObject(Mode mode) {
return COMPRESS_POINTERS_BOOL && mode == COMPRESSED_EMBEDDED_OBJECT;
}
static constexpr bool IsEmbeddedObjectMode(Mode mode) {
return IsInRange(mode, FIRST_EMBEDDED_OBJECT_RELOC_MODE,
LAST_EMBEDDED_OBJECT_RELOC_MODE);
}
static constexpr bool IsRuntimeEntry(Mode mode) {
return mode == RUNTIME_ENTRY;
@ -223,7 +236,12 @@ class RelocInfo {
// can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
V8_INLINE Address target_address();
V8_INLINE HeapObject target_object();
// In GC operations, we don't have a host_ pointer. Retrieving a target
// for COMPRESSED_EMBEDDED_OBJECT mode requires an isolate.
V8_INLINE HeapObject target_object_no_host(Isolate* isolate);
V8_INLINE Handle<HeapObject> target_object_handle(Assembler* origin);
V8_INLINE void set_target_object(
Heap* heap, HeapObject target,
WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
@ -280,7 +298,7 @@ class RelocInfo {
template <typename ObjectVisitor>
void Visit(ObjectVisitor* visitor) {
Mode mode = rmode();
if (IsEmbeddedObject(mode)) {
if (IsEmbeddedObjectMode(mode)) {
visitor->VisitEmbeddedPointer(host(), this);
} else if (IsCodeTargetMode(mode)) {
visitor->VisitCodeTarget(host(), this);
@ -311,12 +329,18 @@ class RelocInfo {
static const int kApplyMask; // Modes affected by apply. Depends on arch.
static int EmbeddedObjectModeMask() {
return ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT);
}
// In addition to modes covered by the apply mask (which is applied at GC
// time, among others), this covers all modes that are relocated by
// Code::CopyFromNoFlush after code generation.
static int PostCodegenRelocationMask() {
return ModeMask(RelocInfo::CODE_TARGET) |
ModeMask(RelocInfo::EMBEDDED_OBJECT) |
ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) |
ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
ModeMask(RelocInfo::RUNTIME_ENTRY) |
ModeMask(RelocInfo::RELATIVE_CODE_TARGET) | kApplyMask;
}

View File

@ -857,7 +857,8 @@ void Serializer::ObjectSerializer::OutputCode(int size) {
// and wipe all pointers in the copy, which we then serialize.
Code off_heap_code = serializer_->CopyCode(on_heap_code);
int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |

View File

@ -136,6 +136,7 @@ void WriteVersion(Writer* writer) {
void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
DCHECK(rinfo->HasTargetAddressAddress());
DCHECK(!RelocInfo::IsCompressedEmbeddedObject(rinfo->rmode()));
WriteUnalignedValue(rinfo->target_address_address(), tag);
#elif V8_TARGET_ARCH_ARM64
Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
@ -161,6 +162,7 @@ void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
uint32_t GetWasmCalleeTag(RelocInfo* rinfo) {
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
DCHECK(!RelocInfo::IsCompressedEmbeddedObject(rinfo->rmode()));
return ReadUnalignedValue<uint32_t>(rinfo->target_address_address());
#elif V8_TARGET_ARCH_ARM64
Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());

View File

@ -266,6 +266,10 @@ Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
return GetCodeTarget(ReadUnalignedValue<int32_t>(pc));
}
Handle<HeapObject> Assembler::compressed_embedded_object_handle_at(Address pc) {
return GetCompressedEmbeddedObject(ReadUnalignedValue<int32_t>(pc));
}
Address Assembler::runtime_entry_at(Address pc) {
return ReadUnalignedValue<int32_t>(pc) + options().code_range_start;
}
@ -292,8 +296,9 @@ Address RelocInfo::target_address() {
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
IsWasmStubCall(rmode_) || IsEmbeddedObject(rmode_) ||
IsExternalReference(rmode_) || IsOffHeapTarget(rmode_));
IsWasmStubCall(rmode_) || IsFullEmbeddedObject(rmode_) ||
IsCompressedEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsOffHeapTarget(rmode_));
return pc_;
}
@ -307,21 +312,43 @@ int RelocInfo::target_address_size() {
if (IsCodedSpecially()) {
return Assembler::kSpecialTargetSize;
} else {
return kSystemPointerSize;
return IsCompressedEmbeddedObject(rmode_) ? kTaggedSize
: kSystemPointerSize;
}
}
HeapObject RelocInfo::target_object() {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObjectMode(rmode_));
if (IsCompressedEmbeddedObject(rmode_)) {
CHECK(!host_.is_null());
Object o = static_cast<Object>(DecompressTaggedPointer(
host_.ptr(), ReadUnalignedValue<Tagged_t>(pc_)));
return HeapObject::cast(o);
}
return HeapObject::cast(Object(ReadUnalignedValue<Address>(pc_)));
}
HeapObject RelocInfo::target_object_no_host(Isolate* isolate) {
DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObjectMode(rmode_));
if (IsCompressedEmbeddedObject(rmode_)) {
Address root = isolate->isolate_root();
Object o = static_cast<Object>(
DecompressTaggedPointer<OnHeapAddressKind::kIsolateRoot>(
root, ReadUnalignedValue<Tagged_t>(pc_)));
return HeapObject::cast(o);
}
return HeapObject::cast(Object(ReadUnalignedValue<Address>(pc_)));
}
Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
if (rmode_ == EMBEDDED_OBJECT) {
return Handle<HeapObject>::cast(ReadUnalignedValue<Handle<Object>>(pc_));
} else {
DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObjectMode(rmode_));
if (IsCodeTarget(rmode_)) {
return origin->code_target_object_handle_at(pc_);
} else {
if (IsCompressedEmbeddedObject(rmode_)) {
return origin->compressed_embedded_object_handle_at(pc_);
}
return Handle<HeapObject>::cast(ReadUnalignedValue<Handle<Object>>(pc_));
}
}
@ -353,8 +380,15 @@ Address RelocInfo::target_internal_reference_address() {
void RelocInfo::set_target_object(Heap* heap, HeapObject target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
WriteUnalignedValue(pc_, target->ptr());
DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObjectMode(rmode_));
if (IsCompressedEmbeddedObject(rmode_)) {
#ifdef V8_COMPRESS_POINTERS
Tagged_t tagged = CompressTagged(target->ptr());
WriteUnalignedValue(pc_, tagged);
#endif // V8_COMPRESS_POINTERS
} else {
WriteUnalignedValue(pc_, target->ptr());
}
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
FlushInstructionCache(pc_, sizeof(Address));
}
@ -383,9 +417,12 @@ Address RelocInfo::target_off_heap_target() {
}
void RelocInfo::WipeOut() {
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
if (IsFullEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_) || IsOffHeapTarget(rmode_)) {
WriteUnalignedValue(pc_, kNullAddress);
} else if (IsCompressedEmbeddedObject(rmode_)) {
Address smi_address = Smi::FromInt(0).ptr();
WriteUnalignedValue(pc_, CompressTagged(smi_address));
} else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
// Effectively write zero into the relocation.
Assembler::set_target_address_at(pc_, constant_pool_,

View File

@ -1818,7 +1818,7 @@ void Assembler::movq_heap_number(Register dst, double value) {
emit_rex(dst, kInt64Size);
emit(0xB8 | dst.low_bits());
RequestHeapObject(HeapObjectRequest(value));
emit(Immediate64(kNullAddress, RelocInfo::EMBEDDED_OBJECT));
emit(Immediate64(kNullAddress, RelocInfo::FULL_EMBEDDED_OBJECT));
}
void Assembler::movq_string(Register dst, const StringConstantBase* str) {
@ -1826,7 +1826,7 @@ void Assembler::movq_string(Register dst, const StringConstantBase* str) {
emit_rex(dst, kInt64Size);
emit(0xB8 | dst.low_bits());
RequestHeapObject(HeapObjectRequest(str));
emit(Immediate64(kNullAddress, RelocInfo::EMBEDDED_OBJECT));
emit(Immediate64(kNullAddress, RelocInfo::FULL_EMBEDDED_OBJECT));
}
// Loads the ip-relative location of the src label into the target location

View File

@ -384,6 +384,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
inline Handle<Code> code_target_object_handle_at(Address pc);
inline Handle<HeapObject> compressed_embedded_object_handle_at(Address pc);
inline Address runtime_entry_at(Address pc);
// Number of bytes taken up by the branch target in the code.

View File

@ -1477,7 +1477,13 @@ void TurboAssembler::Move(Register result, Handle<HeapObject> object,
return;
}
}
movq(result, Immediate64(object.address(), rmode));
if (RelocInfo::IsCompressedEmbeddedObject(rmode)) {
int compressed_embedded_object_index = AddCompressedEmbeddedObject(object);
movl(result, Immediate(compressed_embedded_object_index, rmode));
} else {
DCHECK(RelocInfo::IsFullEmbeddedObject(rmode));
movq(result, Immediate64(object.address(), rmode));
}
}
void TurboAssembler::Move(Operand dst, Handle<HeapObject> object,

View File

@ -308,9 +308,9 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void Move(Register target, Register source);
void Move(Register dst, Handle<HeapObject> source,
RelocInfo::Mode rmode = RelocInfo::EMBEDDED_OBJECT);
RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT);
void Move(Operand dst, Handle<HeapObject> source,
RelocInfo::Mode rmode = RelocInfo::EMBEDDED_OBJECT);
RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT);
// Loads a pointer into a register with a relocation mode.
void Move(Register dst, Address ptr, RelocInfo::Mode rmode) {
@ -323,8 +323,9 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
// Move src0 to dst0 and src1 to dst1, handling possible overlaps.
void MovePair(Register dst0, Register src0, Register dst1, Register src1);
void MoveStringConstant(Register result, const StringConstantBase* string,
RelocInfo::Mode rmode = RelocInfo::EMBEDDED_OBJECT);
void MoveStringConstant(
Register result, const StringConstantBase* string,
RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT);
// Convert smi to word-size sign-extended value.
void SmiUntag(Register dst, Register src);

View File

@ -551,6 +551,7 @@
'test-run-unwinding-info/*': [SKIP],
'test-run-variables/*': [SKIP],
'test-torque/*': [SKIP],
'test-macro-assembler-x64/EmbeddedObj': [SKIP],
# Field representation tracking is disabled in jitless mode.
'test-field-type-tracking/*': [SKIP],

View File

@ -172,7 +172,7 @@ static void CheckNumber(Isolate* isolate, double value, const char* string) {
}
void CheckEmbeddedObjectsAreEqual(Handle<Code> lhs, Handle<Code> rhs) {
int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
int mode_mask = RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT);
RelocIterator lhs_it(*lhs, mode_mask);
RelocIterator rhs_it(*rhs, mode_mask);
while (!lhs_it.done() && !rhs_it.done()) {

View File

@ -6448,7 +6448,7 @@ namespace {
void LoadLiteral(MacroAssembler* masm, Register reg, uint64_t imm) {
// Since we do not allow non-relocatable entries in the literal pool, we need
// to fake a relocation mode that is not NONE here.
masm->Ldr(reg, Immediate(imm, RelocInfo::EMBEDDED_OBJECT));
masm->Ldr(reg, Immediate(imm, RelocInfo::FULL_EMBEDDED_OBJECT));
}
} // namespace

View File

@ -34,7 +34,9 @@
#include "src/macro-assembler.h"
#include "src/objects-inl.h"
#include "src/objects/smi.h"
#include "src/ostreams.h"
#include "src/simulator.h"
#include "src/x64/assembler-x64-inl.h"
#include "test/cctest/cctest.h"
#include "test/common/assembler-tester.h"
@ -423,6 +425,60 @@ void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
}
}
TEST(EmbeddedObj) {
#ifdef V8_COMPRESS_POINTERS
FLAG_always_compact = true;
v8::V8::Initialize();
Isolate* isolate = CcTest::i_isolate();
HandleScope handles(isolate);
auto buffer = AllocateAssemblerBuffer();
MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
buffer->CreateView());
MacroAssembler* masm = &assembler;
EntryCode(masm);
Label exit;
Handle<HeapObject> old_array = isolate->factory()->NewFixedArray(2000);
Handle<HeapObject> my_array = isolate->factory()->NewFixedArray(1000);
__ Move(rcx, my_array, RelocInfo::COMPRESSED_EMBEDDED_OBJECT);
__ Move(rax, old_array, RelocInfo::FULL_EMBEDDED_OBJECT);
__ bind(&exit);
ExitCode(masm);
__ ret(0);
CodeDesc desc;
masm->GetCode(isolate, &desc);
Handle<Code> code =
isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
#ifdef OBJECT_PRINT
StdoutStream os;
code->Print(os);
#endif
typedef int64_t (*myF0)();
myF0 f = FUNCTION_CAST<myF0>(code->entry());
Object result = static_cast<Object>(f());
CHECK_EQ(old_array->ptr(), result.ptr());
// Collect garbage to ensure reloc info can be walked by the heap.
CcTest::CollectAllGarbage();
CcTest::CollectAllGarbage();
CcTest::CollectAllGarbage();
// Test the user-facing reloc interface.
const int mode_mask = RelocInfo::EmbeddedObjectModeMask();
for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (RelocInfo::IsCompressedEmbeddedObject(mode)) {
CHECK_EQ(*my_array, it.rinfo()->target_object());
} else {
CHECK(RelocInfo::IsFullEmbeddedObject(mode));
CHECK_EQ(*old_array, it.rinfo()->target_object());
}
}
#endif // V8_COMPRESS_POINTERS
}
TEST(SmiIndex) {
Isolate* isolate = CcTest::i_isolate();
HandleScope handles(isolate);

View File

@ -216,8 +216,8 @@ TEST(TypedSlotSet, Merge) {
TypedSlotSet set0(0), set1(0);
static const uint32_t kEntries = 10000;
for (uint32_t i = 0; i < kEntries; i++) {
set0.Insert(EMBEDDED_OBJECT_SLOT, 2 * i);
set1.Insert(EMBEDDED_OBJECT_SLOT, 2 * i + 1);
set0.Insert(FULL_EMBEDDED_OBJECT_SLOT, 2 * i);
set1.Insert(FULL_EMBEDDED_OBJECT_SLOT, 2 * i + 1);
}
uint32_t count = 0;
set0.Merge(&set1);