diff --git a/src/serialize.cc b/src/serialize.cc index 8a383db143..d5d06a0677 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -2046,14 +2046,12 @@ void Serializer::ObjectSerializer::VisitExternalOneByteString( } -static Code* CloneCodeObject(HeapObject* code) { - Address copy = new byte[code->Size()]; - MemCopy(copy, code->address(), code->Size()); - return Code::cast(HeapObject::FromAddress(copy)); -} - - -static void WipeOutRelocations(Code* code) { +Address Serializer::ObjectSerializer::PrepareCode() { + // To make snapshots reproducible, we make a copy of the code object + // and wipe all pointers in the copy, which we then serialize. + Code* code = serializer_->CopyCode(Code::cast(object_)); + // Code age headers are not serializable. + code->MakeYoung(serializer_->isolate()); int mode_mask = RelocInfo::kCodeTargetMask | RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | @@ -2064,6 +2062,10 @@ static void WipeOutRelocations(Code* code) { it.rinfo()->WipeOut(); } } + // We need to wipe out the header fields *after* wiping out the + // relocations, because some of these fields are needed for the latter. + code->WipeOutHeader(); + return code->address(); } @@ -2101,17 +2103,7 @@ int Serializer::ObjectSerializer::OutputRawData( sink_->PutInt(bytes_to_output, "length"); } - // To make snapshots reproducible, we need to wipe out all pointers in code. - if (code_object_) { - Code* code = CloneCodeObject(object_); - // Code age headers are not serializable. - code->MakeYoung(serializer_->isolate()); - WipeOutRelocations(code); - // We need to wipe out the header fields *after* wiping out the - // relocations, because some of these fields are needed for the latter. - code->WipeOutHeader(); - object_start = code->address(); - } + if (code_object_) object_start = PrepareCode(); const char* description = code_object_ ? "Code" : "Byte"; #ifdef MEMORY_SANITIZER @@ -2119,7 +2111,6 @@ int Serializer::ObjectSerializer::OutputRawData( MSAN_MEMORY_IS_INITIALIZED(object_start + base, bytes_to_output); #endif // MEMORY_SANITIZER sink_->PutRaw(object_start + base, bytes_to_output, description); - if (code_object_) delete[] object_start; } if (to_skip != 0 && return_skip == kIgnoringReturn) { sink_->Put(kSkip, "Skip"); @@ -2178,6 +2169,14 @@ void Serializer::InitializeCodeAddressMap() { } +Code* Serializer::CopyCode(Code* code) { + code_buffer_.Rewind(0); // Clear buffer without deleting backing store. + int size = code->CodeSize(); + code_buffer_.AddAll(Vector(code->address(), size)); + return Code::cast(HeapObject::FromAddress(&code_buffer_.first())); +} + + ScriptData* CodeSerializer::Serialize(Isolate* isolate, Handle info, Handle source) { diff --git a/src/serialize.h b/src/serialize.h index 415d54244e..6817c7efe6 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -703,6 +703,8 @@ class Serializer : public SerializerDeserializer { // External strings are serialized in a way to resemble sequential strings. void SerializeExternalString(); + Address PrepareCode(); + Serializer* serializer_; HeapObject* object_; SnapshotByteSink* sink_; @@ -749,6 +751,8 @@ class Serializer : public SerializerDeserializer { // of the serializer. Initialize it on demand. void InitializeCodeAddressMap(); + Code* CopyCode(Code* code); + inline uint32_t max_chunk_size(int space) const { DCHECK_LE(0, space); DCHECK_LT(space, kNumberOfSpaces); @@ -783,6 +787,8 @@ class Serializer : public SerializerDeserializer { uint32_t large_objects_total_size_; uint32_t seen_large_objects_index_; + List code_buffer_; + DISALLOW_COPY_AND_ASSIGN(Serializer); };