Commit 7c149afb authored by yangguo's avatar yangguo Committed by Commit bot

Serializer: serialize internal references via object visitor.

Review URL: https://codereview.chromium.org/1005183006

Cr-Commit-Position: refs/heads/master@{#27275}
parent 8c0d2897
......@@ -121,7 +121,7 @@ Address RelocInfo::target_address_address() {
if (FLAG_enable_ool_constant_pool ||
Assembler::IsMovW(Memory::int32_at(pc_))) {
// We return the PC for ool constant pool since this function is used by the
// serializerer and expects the address to reside within the code object.
// serializer and expects the address to reside within the code object.
return reinterpret_cast<Address>(pc_);
} else {
DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)));
......@@ -196,9 +196,9 @@ Address RelocInfo::target_internal_reference() {
}
void RelocInfo::set_target_internal_reference(Address target) {
Address RelocInfo::target_internal_reference_address() {
DCHECK(rmode_ == INTERNAL_REFERENCE);
Memory::Address_at(pc_) = target;
return reinterpret_cast<Address>(pc_);
}
......@@ -310,11 +310,14 @@ Object** RelocInfo::call_object_address() {
void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) ||
IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) ||
IsExternalReference(rmode_));
Assembler::set_target_address_at(pc_, host_, NULL);
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_));
if (IsInternalReference(rmode_)) {
Memory::Address_at(pc_) = NULL;
} else {
Assembler::set_target_address_at(pc_, host_, NULL);
}
}
......@@ -345,6 +348,8 @@ void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
visitor->VisitCell(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
visitor->VisitExternalReference(this);
} else if (mode == RelocInfo::INTERNAL_REFERENCE) {
visitor->VisitInternalReference(this);
} else if (RelocInfo::IsCodeAgeSequence(mode)) {
visitor->VisitCodeAgeSequence(this);
} else if (((RelocInfo::IsJSReturn(mode) &&
......@@ -370,6 +375,8 @@ void RelocInfo::Visit(Heap* heap) {
StaticVisitor::VisitCell(heap, this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(this);
} else if (mode == RelocInfo::INTERNAL_REFERENCE) {
StaticVisitor::VisitInternalReference(this);
} else if (RelocInfo::IsCodeAgeSequence(mode)) {
StaticVisitor::VisitCodeAgeSequence(heap, this);
} else if (heap->isolate()->debug()->has_break_points() &&
......@@ -546,6 +553,12 @@ void Assembler::deserialization_set_special_target_at(
}
void Assembler::deserialization_set_target_internal_reference_at(
Address pc, Address target) {
Memory::Address_at(pc) = target;
}
bool Assembler::is_constant_pool_load(Address pc) {
if (CpuFeatures::IsSupported(ARMv7)) {
return !Assembler::IsMovW(Memory::int32_at(pc)) ||
......
......@@ -795,6 +795,10 @@ class Assembler : public AssemblerBase {
inline static void deserialization_set_special_target_at(
Address constant_pool_entry, Code* code, Address target);
// This sets the internal reference at the pc.
inline static void deserialization_set_target_internal_reference_at(
Address pc, Address target);
// Here we are patching the address in the constant pool, not the actual call
// instruction. The address in the constant pool is the same size as a
// pointer.
......
......@@ -654,6 +654,12 @@ void Assembler::deserialization_set_special_target_at(
}
void Assembler::deserialization_set_target_internal_reference_at(
Address pc, Address target) {
UNIMPLEMENTED(); // ARM64 does not use internal references.
}
void Assembler::set_target_address_at(Address pc,
ConstantPoolArray* constant_pool,
Address target,
......@@ -741,13 +747,15 @@ Address RelocInfo::target_external_reference() {
Address RelocInfo::target_internal_reference() {
DCHECK(rmode_ == INTERNAL_REFERENCE);
return Memory::Address_at(pc_);
UNIMPLEMENTED(); // ARM64 does not use internal references.
return NULL;
}
void RelocInfo::set_target_internal_reference(Address target) {
Address RelocInfo::target_internal_reference_address() {
DCHECK(rmode_ == INTERNAL_REFERENCE);
Memory::Address_at(pc_) = target;
UNIMPLEMENTED(); // ARM64 does not use internal references.
return NULL;
}
......@@ -838,11 +846,14 @@ void RelocInfo::set_call_address(Address target) {
void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) ||
IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) ||
IsExternalReference(rmode_));
Assembler::set_target_address_at(pc_, host_, NULL);
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_));
if (IsInternalReference(rmode_)) {
UNIMPLEMENTED(); // ARM64 does not use internal references.
} else {
Assembler::set_target_address_at(pc_, host_, NULL);
}
}
......@@ -874,6 +885,8 @@ void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
visitor->VisitCell(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
visitor->VisitExternalReference(this);
} else if (mode == RelocInfo::INTERNAL_REFERENCE) {
UNIMPLEMENTED(); // ARM64 does not use internal references.
} else if (((RelocInfo::IsJSReturn(mode) &&
IsPatchedReturnSequence()) ||
(RelocInfo::IsDebugBreakSlot(mode) &&
......@@ -897,6 +910,8 @@ void RelocInfo::Visit(Heap* heap) {
StaticVisitor::VisitCell(heap, this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(this);
} else if (mode == RelocInfo::INTERNAL_REFERENCE) {
UNIMPLEMENTED(); // ARM64 does not use internal references.
} else if (heap->isolate()->debug()->has_break_points() &&
((RelocInfo::IsJSReturn(mode) &&
IsPatchedReturnSequence()) ||
......
......@@ -901,6 +901,10 @@ class Assembler : public AssemblerBase {
inline static void deserialization_set_special_target_at(
Address constant_pool_entry, Code* code, Address target);
// This sets the internal reference at the pc.
inline static void deserialization_set_target_internal_reference_at(
Address pc, Address target);
// All addresses in the constant pool are the same size as pointers.
static const int kSpecialTargetSize = kPointerSize;
......
......@@ -911,14 +911,21 @@ void RelocInfo::Verify(Isolate* isolate) {
CHECK(code->address() == HeapObject::cast(found)->address());
break;
}
case INTERNAL_REFERENCE:
case INTERNAL_REFERENCE_ENCODED: {
Address target = target_internal_reference();
Address pc = target_internal_reference_address();
Code* code = Code::cast(isolate->FindCodeObject(pc));
CHECK(target >= code->instruction_start());
CHECK(target <= code->instruction_end());
break;
}
case RUNTIME_ENTRY:
case JS_RETURN:
case COMMENT:
case POSITION:
case STATEMENT_POSITION:
case EXTERNAL_REFERENCE:
case INTERNAL_REFERENCE:
case INTERNAL_REFERENCE_ENCODED:
case DEOPT_REASON:
case CONST_POOL:
case VENEER_POOL:
......
......@@ -581,10 +581,13 @@ class RelocInfo {
// applies to; can only be called if rmode_ is EXTERNAL_REFERENCE.
INLINE(Address target_external_reference());
// Read/modify the reference in the instruction this relocation
// Read the reference in the instruction this relocation
// applies to; can only be called if rmode_ is INTERNAL_REFERENCE.
INLINE(Address target_internal_reference());
INLINE(void set_target_internal_reference(Address target));
// Return the reference address this relocation applies to;
// can only be called if rmode_ is INTERNAL_REFERENCE.
INLINE(Address target_internal_reference_address());
// Read/modify the address of a call instruction. This is used to relocate
// the break points where straight-line code is patched with a call
......
......@@ -842,6 +842,8 @@ void Code::CodeIterateBody(ObjectVisitor* v) {
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::CELL) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
......@@ -869,6 +871,8 @@ void Code::CodeIterateBody(Heap* heap) {
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::CELL) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
......
......@@ -413,6 +413,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
INLINE(static void VisitCodeTarget(Heap* heap, RelocInfo* rinfo));
INLINE(static void VisitCodeAgeSequence(Heap* heap, RelocInfo* rinfo));
INLINE(static void VisitExternalReference(RelocInfo* rinfo)) {}
INLINE(static void VisitInternalReference(RelocInfo* rinfo)) {}
INLINE(static void VisitRuntimeEntry(RelocInfo* rinfo)) {}
// Skip the weak next code link in a code object.
INLINE(static void VisitNextCodeLink(Heap* heap, Object** slot)) {}
......
......@@ -166,9 +166,9 @@ Address RelocInfo::target_internal_reference() {
}
void RelocInfo::set_target_internal_reference(Address target) {
Address RelocInfo::target_internal_reference_address() {
DCHECK(rmode_ == INTERNAL_REFERENCE);
Memory::Address_at(pc_) = target;
return reinterpret_cast<Address>(pc_);
}
......@@ -280,7 +280,8 @@ Object** RelocInfo::call_object_address() {
void RelocInfo::WipeOut() {
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_)) {
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_)) {
Memory::Address_at(pc_) = NULL;
} else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
// Effectively write zero into the relocation.
......@@ -312,7 +313,8 @@ void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
visitor->VisitCell(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
visitor->VisitExternalReference(this);
CpuFeatures::FlushICache(pc_, sizeof(Address));
} else if (mode == RelocInfo::INTERNAL_REFERENCE) {
visitor->VisitInternalReference(this);
} else if (RelocInfo::IsCodeAgeSequence(mode)) {
visitor->VisitCodeAgeSequence(this);
} else if (((RelocInfo::IsJSReturn(mode) &&
......@@ -339,7 +341,8 @@ void RelocInfo::Visit(Heap* heap) {
StaticVisitor::VisitCell(heap, this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(this);
CpuFeatures::FlushICache(pc_, sizeof(Address));
} else if (mode == RelocInfo::INTERNAL_REFERENCE) {
StaticVisitor::VisitInternalReference(this);
} else if (RelocInfo::IsCodeAgeSequence(mode)) {
StaticVisitor::VisitCodeAgeSequence(heap, this);
} else if (heap->isolate()->debug()->has_break_points() &&
......@@ -528,6 +531,12 @@ void Assembler::emit_near_disp(Label* L) {
}
void Assembler::deserialization_set_target_internal_reference_at(
Address pc, Address target) {
Memory::Address_at(pc) = target;
}
void Operand::set_modrm(int mod, Register rm) {
DCHECK((mod & -4) == 0);
buf_[0] = mod << 6 | rm.code();
......
......@@ -547,6 +547,10 @@ class Assembler : public AssemblerBase {
set_target_address_at(instruction_payload, code, target);
}
// This sets the internal reference at the pc.
inline static void deserialization_set_target_internal_reference_at(
Address pc, Address target);
static const int kSpecialTargetSize = kPointerSize;
// Distance between the address of the code target in the call instruction
......
......@@ -10946,9 +10946,12 @@ class ObjectVisitor BASE_EMBEDDED {
// Visits an external reference embedded into a code object.
virtual void VisitExternalReference(RelocInfo* rinfo);
// Visits an external reference. The value may be modified on return.
// Visits an external reference.
virtual void VisitExternalReference(Address* p) {}
// Visits an (encoded) internal reference.
virtual void VisitInternalReference(RelocInfo* rinfo) {}
// Visits a handle that has an embedder-assigned class ID.
virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
......
......@@ -780,25 +780,13 @@ void Deserializer::ReadObject(int space_number, Object** write_back) {
#ifdef DEBUG
if (obj->IsCode()) {
DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE);
#ifdef VERIFY_HEAP
obj->ObjectVerify();
#endif // VERIFY_HEAP
} else {
DCHECK(space_number != CODE_SPACE);
}
#endif
if (obj->IsCode()) {
// Turn internal references encoded as offsets back to absolute addresses.
Code* code = Code::cast(obj);
Address entry = code->entry();
int mode_mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
RelocInfo* rinfo = it.rinfo();
intptr_t offset =
reinterpret_cast<intptr_t>(rinfo->target_internal_reference());
DCHECK(0 <= offset && offset <= code->instruction_size());
rinfo->set_target_internal_reference(entry + offset);
}
}
#endif // DEBUG
}
......@@ -1172,6 +1160,21 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
break;
}
case kInternalReference: {
// Internal reference address is not encoded via skip, but by offset
// from code entry.
int pc_offset = source_.GetInt();
int target_offset = source_.GetInt();
Code* code =
Code::cast(HeapObject::FromAddress(current_object_address));
DCHECK(0 <= pc_offset && pc_offset <= code->instruction_size());
DCHECK(0 <= target_offset && target_offset <= code->instruction_size());
Address pc = code->entry() + pc_offset;
Address target = code->entry() + target_offset;
Assembler::deserialization_set_target_internal_reference_at(pc, target);
break;
}
case kNativesStringResource: {
DCHECK(!isolate_->heap()->deserialization_complete());
int index = source_.Get();
......@@ -1859,6 +1862,28 @@ void Serializer::ObjectSerializer::VisitExternalReference(RelocInfo* rinfo) {
}
void Serializer::ObjectSerializer::VisitInternalReference(RelocInfo* rinfo) {
// We can only reference to internal references of code that has been output.
DCHECK(is_code_object_ && code_has_been_output_);
// We do not use skip from last patched pc to find the pc to patch, since
// target_address_address may not return addresses in ascending order when
// used for internal references. External references may be stored at the
// end of the code in the constant pool, whereas internal references are
// inline. That would cause the skip to be negative. Instead, we store the
// offset from code entry.
Address entry = Code::cast(object_)->entry();
intptr_t pc_offset = rinfo->target_internal_reference_address() - entry;
intptr_t target_offset = rinfo->target_internal_reference() - entry;
DCHECK(0 <= pc_offset &&
pc_offset <= Code::cast(object_)->instruction_size());
DCHECK(0 <= target_offset &&
target_offset <= Code::cast(object_)->instruction_size());
sink_->Put(kInternalReference, "InternalRef");
sink_->PutInt(static_cast<uintptr_t>(pc_offset), "internal ref address");
sink_->PutInt(static_cast<uintptr_t>(target_offset), "internal ref value");
}
void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) {
int skip = OutputRawData(rinfo->target_address_address(),
kCanReturnSkipInsteadOfSkipping);
......@@ -1934,7 +1959,6 @@ Address Serializer::ObjectSerializer::PrepareCode() {
Code* code = serializer_->CopyCode(original);
// Code age headers are not serializable.
code->MakeYoung(serializer_->isolate());
Address entry = original->entry();
int mode_mask = RelocInfo::kCodeTargetMask |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
......@@ -1943,15 +1967,7 @@ Address Serializer::ObjectSerializer::PrepareCode() {
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
RelocInfo* rinfo = it.rinfo();
RelocInfo::Mode rmode = rinfo->rmode();
if (RelocInfo::IsInternalReference(rmode) ||
RelocInfo::IsInternalReferenceEncoded(rmode)) {
// Convert internal references to relative offsets.
Address target = rinfo->target_internal_reference();
intptr_t offset = target - entry;
DCHECK(0 <= offset && offset <= original->instruction_size());
rinfo->set_target_internal_reference(reinterpret_cast<Address>(offset));
} else if (!(FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool())) {
if (!(FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool())) {
rinfo->WipeOut();
}
}
......@@ -1974,14 +1990,13 @@ int Serializer::ObjectSerializer::OutputRawData(
// locations in a non-ascending order. Luckily that doesn't happen.
DCHECK(to_skip >= 0);
bool outputting_code = false;
if (to_skip != 0 && code_object_ && !code_has_been_output_) {
if (to_skip != 0 && is_code_object_ && !code_has_been_output_) {
// Output the code all at once and fix later.
bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_;
outputting_code = true;
code_has_been_output_ = true;
}
if (bytes_to_output != 0 &&
(!code_object_ || outputting_code)) {
if (bytes_to_output != 0 && (!is_code_object_ || outputting_code)) {
#define RAW_CASE(index) \
if (!outputting_code && bytes_to_output == index * kPointerSize && \
index * kPointerSize == to_skip) { \
......@@ -1996,9 +2011,9 @@ int Serializer::ObjectSerializer::OutputRawData(
sink_->PutInt(bytes_to_output, "length");
}
if (code_object_) object_start = PrepareCode();
if (is_code_object_) object_start = PrepareCode();
const char* description = code_object_ ? "Code" : "Byte";
const char* description = is_code_object_ ? "Code" : "Byte";
#ifdef MEMORY_SANITIZER
// Object sizes are usually rounded up with uninitialized padding space.
MSAN_MEMORY_IS_INITIALIZED(object_start + base, bytes_to_output);
......@@ -2322,7 +2337,6 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(),
*result, NULL, name);
}
return scope.CloseAndEscape(result);
}
......
......@@ -348,6 +348,9 @@ class SerializerDeserializer: public ObjectVisitor {
};
// Misc.
// 0x48, 0x88 and 0xc8 are unused.
// Raw data to be copied from the snapshot. This byte code does not advance
// the current pointer, which is used for code objects, where we write the
// entire code in one memcpy, then fix up stuff with kSkip and other byte
......@@ -357,6 +360,9 @@ class SerializerDeserializer: public ObjectVisitor {
// These autoadvance the current pointer.
static const int kOnePointerRawData = 0x21;
// Internal reference encoded as offsets of pc and target from code entry.
static const int kInternalReference = 0x08;
static const int kVariableRepeat = 0x60;
// 0x61-0x6f Repeat last word
static const int kFixedRepeat = 0x61;
......@@ -611,23 +617,21 @@ class Serializer : public SerializerDeserializer {
protected:
class ObjectSerializer : public ObjectVisitor {
public:
ObjectSerializer(Serializer* serializer,
Object* o,
SnapshotByteSink* sink,
HowToCode how_to_code,
WhereToPoint where_to_point)
: serializer_(serializer),
object_(HeapObject::cast(o)),
sink_(sink),
reference_representation_(how_to_code + where_to_point),
bytes_processed_so_far_(0),
code_object_(o->IsCode()),
code_has_been_output_(false) { }
ObjectSerializer(Serializer* serializer, Object* o, SnapshotByteSink* sink,
HowToCode how_to_code, WhereToPoint where_to_point)
: serializer_(serializer),
object_(HeapObject::cast(o)),
sink_(sink),
reference_representation_(how_to_code + where_to_point),
bytes_processed_so_far_(0),
is_code_object_(o->IsCode()),
code_has_been_output_(false) {}
void Serialize();
void VisitPointers(Object** start, Object** end);
void VisitEmbeddedPointer(RelocInfo* target);
void VisitExternalReference(Address* p);
void VisitExternalReference(RelocInfo* rinfo);
void VisitInternalReference(RelocInfo* rinfo);
void VisitCodeTarget(RelocInfo* target);
void VisitCodeEntry(Address entry_address);
void VisitCell(RelocInfo* rinfo);
......@@ -660,7 +664,7 @@ class Serializer : public SerializerDeserializer {
SnapshotByteSink* sink_;
int reference_representation_;
int bytes_processed_so_far_;
bool code_object_;
bool is_code_object_;
bool code_has_been_output_;
};
......
......@@ -265,6 +265,12 @@ void Assembler::set_target_address_at(Address pc,
}
void Assembler::deserialization_set_target_internal_reference_at(
Address pc, Address target) {
Memory::Address_at(pc) = target;
}
Address Assembler::target_address_from_return_address(Address pc) {
return pc - kCallTargetAddressOffset;
}
......@@ -378,9 +384,9 @@ Address RelocInfo::target_internal_reference() {
}
void RelocInfo::set_target_internal_reference(Address target) {
Address RelocInfo::target_internal_reference_address() {
DCHECK(rmode_ == INTERNAL_REFERENCE);
Memory::Address_at(pc_) = target;
return reinterpret_cast<Address>(pc_);
}
......@@ -450,7 +456,8 @@ void RelocInfo::set_target_cell(Cell* cell,
void RelocInfo::WipeOut() {
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_)) {
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_)) {
Memory::Address_at(pc_) = NULL;
} else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
// Effectively write zero into the relocation.
......@@ -554,7 +561,8 @@ void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
visitor->VisitCell(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
visitor->VisitExternalReference(this);
CpuFeatures::FlushICache(pc_, sizeof(Address));
} else if (mode == RelocInfo::INTERNAL_REFERENCE) {
visitor->VisitInternalReference(this);
} else if (RelocInfo::IsCodeAgeSequence(mode)) {
visitor->VisitCodeAgeSequence(this);
} else if (((RelocInfo::IsJSReturn(mode) &&
......@@ -581,7 +589,8 @@ void RelocInfo::Visit(Heap* heap) {
StaticVisitor::VisitCell(heap, this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(this);
CpuFeatures::FlushICache(pc_, sizeof(Address));
} else if (mode == RelocInfo::INTERNAL_REFERENCE) {
StaticVisitor::VisitInternalReference(this);
} else if (RelocInfo::IsCodeAgeSequence(mode)) {
StaticVisitor::VisitCodeAgeSequence(heap, this);
} else if (heap->isolate()->debug()->has_break_points() &&
......
......@@ -570,6 +570,10 @@ class Assembler : public AssemblerBase {
set_target_address_at(instruction_payload, code, target);
}
// This sets the internal reference at the pc.
inline static void deserialization_set_target_internal_reference_at(
Address instruction, Address target);
static inline RelocInfo::Mode RelocInfoNone() {
if (kPointerSize == kInt64Size) {
return RelocInfo::NONE64;
......
......@@ -1484,6 +1484,9 @@ TEST(SerializeWithHarmonyScoping) {
TEST(SerializeInternalReference) {
#ifdef V8_TARGET_ARCH_ARM64
return;
#endif // V8_TARGET_ARCH_ARM64
// Disable experimental natives that are loaded after deserialization.
FLAG_turbo_deoptimization = false;
FLAG_context_specialization = false;
......@@ -1502,10 +1505,10 @@ TEST(SerializeInternalReference) {
" case 2:"
" case 3: j = 2; break;"
" case 4:"
" case 5: j = 3; break;"
" case 5: j = foo(3) + 1; break;"
" default: j = 0; break;"
" }"
" return j|0;"
" return j + 10;"
" }"
" return { foo: foo };"
"})(this, {}, undefined).foo;"
......@@ -1525,8 +1528,24 @@ TEST(SerializeInternalReference) {
v8::Context::Scope c_scope(context);
v8::Handle<v8::Function> foo =
v8::Handle<v8::Function>::Cast(CompileRun("foo"));
// There are at least 6 internal references.
int mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
RelocIterator it(v8::Utils::OpenHandle(*foo)->code(), mask);
for (int i = 0; i < 6; ++i) {
CHECK(!it.done());
it.next();
}
CHECK(v8::Utils::OpenHandle(*foo)->code()->is_turbofanned());
CHECK_EQ(3, CompileRun("foo(4)")->ToInt32(isolate)->Int32Value());
CHECK_EQ(11, CompileRun("foo(0)")->ToInt32(isolate)->Int32Value());
CHECK_EQ(11, CompileRun("foo(1)")->ToInt32(isolate)->Int32Value());
CHECK_EQ(12, CompileRun("foo(2)")->ToInt32(isolate)->Int32Value());
CHECK_EQ(12, CompileRun("foo(3)")->ToInt32(isolate)->Int32Value());
CHECK_EQ(23, CompileRun("foo(4)")->ToInt32(isolate)->Int32Value());
CHECK_EQ(23, CompileRun("foo(5)")->ToInt32(isolate)->Int32Value());
CHECK_EQ(10, CompileRun("foo(6)")->ToInt32(isolate)->Int32Value());
}
isolate->Dispose();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment