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
This commit is contained in:
parent
8207788047
commit
4a90166dde
@ -554,11 +554,10 @@ ExternalReferenceDecoder::~ExternalReferenceDecoder() {
|
|||||||
|
|
||||||
bool Serializer::serialization_enabled_ = false;
|
bool Serializer::serialization_enabled_ = false;
|
||||||
bool Serializer::too_late_to_enable_now_ = false;
|
bool Serializer::too_late_to_enable_now_ = false;
|
||||||
|
ExternalReferenceDecoder* Deserializer::external_reference_decoder_ = NULL;
|
||||||
|
|
||||||
|
|
||||||
Deserializer::Deserializer(SnapshotByteSource* source)
|
Deserializer::Deserializer(SnapshotByteSource* source) : source_(source) {
|
||||||
: source_(source),
|
|
||||||
external_reference_decoder_(NULL) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -648,9 +647,27 @@ void Deserializer::Deserialize() {
|
|||||||
external_reference_decoder_ = new ExternalReferenceDecoder();
|
external_reference_decoder_ = new ExternalReferenceDecoder();
|
||||||
Heap::IterateRoots(this, VISIT_ONLY_STRONG);
|
Heap::IterateRoots(this, VISIT_ONLY_STRONG);
|
||||||
ASSERT(source_->AtEOF());
|
ASSERT(source_->AtEOF());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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_;
|
delete external_reference_decoder_;
|
||||||
external_reference_decoder_ = NULL;
|
external_reference_decoder_ = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// This is called on the roots. It is the driver of the deserialization
|
// This is called on the roots. It is the driver of the deserialization
|
||||||
@ -862,6 +879,11 @@ void Deserializer::ReadChunk(Object** current,
|
|||||||
*current++ = reinterpret_cast<Object*>(resource);
|
*current++ = reinterpret_cast<Object*>(resource);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ROOT_SERIALIZATION: {
|
||||||
|
int root_id = source_->GetInt();
|
||||||
|
*current++ = Heap::roots_address()[root_id];
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -915,7 +937,8 @@ Serializer::Serializer(SnapshotByteSink* sink)
|
|||||||
: sink_(sink),
|
: sink_(sink),
|
||||||
current_root_index_(0),
|
current_root_index_(0),
|
||||||
external_reference_encoder_(NULL),
|
external_reference_encoder_(NULL),
|
||||||
partial_(false) {
|
partial_(false),
|
||||||
|
large_object_total_(0) {
|
||||||
for (int i = 0; i <= LAST_SPACE; i++) {
|
for (int i = 0; i <= LAST_SPACE; i++) {
|
||||||
fullness_[i] = 0;
|
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
|
// In large object space we merely number the objects instead of trying to
|
||||||
// determine some sort of address.
|
// determine some sort of address.
|
||||||
*new_page = true;
|
*new_page = true;
|
||||||
|
large_object_total_ += size;
|
||||||
return fullness_[LO_SPACE]++;
|
return fullness_[LO_SPACE]++;
|
||||||
}
|
}
|
||||||
*new_page = false;
|
*new_page = false;
|
||||||
|
@ -239,10 +239,16 @@ class Deserializer: public SerDes {
|
|||||||
|
|
||||||
// Deserialize the snapshot into an empty heap.
|
// Deserialize the snapshot into an empty heap.
|
||||||
void Deserialize();
|
void Deserialize();
|
||||||
|
|
||||||
|
// Deserialize a single object and the objects reachable from it.
|
||||||
|
void DeserializePartial(Object** root);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
virtual void Synchronize(const char* tag);
|
virtual void Synchronize(const char* tag);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void TearDown();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void VisitPointers(Object** start, Object** end);
|
virtual void VisitPointers(Object** start, Object** end);
|
||||||
|
|
||||||
@ -267,7 +273,7 @@ class Deserializer: public SerDes {
|
|||||||
List<Address> pages_[SerDes::kNumberOfSpaces];
|
List<Address> pages_[SerDes::kNumberOfSpaces];
|
||||||
|
|
||||||
SnapshotByteSource* source_;
|
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
|
// 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.
|
// space. It is used to calculate the addresses of back-references.
|
||||||
Address high_water_[LAST_SPACE + 1];
|
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
|
// You can call this after serialization to find out how much space was used
|
||||||
// in each space.
|
// in each space.
|
||||||
int CurrentAllocationAddress(int space) {
|
int CurrentAllocationAddress(int space) {
|
||||||
if (SpaceIsLarge(space)) space = LO_SPACE;
|
if (SpaceIsLarge(space)) return large_object_total_;
|
||||||
return fullness_[space];
|
return fullness_[space];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,6 +398,7 @@ class Serializer : public SerDes {
|
|||||||
static bool serialization_enabled_;
|
static bool serialization_enabled_;
|
||||||
// Did we already make use of the fact that serialization was not enabled?
|
// Did we already make use of the fact that serialization was not enabled?
|
||||||
static bool too_late_to_enable_now_;
|
static bool too_late_to_enable_now_;
|
||||||
|
int large_object_total_;
|
||||||
|
|
||||||
friend class ObjectSerializer;
|
friend class ObjectSerializer;
|
||||||
friend class Deserializer;
|
friend class Deserializer;
|
||||||
|
@ -146,6 +146,7 @@ void V8::TearDown() {
|
|||||||
|
|
||||||
Heap::TearDown();
|
Heap::TearDown();
|
||||||
Logger::TearDown();
|
Logger::TearDown();
|
||||||
|
Deserializer::TearDown();
|
||||||
|
|
||||||
is_running_ = false;
|
is_running_ = false;
|
||||||
has_been_disposed_ = true;
|
has_been_disposed_ = true;
|
||||||
|
@ -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
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
@ -277,6 +277,7 @@ class FileByteSink : public SnapshotByteSink {
|
|||||||
public:
|
public:
|
||||||
explicit FileByteSink(const char* snapshot_file) {
|
explicit FileByteSink(const char* snapshot_file) {
|
||||||
fp_ = OS::FOpen(snapshot_file, "wb");
|
fp_ = OS::FOpen(snapshot_file, "wb");
|
||||||
|
file_name_ = snapshot_file;
|
||||||
if (fp_ == NULL) {
|
if (fp_ == NULL) {
|
||||||
PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
|
PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -292,12 +293,44 @@ class FileByteSink : public SnapshotByteSink {
|
|||||||
fputc(byte, fp_);
|
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:
|
private:
|
||||||
FILE* fp_;
|
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<char> name = Vector<char>::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) {
|
TEST(PartialSerialization) {
|
||||||
Serializer::Enable();
|
Serializer::Enable();
|
||||||
v8::V8::Initialize();
|
v8::V8::Initialize();
|
||||||
@ -312,6 +345,47 @@ TEST(PartialSerialization) {
|
|||||||
i::Handle<i::String> internal_foo = v8::Utils::OpenHandle(*foo);
|
i::Handle<i::String> internal_foo = v8::Utils::OpenHandle(*foo);
|
||||||
Object* raw_foo = *internal_foo;
|
Object* raw_foo = *internal_foo;
|
||||||
ser.SerializePartial(&raw_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<char> name = Vector<char>::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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user