[ptr-compr] New RelocInfo for compressed pointers.
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. Bug: v8:7703 Change-Id: I03bfd84effa33c65cf9bcefa5df680ab7eace9dd Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1547661 Commit-Queue: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#61076}
This commit is contained in:
parent
fba1db8c03
commit
b5da9fcb51
@ -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_)) {
|
||||
|
@ -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;
|
||||
|
@ -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_;
|
||||
}
|
||||
|
||||
|
@ -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_)) {
|
||||
|
@ -280,7 +280,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;
|
||||
}
|
||||
|
||||
|
||||
@ -1697,14 +1697,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;
|
||||
|
@ -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
|
||||
|
@ -319,7 +319,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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_;
|
||||
|
@ -239,7 +239,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();
|
||||
@ -258,7 +259,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);
|
||||
|
@ -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()) {
|
||||
|
@ -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,
|
||||
|
@ -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)) {
|
||||
|
@ -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())));
|
||||
}
|
||||
@ -5810,8 +5811,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());
|
||||
}
|
||||
@ -5868,7 +5869,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;
|
||||
}
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
@ -1144,7 +1144,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);
|
||||
@ -2411,7 +2411,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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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->ptr()));
|
||||
@ -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();
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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) |
|
||||
|
@ -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) |
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) |
|
||||
|
@ -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());
|
||||
|
@ -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_,
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user