| 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);
|
| }
|
|
|
|
|