Index: src/serialize.cc |
diff --git a/src/serialize.cc b/src/serialize.cc |
index b846c445c9f5d8e6b2c2ec93077c06c5f0273525..784992d92b869972834c954f211b5d635510294c 100644 |
--- a/src/serialize.cc |
+++ b/src/serialize.cc |
@@ -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); |
} |