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::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,9 +647,27 @@ void Deserializer::Deserialize() {
|
||||
external_reference_decoder_ = new ExternalReferenceDecoder();
|
||||
Heap::IterateRoots(this, VISIT_ONLY_STRONG);
|
||||
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_;
|
||||
external_reference_decoder_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
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;
|
||||
|
@ -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<Address> 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;
|
||||
|
@ -146,6 +146,7 @@ void V8::TearDown() {
|
||||
|
||||
Heap::TearDown();
|
||||
Logger::TearDown();
|
||||
Deserializer::TearDown();
|
||||
|
||||
is_running_ = false;
|
||||
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
|
||||
// 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<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) {
|
||||
Serializer::Enable();
|
||||
v8::V8::Initialize();
|
||||
@ -312,6 +345,47 @@ TEST(PartialSerialization) {
|
||||
i::Handle<i::String> 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<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