From 4a90166dde4e67369d3b1aa8ba6c374e081ddbd0 Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Fri, 15 Jan 2010 14:20:31 +0000 Subject: [PATCH] Implement enough of the partial snapshots that we can deserialize a single string. Review URL: http://codereview.chromium.org/536077 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3619 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/serialize.cc | 36 ++++++++++++++++---- src/serialize.h | 11 +++++-- src/v8.cc | 1 + test/cctest/test-serialize.cc | 76 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 115 insertions(+), 9 deletions(-) diff --git a/src/serialize.cc b/src/serialize.cc index ef263fd..de2fb8e 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -554,11 +554,10 @@ ExternalReferenceDecoder::~ExternalReferenceDecoder() { bool Serializer::serialization_enabled_ = false; bool Serializer::too_late_to_enable_now_ = false; +ExternalReferenceDecoder* Deserializer::external_reference_decoder_ = NULL; -Deserializer::Deserializer(SnapshotByteSource* source) - : source_(source), - external_reference_decoder_(NULL) { +Deserializer::Deserializer(SnapshotByteSource* source) : source_(source) { } @@ -648,8 +647,26 @@ void Deserializer::Deserialize() { external_reference_decoder_ = new ExternalReferenceDecoder(); Heap::IterateRoots(this, VISIT_ONLY_STRONG); ASSERT(source_->AtEOF()); - delete external_reference_decoder_; - external_reference_decoder_ = NULL; +} + + +void Deserializer::DeserializePartial(Object** root) { + // Don't GC while deserializing - just expand the heap. + AlwaysAllocateScope always_allocate; + // Don't use the free lists while deserializing. + LinearAllocationScope allocate_linearly; + if (external_reference_decoder_ == NULL) { + external_reference_decoder_ = new ExternalReferenceDecoder(); + } + VisitPointer(root); +} + + +void Deserializer::TearDown() { + if (external_reference_decoder_ != NULL) { + delete external_reference_decoder_; + external_reference_decoder_ = NULL; + } } @@ -862,6 +879,11 @@ void Deserializer::ReadChunk(Object** current, *current++ = reinterpret_cast(resource); break; } + case ROOT_SERIALIZATION: { + int root_id = source_->GetInt(); + *current++ = Heap::roots_address()[root_id]; + break; + } default: UNREACHABLE(); } @@ -915,7 +937,8 @@ Serializer::Serializer(SnapshotByteSink* sink) : sink_(sink), current_root_index_(0), external_reference_encoder_(NULL), - partial_(false) { + partial_(false), + large_object_total_(0) { for (int i = 0; i <= LAST_SPACE; i++) { fullness_[i] = 0; } @@ -1226,6 +1249,7 @@ int Serializer::Allocate(int space, int size, bool* new_page) { // In large object space we merely number the objects instead of trying to // determine some sort of address. *new_page = true; + large_object_total_ += size; return fullness_[LO_SPACE]++; } *new_page = false; diff --git a/src/serialize.h b/src/serialize.h index b32f4e8..fcd3723 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -239,10 +239,16 @@ class Deserializer: public SerDes { // Deserialize the snapshot into an empty heap. void Deserialize(); + + // Deserialize a single object and the objects reachable from it. + void DeserializePartial(Object** root); + #ifdef DEBUG virtual void Synchronize(const char* tag); #endif + static void TearDown(); + private: virtual void VisitPointers(Object** start, Object** end); @@ -267,7 +273,7 @@ class Deserializer: public SerDes { List
pages_[SerDes::kNumberOfSpaces]; SnapshotByteSource* source_; - ExternalReferenceDecoder* external_reference_decoder_; + static ExternalReferenceDecoder* external_reference_decoder_; // This is the address of the next object that will be allocated in each // space. It is used to calculate the addresses of back-references. Address high_water_[LAST_SPACE + 1]; @@ -302,7 +308,7 @@ class Serializer : public SerDes { // You can call this after serialization to find out how much space was used // in each space. int CurrentAllocationAddress(int space) { - if (SpaceIsLarge(space)) space = LO_SPACE; + if (SpaceIsLarge(space)) return large_object_total_; return fullness_[space]; } @@ -392,6 +398,7 @@ class Serializer : public SerDes { static bool serialization_enabled_; // Did we already make use of the fact that serialization was not enabled? static bool too_late_to_enable_now_; + int large_object_total_; friend class ObjectSerializer; friend class Deserializer; diff --git a/src/v8.cc b/src/v8.cc index 3bec827..db570a4 100644 --- a/src/v8.cc +++ b/src/v8.cc @@ -146,6 +146,7 @@ void V8::TearDown() { Heap::TearDown(); Logger::TearDown(); + Deserializer::TearDown(); is_running_ = false; has_been_disposed_ = true; diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc index 9961281..94b741c 100644 --- a/test/cctest/test-serialize.cc +++ b/test/cctest/test-serialize.cc @@ -1,4 +1,4 @@ -// Copyright 2007-2008 the V8 project authors. All rights reserved. +// Copyright 2007-2010 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -277,6 +277,7 @@ class FileByteSink : public SnapshotByteSink { public: explicit FileByteSink(const char* snapshot_file) { fp_ = OS::FOpen(snapshot_file, "wb"); + file_name_ = snapshot_file; if (fp_ == NULL) { PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file); exit(1); @@ -292,12 +293,44 @@ class FileByteSink : public SnapshotByteSink { fputc(byte, fp_); } } + void WriteSpaceUsed( + 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 large_space_used); private: FILE* fp_; + const char* file_name_; }; +void FileByteSink::WriteSpaceUsed( + 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 large_space_used) { + int file_name_length = strlen(file_name_) + 10; + Vector name = Vector::New(file_name_length + 1); + OS::SNPrintF(name, "%s.size", file_name_); + FILE* fp = OS::FOpen(name.start(), "wa"); + fprintf(fp, "new %d\n", new_space_used); + fprintf(fp, "pointer %d\n", pointer_space_used); + fprintf(fp, "data %d\n", data_space_used); + fprintf(fp, "code %d\n", code_space_used); + fprintf(fp, "map %d\n", map_space_used); + fprintf(fp, "cell %d\n", cell_space_used); + fprintf(fp, "large %d\n", large_space_used); + fclose(fp); +} + + TEST(PartialSerialization) { Serializer::Enable(); v8::V8::Initialize(); @@ -312,6 +345,47 @@ TEST(PartialSerialization) { i::Handle internal_foo = v8::Utils::OpenHandle(*foo); Object* raw_foo = *internal_foo; ser.SerializePartial(&raw_foo); + file.WriteSpaceUsed(ser.CurrentAllocationAddress(NEW_SPACE), + ser.CurrentAllocationAddress(OLD_POINTER_SPACE), + ser.CurrentAllocationAddress(OLD_DATA_SPACE), + ser.CurrentAllocationAddress(CODE_SPACE), + ser.CurrentAllocationAddress(MAP_SPACE), + ser.CurrentAllocationAddress(CELL_SPACE), + ser.CurrentAllocationAddress(LO_SPACE)); +} + + +DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { + v8::V8::Initialize(); + const char* file_name = FLAG_testing_serialization_file; + int file_name_length = strlen(file_name) + 10; + Vector name = Vector::New(file_name_length + 1); + OS::SNPrintF(name, "%s.size", file_name); + FILE* fp = OS::FOpen(name.start(), "ra"); + int new_size, pointer_size, data_size, code_size, map_size, cell_size; + int large_size; + 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, "large %d\n", &large_size)); + fclose(fp); + Heap::ReserveSpace(new_size, + pointer_size, + data_size, + code_size, + map_size, + cell_size, + large_size); + int snapshot_size = 0; + byte* snapshot = ReadBytes(file_name, &snapshot_size); + SnapshotByteSource source(snapshot, snapshot_size); + Deserializer deserializer(&source); + Object* root; + deserializer.DeserializePartial(&root); + CHECK(root->IsString()); } -- 2.7.4