From aa3ceb8b71c646df6952a91add9968844f962832 Mon Sep 17 00:00:00 2001 From: yangguo Date: Thu, 4 Dec 2014 01:50:27 -0800 Subject: [PATCH] Encode reservation meta data in the snapshot blob. This also makes reserving multiple chunks per object space possible. R=vogelheim@chromium.org Review URL: https://codereview.chromium.org/781443002 Cr-Commit-Position: refs/heads/master@{#25652} --- src/mksnapshot.cc | 171 +++++----------------- src/natives-external.cc | 5 +- src/serialize.cc | 265 ++++++++++++++++++++++------------ src/serialize.h | 198 +++++++++++++------------ src/snapshot-common.cc | 40 +---- src/snapshot-empty.cc | 21 --- src/snapshot-external.cc | 84 ++--------- src/snapshot-source-sink.cc | 21 +-- src/snapshot-source-sink.h | 13 +- src/snapshot.h | 24 +-- test/cctest/test-serialize.cc | 129 +++-------------- 11 files changed, 368 insertions(+), 603 deletions(-) diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc index 544e7393ea..77015a2b98 100644 --- a/src/mksnapshot.cc +++ b/src/mksnapshot.cc @@ -20,24 +20,13 @@ using namespace v8; - -class Compressor { - public: - virtual ~Compressor() {} - virtual bool Compress(i::Vector input) = 0; - virtual i::Vector* output() = 0; -}; - - class SnapshotWriter { public: explicit SnapshotWriter(const char* snapshot_file) - : fp_(GetFileDescriptorOrDie(snapshot_file)) - , raw_file_(NULL) - , raw_context_file_(NULL) - , startup_blob_file_(NULL) - , compressor_(NULL) { - } + : fp_(GetFileDescriptorOrDie(snapshot_file)), + raw_file_(NULL), + raw_context_file_(NULL), + startup_blob_file_(NULL) {} ~SnapshotWriter() { fclose(fp_); @@ -46,10 +35,6 @@ class SnapshotWriter { if (startup_blob_file_) fclose(startup_blob_file_); } - void SetCompressor(Compressor* compressor) { - compressor_ = compressor; - } - void SetRawFiles(const char* raw_file, const char* raw_context_file) { raw_file_ = GetFileDescriptorOrDie(raw_file); raw_context_file_ = GetFileDescriptorOrDie(raw_context_file); @@ -60,51 +45,21 @@ class SnapshotWriter { startup_blob_file_ = GetFileDescriptorOrDie(startup_blob_file); } - void WriteSnapshot(const i::List& snapshot_data, - const i::Serializer& serializer, - const i::List& context_snapshot_data, - const i::Serializer& context_serializer) const { - WriteSnapshotFile(snapshot_data, serializer, - context_snapshot_data, context_serializer); - MaybeWriteStartupBlob(snapshot_data, serializer, - context_snapshot_data, context_serializer); + void WriteSnapshot(const i::SnapshotData& sd, + const i::SnapshotData& csd) const { + WriteSnapshotFile(sd, csd); + MaybeWriteStartupBlob(sd, csd); } private: - void MaybeWriteStartupBlob(const i::List& snapshot_data, - const i::Serializer& serializer, - const i::List& context_snapshot_data, - const i::Serializer& context_serializer) const { + void MaybeWriteStartupBlob(const i::SnapshotData& sd, + const i::SnapshotData& csd) const { if (!startup_blob_file_) return; i::SnapshotByteSink sink; - int spaces[] = {i::NEW_SPACE, i::OLD_POINTER_SPACE, - i::OLD_DATA_SPACE, i::CODE_SPACE, - i::MAP_SPACE, i::CELL_SPACE, - i::PROPERTY_CELL_SPACE, i::LO_SPACE}; - - i::byte* snapshot_bytes = snapshot_data.begin(); - sink.PutBlob(snapshot_bytes, snapshot_data.length(), "snapshot"); - for (size_t i = 0; i < arraysize(spaces); ++i) { - i::Vector chunks = - serializer.FinalAllocationChunks(spaces[i]); - // For the start-up snapshot, none of the reservations has more than - // one chunk (reservation for each space fits onto a single page). - CHECK_EQ(1, chunks.length()); - sink.PutInt(chunks[0], "spaces"); - } - - i::byte* context_bytes = context_snapshot_data.begin(); - sink.PutBlob(context_bytes, context_snapshot_data.length(), "context"); - for (size_t i = 0; i < arraysize(spaces); ++i) { - i::Vector chunks = - context_serializer.FinalAllocationChunks(spaces[i]); - // For the context snapshot, none of the reservations has more than - // one chunk (reservation for each space fits onto a single page). - CHECK_EQ(1, chunks.length()); - sink.PutInt(chunks[0], "spaces"); - } + sink.PutBlob(sd.RawData(), "snapshot"); + sink.PutBlob(csd.RawData(), "context"); const i::List& startup_blob = sink.data(); size_t written = fwrite(startup_blob.begin(), 1, startup_blob.length(), @@ -115,15 +70,11 @@ class SnapshotWriter { } } - void WriteSnapshotFile(const i::List& snapshot_data, - const i::Serializer& serializer, - const i::List& context_snapshot_data, - const i::Serializer& context_serializer) const { + void WriteSnapshotFile(const i::SnapshotData& snapshot_data, + const i::SnapshotData& context_snapshot_data) const { WriteFilePrefix(); - WriteData("", snapshot_data, raw_file_); - WriteData("context_", context_snapshot_data, raw_context_file_); - WriteMeta("context_", context_serializer); - WriteMeta("", serializer); + WriteData("", snapshot_data.RawData(), raw_file_); + WriteData("context_", context_snapshot_data.RawData(), raw_context_file_); WriteFileSuffix(); } @@ -141,90 +92,43 @@ class SnapshotWriter { fprintf(fp_, "} // namespace v8\n"); } - void WriteData(const char* prefix, const i::List& source_data, + void WriteData(const char* prefix, + const i::Vector& source_data, FILE* raw_file) const { - const i::List* data_to_be_written = NULL; - i::List compressed_data; - if (!compressor_) { - data_to_be_written = &source_data; - } else if (compressor_->Compress(source_data.ToVector())) { - compressed_data.AddAll(*compressor_->output()); - data_to_be_written = &compressed_data; - } else { - i::PrintF("Compression failed. Aborting.\n"); - exit(1); - } - - DCHECK(data_to_be_written); - MaybeWriteRawFile(data_to_be_written, raw_file); - WriteData(prefix, source_data, data_to_be_written); + MaybeWriteRawFile(&source_data, raw_file); + WriteData(prefix, source_data); } - void MaybeWriteRawFile(const i::List* data, FILE* raw_file) const { - if (!data || !raw_file) - return; + void MaybeWriteRawFile(const i::Vector* data, + FILE* raw_file) const { + if (!data || !raw_file) return; // Sanity check, whether i::List iterators truly return pointers to an // internal array. DCHECK(data->end() - data->begin() == data->length()); size_t written = fwrite(data->begin(), 1, data->length(), raw_file); - if (written != (size_t)data->length()) { + if (written != static_cast(data->length())) { i::PrintF("Writing raw file failed.. Aborting.\n"); exit(1); } } - void WriteData(const char* prefix, const i::List& source_data, - const i::List* data_to_be_written) const { + void WriteData(const char* prefix, + const i::Vector& source_data) const { fprintf(fp_, "const byte Snapshot::%sdata_[] = {\n", prefix); - WriteSnapshotData(data_to_be_written); + WriteSnapshotData(source_data); fprintf(fp_, "};\n"); fprintf(fp_, "const int Snapshot::%ssize_ = %d;\n", prefix, - data_to_be_written->length()); - - if (data_to_be_written == &source_data) { - fprintf(fp_, "const byte* Snapshot::%sraw_data_ = Snapshot::%sdata_;\n", - prefix, prefix); - fprintf(fp_, "const int Snapshot::%sraw_size_ = Snapshot::%ssize_;\n", - prefix, prefix); - } else { - fprintf(fp_, "const byte* Snapshot::%sraw_data_ = NULL;\n", prefix); - fprintf(fp_, "const int Snapshot::%sraw_size_ = %d;\n", - prefix, source_data.length()); - } + source_data.length()); fprintf(fp_, "\n"); } - void WriteMeta(const char* prefix, const i::Serializer& ser) const { - WriteSizeVar(ser, prefix, "new", i::NEW_SPACE); - WriteSizeVar(ser, prefix, "pointer", i::OLD_POINTER_SPACE); - WriteSizeVar(ser, prefix, "data", i::OLD_DATA_SPACE); - WriteSizeVar(ser, prefix, "code", i::CODE_SPACE); - WriteSizeVar(ser, prefix, "map", i::MAP_SPACE); - WriteSizeVar(ser, prefix, "cell", i::CELL_SPACE); - WriteSizeVar(ser, prefix, "property_cell", i::PROPERTY_CELL_SPACE); - WriteSizeVar(ser, prefix, "lo", i::LO_SPACE); - fprintf(fp_, "\n"); - } - - void WriteSizeVar(const i::Serializer& ser, const char* prefix, - const char* name, int space) const { - i::Vector chunks = ser.FinalAllocationChunks(space); - // For the start-up snapshot, none of the reservations has more than - // one chunk (total reservation fits into a single page). - CHECK_EQ(1, chunks.length()); - fprintf(fp_, "const int Snapshot::%s%s_space_used_ = %d;\n", prefix, name, - chunks[0]); - } - - void WriteSnapshotData(const i::List* data) const { - for (int i = 0; i < data->length(); i++) { - if ((i & 0x1f) == 0x1f) - fprintf(fp_, "\n"); - if (i > 0) - fprintf(fp_, ","); - fprintf(fp_, "%u", static_cast(data->at(i))); + void WriteSnapshotData(const i::Vector& data) const { + for (int i = 0; i < data.length(); i++) { + if ((i & 0x1f) == 0x1f) fprintf(fp_, "\n"); + if (i > 0) fprintf(fp_, ","); + fprintf(fp_, "%u", static_cast(data.at(i))); } fprintf(fp_, "\n"); } @@ -242,7 +146,6 @@ class SnapshotWriter { FILE* raw_file_; FILE* raw_context_file_; FILE* startup_blob_file_; - Compressor* compressor_; }; @@ -365,17 +268,15 @@ int main(int argc, char** argv) { context_ser.Serialize(&raw_context); ser.SerializeWeakReferences(); - context_ser.FinalizeAllocation(); - ser.FinalizeAllocation(); - { SnapshotWriter writer(argv[1]); if (i::FLAG_raw_file && i::FLAG_raw_context_file) writer.SetRawFiles(i::FLAG_raw_file, i::FLAG_raw_context_file); if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob); - writer.WriteSnapshot(snapshot_sink.data(), ser, context_sink.data(), - context_ser); + i::SnapshotData sd(snapshot_sink, ser); + i::SnapshotData csd(context_sink, context_ser); + writer.WriteSnapshot(sd, csd); } } diff --git a/src/natives-external.cc b/src/natives-external.cc index 75e866b1b0..1b0f275bc0 100644 --- a/src/natives-external.cc +++ b/src/natives-external.cc @@ -147,9 +147,8 @@ void SetNativesFromFile(StartupData* natives_blob) { DCHECK(natives_blob->data); DCHECK(natives_blob->raw_size > 0); - SnapshotByteSource bytes( - reinterpret_cast(natives_blob->data), - natives_blob->raw_size); + SnapshotByteSource bytes(reinterpret_cast(natives_blob->data), + natives_blob->raw_size); NativesHolder::set(NativesStore::MakeFromScriptsSource(&bytes)); NativesHolder::set(NativesStore::MakeFromScriptsSource(&bytes)); DCHECK(!bytes.HasMore()); diff --git a/src/serialize.cc b/src/serialize.cc index e6aae7fe8d..f0bd68e659 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -611,12 +611,16 @@ class CodeAddressMap: public CodeEventLogger { }; -Deserializer::Deserializer(SnapshotByteSource* source) - : isolate_(NULL), - attached_objects_(NULL), - source_(source), - external_reference_decoder_(NULL), - deserialized_large_objects_(0) { +void Deserializer::DecodeReservation( + Vector res) { + DCHECK_EQ(0, reservations_[NEW_SPACE].length()); + STATIC_ASSERT(NEW_SPACE == 0); + int current_space = NEW_SPACE; + for (const auto& r : res) { + reservations_[current_space].Add({r.chunk_size(), NULL, NULL}); + if (r.is_last()) current_space++; + } + DCHECK_EQ(kNumberOfSpaces, current_space); for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0; } @@ -716,7 +720,7 @@ void Deserializer::DeserializePartial(Isolate* isolate, Object** root, Deserializer::~Deserializer() { // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. - // DCHECK(source_->AtEOF()); + // DCHECK(source_.AtEOF()); if (external_reference_decoder_) { delete external_reference_decoder_; external_reference_decoder_ = NULL; @@ -797,10 +801,10 @@ HeapObject* Deserializer::ProcessNewObjectFromSerializedCode(HeapObject* obj) { HeapObject* Deserializer::GetBackReferencedObject(int space) { HeapObject* obj; if (space == LO_SPACE) { - uint32_t index = source_->GetInt(); + uint32_t index = source_.GetInt(); obj = deserialized_large_objects_[index]; } else { - BackReference back_reference(source_->GetInt()); + BackReference back_reference(source_.GetInt()); DCHECK(space < kNumberOfPreallocatedSpaces); uint32_t chunk_index = back_reference.chunk_index(); DCHECK_LE(chunk_index, current_chunk_[space]); @@ -824,12 +828,12 @@ HeapObject* Deserializer::GetBackReferencedObject(int space) { void Deserializer::ReadObject(int space_number, Object** write_back) { Address address; HeapObject* obj; - int next_int = source_->GetInt(); + int next_int = source_.GetInt(); bool double_align = false; #ifndef V8_HOST_ARCH_64_BIT double_align = next_int == kDoubleAlignmentSentinel; - if (double_align) next_int = source_->GetInt(); + if (double_align) next_int = source_.GetInt(); #endif DCHECK_NE(kDoubleAlignmentSentinel, next_int); @@ -846,7 +850,7 @@ void Deserializer::ReadObject(int space_number, Object** write_back) { Object** current = reinterpret_cast(address); Object** limit = current + (size >> kPointerSizeLog2); if (FLAG_log_snapshot_positions) { - LOG(isolate_, SnapshotPositionEvent(address, source_->position())); + LOG(isolate_, SnapshotPositionEvent(address, source_.position())); } ReadData(current, limit, space_number, address); @@ -884,7 +888,7 @@ Address Deserializer::Allocate(int space_index, int size) { if (space_index == LO_SPACE) { AlwaysAllocateScope scope(isolate_); LargeObjectSpace* lo_space = isolate_->heap()->lo_space(); - Executability exec = static_cast(source_->Get()); + Executability exec = static_cast(source_.Get()); AllocationResult result = lo_space->AllocateRaw(size, exec); HeapObject* obj = HeapObject::cast(result.ToObjectChecked()); deserialized_large_objects_.Add(obj); @@ -918,7 +922,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, source_space != CODE_SPACE && source_space != OLD_DATA_SPACE); while (current < limit) { - byte data = source_->Get(); + byte data = source_.Get(); switch (data) { #define CASE_STATEMENT(where, how, within, space_number) \ case where + how + within + space_number: \ @@ -942,18 +946,18 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, if (where == kNewObject) { \ ReadObject(space_number, &new_object); \ } else if (where == kRootArray) { \ - int root_id = source_->GetInt(); \ + int root_id = source_.GetInt(); \ new_object = isolate->heap()->roots_array_start()[root_id]; \ emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ } else if (where == kPartialSnapshotCache) { \ - int cache_index = source_->GetInt(); \ + int cache_index = source_.GetInt(); \ new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ } else if (where == kExternalReference) { \ - int skip = source_->GetInt(); \ + int skip = source_.GetInt(); \ current = reinterpret_cast( \ reinterpret_cast
(current) + skip); \ - int reference_id = source_->GetInt(); \ + int reference_id = source_.GetInt(); \ Address address = external_reference_decoder_->Decode(reference_id); \ new_object = reinterpret_cast(address); \ } else if (where == kBackref) { \ @@ -961,7 +965,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, new_object = GetBackReferencedObject(data & kSpaceMask); \ } else if (where == kBuiltin) { \ DCHECK(deserializing_user_code()); \ - int builtin_id = source_->GetInt(); \ + int builtin_id = source_.GetInt(); \ DCHECK_LE(0, builtin_id); \ DCHECK_LT(builtin_id, Builtins::builtin_count); \ Builtins::Name name = static_cast(builtin_id); \ @@ -969,12 +973,12 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, emit_write_barrier = false; \ } else if (where == kAttachedReference) { \ DCHECK(deserializing_user_code()); \ - int index = source_->GetInt(); \ + int index = source_.GetInt(); \ new_object = *attached_objects_->at(index); \ emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ } else { \ DCHECK(where == kBackrefWithSkip); \ - int skip = source_->GetInt(); \ + int skip = source_.GetInt(); \ current = reinterpret_cast( \ reinterpret_cast
(current) + skip); \ emit_write_barrier = (space_number == NEW_SPACE); \ @@ -1078,23 +1082,22 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, // We generate 15 cases and bodies that process special tags that combine // the raw data tag and the length into one byte. -#define RAW_CASE(index) \ - case kRawData + index: { \ - byte* raw_data_out = reinterpret_cast(current); \ - source_->CopyRaw(raw_data_out, index * kPointerSize); \ - current = \ - reinterpret_cast(raw_data_out + index * kPointerSize); \ - break; \ - } +#define RAW_CASE(index) \ + case kRawData + index: { \ + byte* raw_data_out = reinterpret_cast(current); \ + source_.CopyRaw(raw_data_out, index* kPointerSize); \ + current = reinterpret_cast(raw_data_out + index * kPointerSize); \ + break; \ + } COMMON_RAW_LENGTHS(RAW_CASE) #undef RAW_CASE // Deserialize a chunk of raw data that doesn't have one of the popular // lengths. case kRawData: { - int size = source_->GetInt(); + int size = source_.GetInt(); byte* raw_data_out = reinterpret_cast(current); - source_->CopyRaw(raw_data_out, size); + source_.CopyRaw(raw_data_out, size); break; } @@ -1110,7 +1113,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance) SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance + 16) { int root_id = RootArrayConstantFromByteCode(data); - int skip = source_->GetInt(); + int skip = source_.GetInt(); current = reinterpret_cast( reinterpret_cast(current) + skip); Object* object = isolate->heap()->roots_array_start()[root_id]; @@ -1120,7 +1123,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, } case kVariableRepeat: { - int repeats = source_->GetInt(); + int repeats = source_.GetInt(); Object* object = current[-1]; DCHECK(!isolate->heap()->InNewSpace(object)); for (int i = 0; i < repeats; i++) current[i] = object; @@ -1240,14 +1243,14 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, #undef ALL_SPACES case kSkip: { - int size = source_->GetInt(); + int size = source_.GetInt(); current = reinterpret_cast( reinterpret_cast(current) + size); break; } case kNativesStringResource: { - int index = source_->Get(); + int index = source_.Get(); Vector source_vector = Natives::GetRawScriptSource(index); NativesExternalStringResource* resource = new NativesExternalStringResource(isolate->bootstrapper(), @@ -1258,7 +1261,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, } case kNextChunk: { - int space = source_->Get(); + int space = source_.Get(); DCHECK(space < kNumberOfPreallocatedSpaces); int chunk_index = current_chunk_[space]; const Heap::Reservation& reservation = reservations_[space]; @@ -1273,7 +1276,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, FOUR_CASES(kHotObjectWithSkip) FOUR_CASES(kHotObjectWithSkip + 4) { - int skip = source_->GetInt(); + int skip = source_.GetInt(); current = reinterpret_cast( reinterpret_cast
(current) + skip); // Fall through. @@ -1394,15 +1397,21 @@ void Serializer::VisitPointers(Object** start, Object** end) { } -void Serializer::FinalizeAllocation() { +void Serializer::EncodeReservations( + List* out) const { for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { - // Complete the last pending chunk and if there are no completed chunks, - // make sure there is at least one empty chunk. - if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { - completed_chunks_[i].Add(pending_chunk_[i]); - pending_chunk_[i] = 0; + for (int j = 0; j < completed_chunks_[i].length(); j++) { + out->Add(SerializedData::Reservation(completed_chunks_[i][j])); } + + if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { + out->Add(SerializedData::Reservation(pending_chunk_[i])); + } + out->last().mark_as_last(); } + + out->Add(SerializedData::Reservation(large_objects_total_size_)); + out->last().mark_as_last(); } @@ -1718,7 +1727,7 @@ void Serializer::ObjectSerializer::SerializeExternalString() { } // Serialize string content. - sink_->PutRaw(const_cast(resource), content_size, "StringContent"); + sink_->PutRaw(resource, content_size, "StringContent"); // Since the allocation size is rounded up to object alignment, there // maybe left-over bytes that need to be padded. @@ -2021,6 +2030,7 @@ BackReference Serializer::Allocate(AllocationSpace space, int size) { sink_->Put(kNextChunk, "NextChunk"); sink_->Put(space, "NextChunkSpace"); completed_chunks_[space].Add(pending_chunk_[space]); + DCHECK_LE(completed_chunks_[space].length(), BackReference::kMaxChunkIndex); pending_chunk_[space] = 0; new_chunk_size = size; } @@ -2065,16 +2075,8 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate, Object** location = Handle::cast(info).location(); cs.VisitPointer(location); cs.Pad(); - cs.FinalizeAllocation(); - for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { - // Fail if any chunk index exceeds the limit. - if (cs.FinalAllocationChunks(i).length() > BackReference::kMaxChunkIndex) { - return NULL; - } - } - - SerializedCodeData data(sink.data(), &cs); + SerializedCodeData data(sink.data(), cs); ScriptData* script_data = data.GetScriptData(); if (FLAG_profile_deserialization) { @@ -2275,23 +2277,11 @@ MaybeHandle CodeSerializer::Deserialize( DCHECK(cached_data->rejected()); return MaybeHandle(); } - SnapshotByteSource payload(scd->Payload(), scd->PayloadLength()); - Deserializer deserializer(&payload); // Eagerly expand string table to avoid allocations during deserialization. StringTable::EnsureCapacityForDeserialization( isolate, scd->NumInternalizedStrings()); - // Set reservations. - STATIC_ASSERT(NEW_SPACE == 0); - int current_space = NEW_SPACE; - Vector res = scd->Reservations(); - for (const auto& r : res) { - deserializer.AddReservation(current_space, r.chunk_size()); - if (r.is_last_chunk()) current_space++; - } - DCHECK_EQ(kNumberOfSpaces, current_space); - // Prepare and register list of attached objects. Vector code_stub_keys = scd->CodeStubKeys(); Vector > attached_objects = Vector >::New( @@ -2301,6 +2291,8 @@ MaybeHandle CodeSerializer::Deserialize( attached_objects[i + kCodeStubsBaseIndex] = CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); } + + Deserializer deserializer(scd.get()); deserializer.SetAttachedObjects(&attached_objects); // Deserialize. @@ -2336,65 +2328,152 @@ MaybeHandle CodeSerializer::Deserialize( } -SerializedCodeData::SerializedCodeData(const List& payload, - CodeSerializer* cs) - : script_data_(NULL), owns_script_data_(true) { - DisallowHeapAllocation no_gc; - List* stub_keys = cs->stub_keys(); +void SerializedData::AllocateData(int size) { + DCHECK(!owns_data_); + data_ = NewArray(size); + size_ = size; + owns_data_ = true; + DCHECK(IsAligned(reinterpret_cast(data_), kPointerAlignment)); +} - // Gather reservation chunk sizes. - List reservations(SerializerDeserializer::kNumberOfSpaces); - STATIC_ASSERT(NEW_SPACE == 0); - for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) { - Vector chunks = cs->FinalAllocationChunks(i); - for (int j = 0; j < chunks.length(); j++) { - uint32_t chunk = ChunkSizeBits::encode(chunks[j]) | - IsLastChunkBits::encode(j == chunks.length() - 1); - reservations.Add(chunk); - } - } + +SnapshotData::SnapshotData(const SnapshotByteSink& sink, + const Serializer& ser) { + DisallowHeapAllocation no_gc; + List reservations; + ser.EncodeReservations(&reservations); + const List& payload = sink.data(); + + // Calculate sizes. + int reservation_size = reservations.length() * kInt32Size; + int size = kHeaderSize + reservation_size + payload.length(); + + // Allocate backing store and create result data. + AllocateData(size); + + // Set header values. + SetHeaderValue(kCheckSumOffset, Version::Hash()); + SetHeaderValue(kReservationsOffset, reservations.length()); + SetHeaderValue(kPayloadLengthOffset, payload.length()); + + // Copy reservation chunk sizes. + CopyBytes(data_ + kHeaderSize, reinterpret_cast(reservations.begin()), + reservation_size); + + // Copy serialized data. + CopyBytes(data_ + kHeaderSize + reservation_size, payload.begin(), + static_cast(payload.length())); +} + + +bool SnapshotData::IsSane() { + return GetHeaderValue(kCheckSumOffset) == Version::Hash(); +} + + +Vector SnapshotData::Reservations() const { + return Vector( + reinterpret_cast(data_ + kHeaderSize), + GetHeaderValue(kReservationsOffset)); +} + + +Vector SnapshotData::Payload() const { + int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; + const byte* payload = data_ + kHeaderSize + reservations_size; + int length = GetHeaderValue(kPayloadLengthOffset); + DCHECK_EQ(data_ + size_, payload + length); + return Vector(payload, length); +} + + +SerializedCodeData::SerializedCodeData(const List& payload, + const CodeSerializer& cs) { + DisallowHeapAllocation no_gc; + const List* stub_keys = cs.stub_keys(); + + List reservations; + cs.EncodeReservations(&reservations); // Calculate sizes. int reservation_size = reservations.length() * kInt32Size; int num_stub_keys = stub_keys->length(); int stub_keys_size = stub_keys->length() * kInt32Size; - int data_length = - kHeaderSize + reservation_size + stub_keys_size + payload.length(); + int size = kHeaderSize + reservation_size + stub_keys_size + payload.length(); // Allocate backing store and create result data. - byte* data = NewArray(data_length); - DCHECK(IsAligned(reinterpret_cast(data), kPointerAlignment)); - script_data_ = new ScriptData(data, data_length); - script_data_->AcquireDataOwnership(); + AllocateData(size); // Set header values. - SetHeaderValue(kCheckSumOffset, CheckSum(cs->source())); - SetHeaderValue(kNumInternalizedStringsOffset, cs->num_internalized_strings()); + SetHeaderValue(kCheckSumOffset, CheckSum(cs.source())); + SetHeaderValue(kNumInternalizedStringsOffset, cs.num_internalized_strings()); SetHeaderValue(kReservationsOffset, reservations.length()); SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); SetHeaderValue(kPayloadLengthOffset, payload.length()); // Copy reservation chunk sizes. - CopyBytes(data + kHeaderSize, reinterpret_cast(reservations.begin()), + CopyBytes(data_ + kHeaderSize, reinterpret_cast(reservations.begin()), reservation_size); // Copy code stub keys. - CopyBytes(data + kHeaderSize + reservation_size, + CopyBytes(data_ + kHeaderSize + reservation_size, reinterpret_cast(stub_keys->begin()), stub_keys_size); // Copy serialized data. - CopyBytes(data + kHeaderSize + reservation_size + stub_keys_size, + CopyBytes(data_ + kHeaderSize + reservation_size + stub_keys_size, payload.begin(), static_cast(payload.length())); } bool SerializedCodeData::IsSane(String* source) { return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && - PayloadLength() >= SharedFunctionInfo::kSize; + Payload().length() >= SharedFunctionInfo::kSize; } int SerializedCodeData::CheckSum(String* string) { return Version::Hash() ^ string->length(); } + + +// Return ScriptData object and relinquish ownership over it to the caller. +ScriptData* SerializedCodeData::GetScriptData() { + DCHECK(owns_data_); + ScriptData* result = new ScriptData(data_, size_); + result->AcquireDataOwnership(); + owns_data_ = false; + data_ = NULL; + return result; +} + + +Vector SerializedCodeData::Reservations() + const { + return Vector( + reinterpret_cast(data_ + kHeaderSize), + GetHeaderValue(kReservationsOffset)); +} + + +Vector SerializedCodeData::Payload() const { + int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; + int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size; + const byte* payload = + data_ + kHeaderSize + reservations_size + code_stubs_size; + int length = GetHeaderValue(kPayloadLengthOffset); + DCHECK_EQ(data_ + size_, payload + length); + return Vector(payload, length); +} + + +int SerializedCodeData::NumInternalizedStrings() const { + return GetHeaderValue(kNumInternalizedStringsOffset); +} + +Vector SerializedCodeData::CodeStubKeys() const { + int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; + const byte* start = data_ + kHeaderSize + reservations_size; + return Vector(reinterpret_cast(start), + GetHeaderValue(kNumCodeStubKeysOffset)); +} } } // namespace v8::internal diff --git a/src/serialize.h b/src/serialize.h index 43a01e45ac..0c34650333 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -453,11 +453,63 @@ class SerializerDeserializer: public ObjectVisitor { }; +class SerializedData { + public: + class Reservation { + public: + explicit Reservation(uint32_t size) + : reservation_(ChunkSizeBits::encode(size)) {} + + uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); } + bool is_last() const { return IsLastChunkBits::decode(reservation_); } + + void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); } + + private: + uint32_t reservation_; + }; + + SerializedData(byte* data, int size) + : data_(data), size_(size), owns_data_(false) {} + SerializedData() : data_(NULL), size_(0), owns_data_(false) {} + + ~SerializedData() { + if (owns_data_) DeleteArray(data_); + } + + class ChunkSizeBits : public BitField {}; + class IsLastChunkBits : public BitField {}; + + protected: + void SetHeaderValue(int offset, int value) { + reinterpret_cast(data_)[offset] = value; + } + + int GetHeaderValue(int offset) const { + return reinterpret_cast(data_)[offset]; + } + + void AllocateData(int size); + + byte* data_; + int size_; + bool owns_data_; +}; + + // A Deserializer reads a snapshot and reconstructs the Object graph it defines. class Deserializer: public SerializerDeserializer { public: // Create a deserializer from a snapshot byte source. - explicit Deserializer(SnapshotByteSource* source); + template + explicit Deserializer(Data* data) + : isolate_(NULL), + attached_objects_(NULL), + source_(data->Payload()), + external_reference_decoder_(NULL), + deserialized_large_objects_(0) { + DecodeReservation(data->Reservations()); + } virtual ~Deserializer(); @@ -471,12 +523,6 @@ class Deserializer: public SerializerDeserializer { void DeserializePartial(Isolate* isolate, Object** root, OnOOM on_oom = FATAL_ON_OOM); - void AddReservation(int space, uint32_t chunk) { - DCHECK(space >= 0); - DCHECK(space < kNumberOfSpaces); - reservations_[space].Add({chunk, NULL, NULL}); - } - void FlushICacheForNewCodeObjects(); // Serialized user code reference certain objects that are provided in a list @@ -494,6 +540,8 @@ class Deserializer: public SerializerDeserializer { UNREACHABLE(); } + void DecodeReservation(Vector res); + bool ReserveSpace(); // Allocation sites are present in the snapshot, and must be linked into @@ -523,7 +571,7 @@ class Deserializer: public SerializerDeserializer { // Objects from the attached object descriptions in the serialized user code. Vector >* attached_objects_; - SnapshotByteSource* source_; + SnapshotByteSource source_; // The address of the next object that will be allocated in each space. // Each space has a number of chunks reserved by the GC, with each chunk // fitting into a page. Deserialized objects are allocated into the @@ -549,16 +597,7 @@ class Serializer : public SerializerDeserializer { ~Serializer(); virtual void VisitPointers(Object** start, Object** end) OVERRIDE; - void FinalizeAllocation(); - - Vector FinalAllocationChunks(int space) const { - if (space == LO_SPACE) { - return Vector(&large_objects_total_size_, 1); - } else { - DCHECK_EQ(0, pending_chunk_[space]); // No pending chunks. - return completed_chunks_[space].ToConstVector(); - } - } + void EncodeReservations(List* out) const; Isolate* isolate() const { return isolate_; } @@ -782,7 +821,7 @@ class CodeSerializer : public Serializer { return source_; } - List* stub_keys() { return &stub_keys_; } + const List* stub_keys() const { return &stub_keys_; } int num_internalized_strings() const { return num_internalized_strings_; } private: @@ -819,10 +858,42 @@ class CodeSerializer : public Serializer { }; -// Wrapper around ScriptData to provide code-serializer-specific functionality. -class SerializedCodeData { +// Wrapper around reservation sizes and the serialization payload. +class SnapshotData : public SerializedData { public: - // Used by when consuming. + // Used when producing. + SnapshotData(const SnapshotByteSink& sink, const Serializer& ser); + + // Used when consuming. + explicit SnapshotData(const byte* data, int size) + : SerializedData(const_cast(data), size) { + CHECK(IsSane()); + } + + Vector Reservations() const; + Vector Payload() const; + + Vector RawData() const { + return Vector(data_, size_); + } + + private: + bool IsSane(); + // The data header consists of int-sized entries: + // [0] version hash + // [1] number of reservation size entries + // [2] payload length + static const int kCheckSumOffset = 0; + static const int kReservationsOffset = 1; + static const int kPayloadLengthOffset = 2; + static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize; +}; + + +// Wrapper around ScriptData to provide code-serializer-specific functionality. +class SerializedCodeData : public SerializedData { + public: + // Used when consuming. static SerializedCodeData* FromCachedData(ScriptData* cached_data, String* source) { DisallowHeapAllocation no_gc; @@ -834,75 +905,20 @@ class SerializedCodeData { } // Used when producing. - SerializedCodeData(const List& payload, CodeSerializer* cs); - - ~SerializedCodeData() { - if (owns_script_data_) delete script_data_; - } + SerializedCodeData(const List& payload, const CodeSerializer& cs); // Return ScriptData object and relinquish ownership over it to the caller. - ScriptData* GetScriptData() { - ScriptData* result = script_data_; - script_data_ = NULL; - DCHECK(owns_script_data_); - owns_script_data_ = false; - return result; - } + ScriptData* GetScriptData(); - class Reservation { - public: - uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation); } - bool is_last_chunk() const { return IsLastChunkBits::decode(reservation); } + Vector Reservations() const; + Vector Payload() const; - private: - uint32_t reservation; - - DISALLOW_COPY_AND_ASSIGN(Reservation); - }; - - int NumInternalizedStrings() const { - return GetHeaderValue(kNumInternalizedStringsOffset); - } - - Vector Reservations() const { - return Vector(reinterpret_cast( - script_data_->data() + kHeaderSize), - GetHeaderValue(kReservationsOffset)); - } - - Vector CodeStubKeys() const { - int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; - const byte* start = script_data_->data() + kHeaderSize + reservations_size; - return Vector(reinterpret_cast(start), - GetHeaderValue(kNumCodeStubKeysOffset)); - } - - const byte* Payload() const { - int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; - int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size; - return script_data_->data() + kHeaderSize + reservations_size + - code_stubs_size; - } - - int PayloadLength() const { - int payload_length = GetHeaderValue(kPayloadLengthOffset); - DCHECK_EQ(script_data_->data() + script_data_->length(), - Payload() + payload_length); - return payload_length; - } + int NumInternalizedStrings() const; + Vector CodeStubKeys() const; private: explicit SerializedCodeData(ScriptData* data) - : script_data_(data), owns_script_data_(false) {} - - void SetHeaderValue(int offset, int value) { - reinterpret_cast(const_cast(script_data_->data()))[offset] = - value; - } - - int GetHeaderValue(int offset) const { - return reinterpret_cast(script_data_->data())[offset]; - } + : SerializedData(const_cast(data->data()), data->length()) {} bool IsSane(String* source); @@ -912,24 +928,14 @@ class SerializedCodeData { // [0] version hash // [1] number of internalized strings // [2] number of code stub keys - // [3] payload length - // [4..10] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE. + // [3] number of reservation size entries + // [4] payload length static const int kCheckSumOffset = 0; static const int kNumInternalizedStringsOffset = 1; static const int kReservationsOffset = 2; static const int kNumCodeStubKeysOffset = 3; static const int kPayloadLengthOffset = 4; static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize; - - class ChunkSizeBits : public BitField {}; - class IsLastChunkBits : public BitField {}; - - // Following the header, we store, in sequential order - // - code stub keys - // - serialization payload - - ScriptData* script_data_; - bool owns_script_data_; }; } } // namespace v8::internal diff --git a/src/snapshot-common.cc b/src/snapshot-common.cc index b152ad354b..f06f38a199 100644 --- a/src/snapshot-common.cc +++ b/src/snapshot-common.cc @@ -14,27 +14,14 @@ namespace v8 { namespace internal { -void Snapshot::ReserveSpaceForLinkedInSnapshot(Deserializer* deserializer) { - deserializer->AddReservation(NEW_SPACE, new_space_used_); - deserializer->AddReservation(OLD_POINTER_SPACE, pointer_space_used_); - deserializer->AddReservation(OLD_DATA_SPACE, data_space_used_); - deserializer->AddReservation(CODE_SPACE, code_space_used_); - deserializer->AddReservation(MAP_SPACE, map_space_used_); - deserializer->AddReservation(CELL_SPACE, cell_space_used_); - deserializer->AddReservation(PROPERTY_CELL_SPACE, property_cell_space_used_); - deserializer->AddReservation(LO_SPACE, lo_space_used_); -} - bool Snapshot::Initialize(Isolate* isolate) { if (size_ > 0) { base::ElapsedTimer timer; - if (FLAG_profile_deserialization) { - timer.Start(); - } - SnapshotByteSource source(raw_data_, raw_size_); - Deserializer deserializer(&source); - ReserveSpaceForLinkedInSnapshot(&deserializer); + if (FLAG_profile_deserialization) timer.Start(); + + SnapshotData snapshot_data(data_, size_); + Deserializer deserializer(&snapshot_data); bool success = isolate->Init(&deserializer); if (FLAG_profile_deserialization) { double ms = timer.Elapsed().InMillisecondsF(); @@ -52,22 +39,11 @@ bool Snapshot::HaveASnapshotToStartFrom() { Handle Snapshot::NewContextFromSnapshot(Isolate* isolate) { - if (context_size_ == 0) { - return Handle(); - } - SnapshotByteSource source(context_raw_data_, - context_raw_size_); - Deserializer deserializer(&source); + if (context_size_ == 0) return Handle(); + + SnapshotData snapshot_data(context_data_, context_size_); + Deserializer deserializer(&snapshot_data); Object* root; - deserializer.AddReservation(NEW_SPACE, context_new_space_used_); - deserializer.AddReservation(OLD_POINTER_SPACE, context_pointer_space_used_); - deserializer.AddReservation(OLD_DATA_SPACE, context_data_space_used_); - deserializer.AddReservation(CODE_SPACE, context_code_space_used_); - deserializer.AddReservation(MAP_SPACE, context_map_space_used_); - deserializer.AddReservation(CELL_SPACE, context_cell_space_used_); - deserializer.AddReservation(PROPERTY_CELL_SPACE, - context_property_cell_space_used_); - deserializer.AddReservation(LO_SPACE, context_lo_space_used_); deserializer.DeserializePartial(isolate, &root); CHECK(root->IsContext()); return Handle(Context::cast(root)); diff --git a/src/snapshot-empty.cc b/src/snapshot-empty.cc index e8673e5600..749c5874aa 100644 --- a/src/snapshot-empty.cc +++ b/src/snapshot-empty.cc @@ -12,29 +12,8 @@ namespace v8 { namespace internal { const byte Snapshot::data_[] = { 0 }; -const byte* Snapshot::raw_data_ = NULL; const int Snapshot::size_ = 0; -const int Snapshot::raw_size_ = 0; const byte Snapshot::context_data_[] = { 0 }; -const byte* Snapshot::context_raw_data_ = NULL; const int Snapshot::context_size_ = 0; -const int Snapshot::context_raw_size_ = 0; -const int Snapshot::new_space_used_ = 0; -const int Snapshot::pointer_space_used_ = 0; -const int Snapshot::data_space_used_ = 0; -const int Snapshot::code_space_used_ = 0; -const int Snapshot::map_space_used_ = 0; -const int Snapshot::cell_space_used_ = 0; -const int Snapshot::property_cell_space_used_ = 0; -const int Snapshot::lo_space_used_ = 0; - -const int Snapshot::context_new_space_used_ = 0; -const int Snapshot::context_pointer_space_used_ = 0; -const int Snapshot::context_data_space_used_ = 0; -const int Snapshot::context_code_space_used_ = 0; -const int Snapshot::context_map_space_used_ = 0; -const int Snapshot::context_cell_space_used_ = 0; -const int Snapshot::context_property_cell_space_used_ = 0; -const int Snapshot::context_lo_space_used_ = 0; } } // namespace v8::internal diff --git a/src/snapshot-external.cc b/src/snapshot-external.cc index b75e232295..1e5aec9250 100644 --- a/src/snapshot-external.cc +++ b/src/snapshot-external.cc @@ -18,25 +18,8 @@ struct SnapshotImpl { public: const byte* data; int size; - int new_space_used; - int pointer_space_used; - int data_space_used; - int code_space_used; - int map_space_used; - int cell_space_used; - int property_cell_space_used; - int lo_space_used; - const byte* context_data; int context_size; - int context_new_space_used; - int context_pointer_space_used; - int context_data_space_used; - int context_code_space_used; - int context_map_space_used; - int context_cell_space_used; - int context_property_cell_space_used; - int context_lo_space_used; }; @@ -49,25 +32,13 @@ bool Snapshot::HaveASnapshotToStartFrom() { bool Snapshot::Initialize(Isolate* isolate) { - if (!HaveASnapshotToStartFrom()) - return false; - + if (!HaveASnapshotToStartFrom()) return false; base::ElapsedTimer timer; - if (FLAG_profile_deserialization) { - timer.Start(); - } - SnapshotByteSource source(snapshot_impl_->data, snapshot_impl_->size); - Deserializer deserializer(&source); - deserializer.AddReservation(NEW_SPACE, snapshot_impl_->new_space_used); - deserializer.AddReservation(OLD_POINTER_SPACE, - snapshot_impl_->pointer_space_used); - deserializer.AddReservation(OLD_DATA_SPACE, snapshot_impl_->data_space_used); - deserializer.AddReservation(CODE_SPACE, snapshot_impl_->code_space_used); - deserializer.AddReservation(MAP_SPACE, snapshot_impl_->map_space_used); - deserializer.AddReservation(CELL_SPACE, snapshot_impl_->cell_space_used); - deserializer.AddReservation(PROPERTY_CELL_SPACE, - snapshot_impl_->property_cell_space_used); - deserializer.AddReservation(LO_SPACE, snapshot_impl_->lo_space_used); + if (FLAG_profile_deserialization) timer.Start(); + + + SnapshotData snapshot_data(snapshot_impl_->data, snapshot_impl_->size); + Deserializer deserializer(&snapshot_data); bool success = isolate->Init(&deserializer); if (FLAG_profile_deserialization) { double ms = timer.Elapsed().InMillisecondsF(); @@ -78,27 +49,11 @@ bool Snapshot::Initialize(Isolate* isolate) { Handle Snapshot::NewContextFromSnapshot(Isolate* isolate) { - if (!HaveASnapshotToStartFrom()) - return Handle(); + if (!HaveASnapshotToStartFrom()) return Handle(); - SnapshotByteSource source(snapshot_impl_->context_data, - snapshot_impl_->context_size); - Deserializer deserializer(&source); - deserializer.AddReservation(NEW_SPACE, - snapshot_impl_->context_new_space_used); - deserializer.AddReservation(OLD_POINTER_SPACE, - snapshot_impl_->context_pointer_space_used); - deserializer.AddReservation(OLD_DATA_SPACE, - snapshot_impl_->context_data_space_used); - deserializer.AddReservation(CODE_SPACE, - snapshot_impl_->context_code_space_used); - deserializer.AddReservation(MAP_SPACE, - snapshot_impl_->context_map_space_used); - deserializer.AddReservation(CELL_SPACE, - snapshot_impl_->context_cell_space_used); - deserializer.AddReservation(PROPERTY_CELL_SPACE, - snapshot_impl_->context_property_cell_space_used); - deserializer.AddReservation(LO_SPACE, snapshot_impl_->context_lo_space_used); + SnapshotData snapshot_data(snapshot_impl_->context_data, + snapshot_impl_->context_size); + Deserializer deserializer(&snapshot_data); Object* root; deserializer.DeserializePartial(isolate, &root); CHECK(root->IsContext()); @@ -115,29 +70,10 @@ void SetSnapshotFromFile(StartupData* snapshot_blob) { snapshot_impl_ = new SnapshotImpl; SnapshotByteSource source(reinterpret_cast(snapshot_blob->data), snapshot_blob->raw_size); - bool success = source.GetBlob(&snapshot_impl_->data, &snapshot_impl_->size); - snapshot_impl_->new_space_used = source.GetInt(); - snapshot_impl_->pointer_space_used = source.GetInt(); - snapshot_impl_->data_space_used = source.GetInt(); - snapshot_impl_->code_space_used = source.GetInt(); - snapshot_impl_->map_space_used = source.GetInt(); - snapshot_impl_->cell_space_used = source.GetInt(); - snapshot_impl_->property_cell_space_used = source.GetInt(); - snapshot_impl_->lo_space_used = source.GetInt(); - success &= source.GetBlob(&snapshot_impl_->context_data, &snapshot_impl_->context_size); - snapshot_impl_->context_new_space_used = source.GetInt(); - snapshot_impl_->context_pointer_space_used = source.GetInt(); - snapshot_impl_->context_data_space_used = source.GetInt(); - snapshot_impl_->context_code_space_used = source.GetInt(); - snapshot_impl_->context_map_space_used = source.GetInt(); - snapshot_impl_->context_cell_space_used = source.GetInt(); - snapshot_impl_->context_property_cell_space_used = source.GetInt(); - snapshot_impl_->context_lo_space_used = source.GetInt(); - DCHECK(success); } diff --git a/src/snapshot-source-sink.cc b/src/snapshot-source-sink.cc index 9935ff7396..ec05734e9e 100644 --- a/src/snapshot-source-sink.cc +++ b/src/snapshot-source-sink.cc @@ -13,15 +13,6 @@ namespace v8 { namespace internal { - -SnapshotByteSource::SnapshotByteSource(const byte* array, int length) - : data_(array), length_(length), position_(0) { -} - - -SnapshotByteSource::~SnapshotByteSource() { } - - int32_t SnapshotByteSource::GetUnalignedInt() { DCHECK(position_ < length_); // Require at least one byte left. int32_t answer = data_[position_]; @@ -52,15 +43,17 @@ void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) { if (bytes > 3) Put(static_cast((integer >> 24) & 0xff), "IntPart4"); } -void SnapshotByteSink::PutRaw(byte* data, int number_of_bytes, + +void SnapshotByteSink::PutRaw(const byte* data, int number_of_bytes, const char* description) { - data_.AddAll(Vector(data, number_of_bytes)); + data_.AddAll(Vector(const_cast(data), number_of_bytes)); } -void SnapshotByteSink::PutBlob(byte* data, int number_of_bytes, + +void SnapshotByteSink::PutBlob(Vector blob, const char* description) { - PutInt(number_of_bytes, description); - PutRaw(data, number_of_bytes, description); + PutInt(blob.length(), description); + PutRaw(blob.start(), blob.length(), description); } diff --git a/src/snapshot-source-sink.h b/src/snapshot-source-sink.h index 398276fe5f..f0cf1bb18f 100644 --- a/src/snapshot-source-sink.h +++ b/src/snapshot-source-sink.h @@ -19,8 +19,13 @@ namespace internal { */ class SnapshotByteSource FINAL { public: - SnapshotByteSource(const byte* array, int length); - ~SnapshotByteSource(); + SnapshotByteSource(const byte* data, int length) + : data_(data), length_(length), position_(0) {} + + explicit SnapshotByteSource(Vector payload) + : data_(payload.start()), length_(payload.length()), position_(0) {} + + ~SnapshotByteSource() {} bool HasMore() { return position_ < length_; } @@ -83,8 +88,8 @@ class SnapshotByteSink { } void PutInt(uintptr_t integer, const char* description); - void PutRaw(byte* data, int number_of_bytes, const char* description); - void PutBlob(byte* data, int number_of_bytes, const char* description); + void PutRaw(const byte* data, int number_of_bytes, const char* description); + void PutBlob(Vector blob, const char* description); int Position() { return data_.length(); } const List& data() const { return data_; } diff --git a/src/snapshot.h b/src/snapshot.h index 6d4bf95391..384e655c56 100644 --- a/src/snapshot.h +++ b/src/snapshot.h @@ -23,31 +23,9 @@ class Snapshot { private: static const byte data_[]; - static const byte* raw_data_; - static const byte context_data_[]; - static const byte* context_raw_data_; - static const int new_space_used_; - static const int pointer_space_used_; - static const int data_space_used_; - static const int code_space_used_; - static const int map_space_used_; - static const int cell_space_used_; - static const int property_cell_space_used_; - static const int lo_space_used_; - static const int context_new_space_used_; - static const int context_pointer_space_used_; - static const int context_data_space_used_; - static const int context_code_space_used_; - static const int context_map_space_used_; - static const int context_cell_space_used_; - static const int context_property_cell_space_used_; - static const int context_lo_space_used_; static const int size_; - static const int raw_size_; + static const byte context_data_[]; static const int context_size_; - static const int context_raw_size_; - - static void ReserveSpaceForLinkedInSnapshot(Deserializer* deserializer); DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot); }; diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc index 6abb3845f9..de22a5da68 100644 --- a/test/cctest/test-serialize.cc +++ b/test/cctest/test-serialize.cc @@ -114,7 +114,7 @@ TEST(ExternalReferenceDecoder) { } -void WritePayload(const List& payload, const char* file_name) { +void WritePayload(const Vector& payload, const char* file_name) { FILE* file = v8::base::OS::FOpen(file_name, "wb"); if (file == NULL) { PrintF("Unable to write to snapshot file \"%s\"\n", file_name); @@ -129,50 +129,12 @@ void WritePayload(const List& payload, const char* file_name) { } -void WriteSpaceUsed(Serializer* ser, const char* file_name) { - int file_name_length = StrLength(file_name) + 10; - Vector name = Vector::New(file_name_length + 1); - SNPrintF(name, "%s.size", file_name); - FILE* fp = v8::base::OS::FOpen(name.start(), "w"); - name.Dispose(); - - Vector chunks = ser->FinalAllocationChunks(NEW_SPACE); - CHECK_EQ(1, chunks.length()); - fprintf(fp, "new %d\n", chunks[0]); - chunks = ser->FinalAllocationChunks(OLD_POINTER_SPACE); - CHECK_EQ(1, chunks.length()); - fprintf(fp, "pointer %d\n", chunks[0]); - chunks = ser->FinalAllocationChunks(OLD_DATA_SPACE); - CHECK_EQ(1, chunks.length()); - fprintf(fp, "data %d\n", chunks[0]); - chunks = ser->FinalAllocationChunks(CODE_SPACE); - CHECK_EQ(1, chunks.length()); - fprintf(fp, "code %d\n", chunks[0]); - chunks = ser->FinalAllocationChunks(MAP_SPACE); - CHECK_EQ(1, chunks.length()); - fprintf(fp, "map %d\n", chunks[0]); - chunks = ser->FinalAllocationChunks(CELL_SPACE); - CHECK_EQ(1, chunks.length()); - fprintf(fp, "cell %d\n", chunks[0]); - chunks = ser->FinalAllocationChunks(PROPERTY_CELL_SPACE); - CHECK_EQ(1, chunks.length()); - fprintf(fp, "property cell %d\n", chunks[0]); - chunks = ser->FinalAllocationChunks(LO_SPACE); - CHECK_EQ(1, chunks.length()); - fprintf(fp, "lo %d\n", chunks[0]); - fclose(fp); -} - - static bool WriteToFile(Isolate* isolate, const char* snapshot_file) { SnapshotByteSink sink; StartupSerializer ser(isolate, &sink); ser.Serialize(); - ser.FinalizeAllocation(); - - WritePayload(sink.data(), snapshot_file); - WriteSpaceUsed(&ser, snapshot_file); - + SnapshotData snapshot_data(sink, ser); + WritePayload(snapshot_data.RawData(), snapshot_file); return true; } @@ -220,53 +182,14 @@ UNINITIALIZED_TEST(SerializeTwice) { //---------------------------------------------------------------------------- // Tests that the heap can be deserialized. - -static void ReserveSpaceForSnapshot(Deserializer* deserializer, - const char* file_name) { - int file_name_length = StrLength(file_name) + 10; - Vector name = Vector::New(file_name_length + 1); - SNPrintF(name, "%s.size", file_name); - FILE* fp = v8::base::OS::FOpen(name.start(), "r"); - name.Dispose(); - int new_size, pointer_size, data_size, code_size, map_size, cell_size, - property_cell_size, lo_size; -#if V8_CC_MSVC - // Avoid warning about unsafe fscanf from MSVC. - // Please note that this is only fine if %c and %s are not being used. -#define fscanf fscanf_s -#endif - CHECK_EQ(1, fscanf(fp, "new %d\n", &new_size)); - CHECK_EQ(1, fscanf(fp, "pointer %d\n", &pointer_size)); - CHECK_EQ(1, fscanf(fp, "data %d\n", &data_size)); - CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size)); - CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size)); - CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size)); - CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size)); - CHECK_EQ(1, fscanf(fp, "lo %d\n", &lo_size)); -#if V8_CC_MSVC -#undef fscanf -#endif - fclose(fp); - deserializer->AddReservation(NEW_SPACE, new_size); - deserializer->AddReservation(OLD_POINTER_SPACE, pointer_size); - deserializer->AddReservation(OLD_DATA_SPACE, data_size); - deserializer->AddReservation(CODE_SPACE, code_size); - deserializer->AddReservation(MAP_SPACE, map_size); - deserializer->AddReservation(CELL_SPACE, cell_size); - deserializer->AddReservation(PROPERTY_CELL_SPACE, property_cell_size); - deserializer->AddReservation(LO_SPACE, lo_size); -} - - v8::Isolate* InitializeFromFile(const char* snapshot_file) { int len; byte* str = ReadBytes(snapshot_file, &len); if (!str) return NULL; v8::Isolate* v8_isolate = NULL; { - SnapshotByteSource source(str, len); - Deserializer deserializer(&source); - ReserveSpaceForSnapshot(&deserializer, snapshot_file); + SnapshotData snapshot_data(str, len); + Deserializer deserializer(&snapshot_data); Isolate* isolate = Isolate::NewForTesting(); v8_isolate = reinterpret_cast(isolate); v8::Isolate::Scope isolate_scope(v8_isolate); @@ -436,14 +359,11 @@ UNINITIALIZED_TEST(PartialSerialization) { startup_serializer.SerializeWeakReferences(); - partial_serializer.FinalizeAllocation(); - startup_serializer.FinalizeAllocation(); + SnapshotData startup_snapshot(startup_sink, startup_serializer); + SnapshotData partial_snapshot(partial_sink, partial_serializer); - WritePayload(partial_sink.data(), FLAG_testing_serialization_file); - WritePayload(startup_sink.data(), startup_name.start()); - - WriteSpaceUsed(&partial_serializer, FLAG_testing_serialization_file); - WriteSpaceUsed(&startup_serializer, startup_name.start()); + WritePayload(partial_snapshot.RawData(), FLAG_testing_serialization_file); + WritePayload(startup_snapshot.RawData(), startup_name.start()); startup_name.Dispose(); } @@ -473,9 +393,8 @@ UNINITIALIZED_DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { Isolate* isolate = reinterpret_cast(v8_isolate); Object* root; { - SnapshotByteSource source(snapshot, snapshot_size); - Deserializer deserializer(&source); - ReserveSpaceForSnapshot(&deserializer, file_name); + SnapshotData snapshot_data(snapshot, snapshot_size); + Deserializer deserializer(&snapshot_data); deserializer.DeserializePartial(isolate, &root); CHECK(root->IsString()); } @@ -485,9 +404,8 @@ UNINITIALIZED_DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { Object* root2; { - SnapshotByteSource source(snapshot, snapshot_size); - Deserializer deserializer(&source); - ReserveSpaceForSnapshot(&deserializer, file_name); + SnapshotData snapshot_data(snapshot, snapshot_size); + Deserializer deserializer(&snapshot_data); deserializer.DeserializePartial(isolate, &root2); CHECK(root2->IsString()); CHECK(*root_handle == root2); @@ -552,14 +470,11 @@ UNINITIALIZED_TEST(ContextSerialization) { partial_serializer.Serialize(&raw_context); startup_serializer.SerializeWeakReferences(); - partial_serializer.FinalizeAllocation(); - startup_serializer.FinalizeAllocation(); + SnapshotData startup_snapshot(startup_sink, startup_serializer); + SnapshotData partial_snapshot(partial_sink, partial_serializer); - WritePayload(partial_sink.data(), FLAG_testing_serialization_file); - WritePayload(startup_sink.data(), startup_name.start()); - - WriteSpaceUsed(&partial_serializer, FLAG_testing_serialization_file); - WriteSpaceUsed(&startup_serializer, startup_name.start()); + WritePayload(startup_snapshot.RawData(), FLAG_testing_serialization_file); + WritePayload(startup_snapshot.RawData(), startup_name.start()); startup_name.Dispose(); } @@ -588,9 +503,8 @@ UNINITIALIZED_DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { Isolate* isolate = reinterpret_cast(v8_isolate); Object* root; { - SnapshotByteSource source(snapshot, snapshot_size); - Deserializer deserializer(&source); - ReserveSpaceForSnapshot(&deserializer, file_name); + SnapshotData snapshot_data(snapshot, snapshot_size); + Deserializer deserializer(&snapshot_data); deserializer.DeserializePartial(isolate, &root); CHECK(root->IsContext()); } @@ -600,9 +514,8 @@ UNINITIALIZED_DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { Object* root2; { - SnapshotByteSource source(snapshot, snapshot_size); - Deserializer deserializer(&source); - ReserveSpaceForSnapshot(&deserializer, file_name); + SnapshotData snapshot_data(snapshot, snapshot_size); + Deserializer deserializer(&snapshot_data); deserializer.DeserializePartial(isolate, &root2); CHECK(root2->IsContext()); CHECK(*root_handle != root2);