Chromium Code Reviews| Index: src/serialize.cc | 
| diff --git a/src/serialize.cc b/src/serialize.cc | 
| index 7ed36665e2fa3ea7c917f552626788cc4d4da54f..67cac884d5c7a97cba99b3590596ded3849dc540 100644 | 
| --- a/src/serialize.cc | 
| +++ b/src/serialize.cc | 
| @@ -1776,10 +1776,43 @@ void Serializer::ObjectSerializer::VisitExternalAsciiString( | 
| } | 
| +static Code* CloneCodeObject(HeapObject* code) { | 
| + Address copy = new byte[code->Size()]; | 
| + OS::MemCopy(copy, code->address(), code->Size()); | 
| + return Code::cast(HeapObject::FromAddress(copy)); | 
| +} | 
| + | 
| + | 
| +static void WipeOutCodeHeader(Code* code) { | 
| + code->set_relocation_info( | 
| 
 
Benedikt Meurer
2013/11/04 11:25:14
Nit: Can we do better here?
 
 | 
| + reinterpret_cast<ByteArray*>(Smi::FromInt(0)), SKIP_WRITE_BARRIER); | 
| + code->set_handler_table( | 
| + reinterpret_cast<FixedArray*>(Smi::FromInt(0)), SKIP_WRITE_BARRIER); | 
| + code->set_deoptimization_data( | 
| + reinterpret_cast<FixedArray*>(Smi::FromInt(0)), SKIP_WRITE_BARRIER); | 
| + // Do not wipe out e.g. a minor key. | 
| + if (!code->raw_type_feedback_info()->IsSmi()) { | 
| + code->InitializeTypeFeedbackInfoNoWriteBarrier(Smi::FromInt(0)); | 
| + } | 
| +} | 
| + | 
| + | 
| +static void WipeOutRelocations(Code* code) { | 
| + int mode_mask = | 
| + RelocInfo::kCodeTargetMask | | 
| + RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 
| + RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 
| + RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | 
| + for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | 
| + it.rinfo()->WipeOut(); | 
| + } | 
| +} | 
| + | 
| + | 
| int Serializer::ObjectSerializer::OutputRawData( | 
| Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) { | 
| Address object_start = object_->address(); | 
| - Address base = object_start + bytes_processed_so_far_; | 
| + int base = bytes_processed_so_far_; | 
| int up_to_offset = static_cast<int>(up_to - object_start); | 
| int to_skip = up_to_offset - bytes_processed_so_far_; | 
| int bytes_to_output = to_skip; | 
| @@ -1809,10 +1842,22 @@ int Serializer::ObjectSerializer::OutputRawData( | 
| sink_->Put(kRawData, "RawData"); | 
| 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_); | 
| + 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. | 
| + WipeOutCodeHeader(code); | 
| + object_start = code->address(); | 
| + } | 
| + | 
| + const char* description = code_object_ ? "Code" : "Byte"; | 
| for (int i = 0; i < bytes_to_output; i++) { | 
| - unsigned int data = base[i]; | 
| - sink_->PutSection(data, "Byte"); | 
| + sink_->PutSection(object_start[base + i], description); | 
| } | 
| + if (code_object_) delete[] object_start; | 
| } | 
| if (to_skip != 0 && return_skip == kIgnoringReturn) { | 
| sink_->Put(kSkip, "Skip"); |