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}
This commit is contained in:
parent
b991ece9ac
commit
aa3ceb8b71
@ -20,24 +20,13 @@
|
||||
|
||||
using namespace v8;
|
||||
|
||||
|
||||
class Compressor {
|
||||
public:
|
||||
virtual ~Compressor() {}
|
||||
virtual bool Compress(i::Vector<i::byte> input) = 0;
|
||||
virtual i::Vector<i::byte>* 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<i::byte>& snapshot_data,
|
||||
const i::Serializer& serializer,
|
||||
const i::List<i::byte>& 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<i::byte>& snapshot_data,
|
||||
const i::Serializer& serializer,
|
||||
const i::List<i::byte>& 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<const uint32_t> 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<const uint32_t> 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<i::byte>& 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<i::byte>& snapshot_data,
|
||||
const i::Serializer& serializer,
|
||||
const i::List<i::byte>& 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<i::byte>& source_data,
|
||||
void WriteData(const char* prefix,
|
||||
const i::Vector<const i::byte>& source_data,
|
||||
FILE* raw_file) const {
|
||||
const i::List<i::byte>* data_to_be_written = NULL;
|
||||
i::List<i::byte> 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<i::byte>* data, FILE* raw_file) const {
|
||||
if (!data || !raw_file)
|
||||
return;
|
||||
void MaybeWriteRawFile(const i::Vector<const i::byte>* 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<size_t>(data->length())) {
|
||||
i::PrintF("Writing raw file failed.. Aborting.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteData(const char* prefix, const i::List<i::byte>& source_data,
|
||||
const i::List<i::byte>* data_to_be_written) const {
|
||||
void WriteData(const char* prefix,
|
||||
const i::Vector<const i::byte>& 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<const uint32_t> 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<i::byte>* 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<unsigned char>(data->at(i)));
|
||||
void WriteSnapshotData(const i::Vector<const i::byte>& 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<unsigned char>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,9 +147,8 @@ void SetNativesFromFile(StartupData* natives_blob) {
|
||||
DCHECK(natives_blob->data);
|
||||
DCHECK(natives_blob->raw_size > 0);
|
||||
|
||||
SnapshotByteSource bytes(
|
||||
reinterpret_cast<const byte*>(natives_blob->data),
|
||||
natives_blob->raw_size);
|
||||
SnapshotByteSource bytes(reinterpret_cast<const byte*>(natives_blob->data),
|
||||
natives_blob->raw_size);
|
||||
NativesHolder<CORE>::set(NativesStore::MakeFromScriptsSource(&bytes));
|
||||
NativesHolder<EXPERIMENTAL>::set(NativesStore::MakeFromScriptsSource(&bytes));
|
||||
DCHECK(!bytes.HasMore());
|
||||
|
265
src/serialize.cc
265
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<const SerializedData::Reservation> 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<Object**>(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<Executability>(source_->Get());
|
||||
Executability exec = static_cast<Executability>(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<Object**>( \
|
||||
reinterpret_cast<Address>(current) + skip); \
|
||||
int reference_id = source_->GetInt(); \
|
||||
int reference_id = source_.GetInt(); \
|
||||
Address address = external_reference_decoder_->Decode(reference_id); \
|
||||
new_object = reinterpret_cast<Object*>(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<Builtins::Name>(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<Object**>( \
|
||||
reinterpret_cast<Address>(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<byte*>(current); \
|
||||
source_->CopyRaw(raw_data_out, index * kPointerSize); \
|
||||
current = \
|
||||
reinterpret_cast<Object**>(raw_data_out + index * kPointerSize); \
|
||||
break; \
|
||||
}
|
||||
#define RAW_CASE(index) \
|
||||
case kRawData + index: { \
|
||||
byte* raw_data_out = reinterpret_cast<byte*>(current); \
|
||||
source_.CopyRaw(raw_data_out, index* kPointerSize); \
|
||||
current = reinterpret_cast<Object**>(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<byte*>(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<Object**>(
|
||||
reinterpret_cast<intptr_t>(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<Object**>(
|
||||
reinterpret_cast<intptr_t>(current) + size);
|
||||
break;
|
||||
}
|
||||
|
||||
case kNativesStringResource: {
|
||||
int index = source_->Get();
|
||||
int index = source_.Get();
|
||||
Vector<const char> 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<Object**>(
|
||||
reinterpret_cast<Address>(current) + skip);
|
||||
// Fall through.
|
||||
@ -1394,15 +1397,21 @@ void Serializer::VisitPointers(Object** start, Object** end) {
|
||||
}
|
||||
|
||||
|
||||
void Serializer::FinalizeAllocation() {
|
||||
void Serializer::EncodeReservations(
|
||||
List<SerializedData::Reservation>* 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<byte*>(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<Object>::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<SharedFunctionInfo> CodeSerializer::Deserialize(
|
||||
DCHECK(cached_data->rejected());
|
||||
return MaybeHandle<SharedFunctionInfo>();
|
||||
}
|
||||
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<const SerializedCodeData::Reservation> 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<const uint32_t> code_stub_keys = scd->CodeStubKeys();
|
||||
Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
|
||||
@ -2301,6 +2291,8 @@ MaybeHandle<SharedFunctionInfo> 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<SharedFunctionInfo> CodeSerializer::Deserialize(
|
||||
}
|
||||
|
||||
|
||||
SerializedCodeData::SerializedCodeData(const List<byte>& payload,
|
||||
CodeSerializer* cs)
|
||||
: script_data_(NULL), owns_script_data_(true) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
List<uint32_t>* stub_keys = cs->stub_keys();
|
||||
void SerializedData::AllocateData(int size) {
|
||||
DCHECK(!owns_data_);
|
||||
data_ = NewArray<byte>(size);
|
||||
size_ = size;
|
||||
owns_data_ = true;
|
||||
DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment));
|
||||
}
|
||||
|
||||
// Gather reservation chunk sizes.
|
||||
List<uint32_t> reservations(SerializerDeserializer::kNumberOfSpaces);
|
||||
STATIC_ASSERT(NEW_SPACE == 0);
|
||||
for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) {
|
||||
Vector<const uint32_t> 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<Reservation> reservations;
|
||||
ser.EncodeReservations(&reservations);
|
||||
const List<byte>& 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<byte*>(reservations.begin()),
|
||||
reservation_size);
|
||||
|
||||
// Copy serialized data.
|
||||
CopyBytes(data_ + kHeaderSize + reservation_size, payload.begin(),
|
||||
static_cast<size_t>(payload.length()));
|
||||
}
|
||||
|
||||
|
||||
bool SnapshotData::IsSane() {
|
||||
return GetHeaderValue(kCheckSumOffset) == Version::Hash();
|
||||
}
|
||||
|
||||
|
||||
Vector<const SerializedData::Reservation> SnapshotData::Reservations() const {
|
||||
return Vector<const Reservation>(
|
||||
reinterpret_cast<const Reservation*>(data_ + kHeaderSize),
|
||||
GetHeaderValue(kReservationsOffset));
|
||||
}
|
||||
|
||||
|
||||
Vector<const byte> 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<const byte>(payload, length);
|
||||
}
|
||||
|
||||
|
||||
SerializedCodeData::SerializedCodeData(const List<byte>& payload,
|
||||
const CodeSerializer& cs) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
const List<uint32_t>* stub_keys = cs.stub_keys();
|
||||
|
||||
List<Reservation> 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<byte>(data_length);
|
||||
DCHECK(IsAligned(reinterpret_cast<intptr_t>(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<byte*>(reservations.begin()),
|
||||
CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()),
|
||||
reservation_size);
|
||||
|
||||
// Copy code stub keys.
|
||||
CopyBytes(data + kHeaderSize + reservation_size,
|
||||
CopyBytes(data_ + kHeaderSize + reservation_size,
|
||||
reinterpret_cast<byte*>(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<size_t>(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<const SerializedData::Reservation> SerializedCodeData::Reservations()
|
||||
const {
|
||||
return Vector<const Reservation>(
|
||||
reinterpret_cast<const Reservation*>(data_ + kHeaderSize),
|
||||
GetHeaderValue(kReservationsOffset));
|
||||
}
|
||||
|
||||
|
||||
Vector<const byte> 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<const byte>(payload, length);
|
||||
}
|
||||
|
||||
|
||||
int SerializedCodeData::NumInternalizedStrings() const {
|
||||
return GetHeaderValue(kNumInternalizedStringsOffset);
|
||||
}
|
||||
|
||||
Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const {
|
||||
int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size;
|
||||
const byte* start = data_ + kHeaderSize + reservations_size;
|
||||
return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start),
|
||||
GetHeaderValue(kNumCodeStubKeysOffset));
|
||||
}
|
||||
} } // namespace v8::internal
|
||||
|
198
src/serialize.h
198
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<byte>(data_);
|
||||
}
|
||||
|
||||
class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
|
||||
class IsLastChunkBits : public BitField<bool, 31, 1> {};
|
||||
|
||||
protected:
|
||||
void SetHeaderValue(int offset, int value) {
|
||||
reinterpret_cast<int*>(data_)[offset] = value;
|
||||
}
|
||||
|
||||
int GetHeaderValue(int offset) const {
|
||||
return reinterpret_cast<const int*>(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 <class Data>
|
||||
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<const SerializedData::Reservation> 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<Handle<Object> >* 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<const uint32_t> FinalAllocationChunks(int space) const {
|
||||
if (space == LO_SPACE) {
|
||||
return Vector<const uint32_t>(&large_objects_total_size_, 1);
|
||||
} else {
|
||||
DCHECK_EQ(0, pending_chunk_[space]); // No pending chunks.
|
||||
return completed_chunks_[space].ToConstVector();
|
||||
}
|
||||
}
|
||||
void EncodeReservations(List<SerializedData::Reservation>* out) const;
|
||||
|
||||
Isolate* isolate() const { return isolate_; }
|
||||
|
||||
@ -782,7 +821,7 @@ class CodeSerializer : public Serializer {
|
||||
return source_;
|
||||
}
|
||||
|
||||
List<uint32_t>* stub_keys() { return &stub_keys_; }
|
||||
const List<uint32_t>* 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<byte*>(data), size) {
|
||||
CHECK(IsSane());
|
||||
}
|
||||
|
||||
Vector<const Reservation> Reservations() const;
|
||||
Vector<const byte> Payload() const;
|
||||
|
||||
Vector<const byte> RawData() const {
|
||||
return Vector<const byte>(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<byte>& payload, CodeSerializer* cs);
|
||||
|
||||
~SerializedCodeData() {
|
||||
if (owns_script_data_) delete script_data_;
|
||||
}
|
||||
SerializedCodeData(const List<byte>& 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<const Reservation> Reservations() const;
|
||||
Vector<const byte> Payload() const;
|
||||
|
||||
private:
|
||||
uint32_t reservation;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Reservation);
|
||||
};
|
||||
|
||||
int NumInternalizedStrings() const {
|
||||
return GetHeaderValue(kNumInternalizedStringsOffset);
|
||||
}
|
||||
|
||||
Vector<const Reservation> Reservations() const {
|
||||
return Vector<const Reservation>(reinterpret_cast<const Reservation*>(
|
||||
script_data_->data() + kHeaderSize),
|
||||
GetHeaderValue(kReservationsOffset));
|
||||
}
|
||||
|
||||
Vector<const uint32_t> CodeStubKeys() const {
|
||||
int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size;
|
||||
const byte* start = script_data_->data() + kHeaderSize + reservations_size;
|
||||
return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(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<const uint32_t> CodeStubKeys() const;
|
||||
|
||||
private:
|
||||
explicit SerializedCodeData(ScriptData* data)
|
||||
: script_data_(data), owns_script_data_(false) {}
|
||||
|
||||
void SetHeaderValue(int offset, int value) {
|
||||
reinterpret_cast<int*>(const_cast<byte*>(script_data_->data()))[offset] =
|
||||
value;
|
||||
}
|
||||
|
||||
int GetHeaderValue(int offset) const {
|
||||
return reinterpret_cast<const int*>(script_data_->data())[offset];
|
||||
}
|
||||
: SerializedData(const_cast<byte*>(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<uint32_t, 0, 31> {};
|
||||
class IsLastChunkBits : public BitField<bool, 31, 1> {};
|
||||
|
||||
// Following the header, we store, in sequential order
|
||||
// - code stub keys
|
||||
// - serialization payload
|
||||
|
||||
ScriptData* script_data_;
|
||||
bool owns_script_data_;
|
||||
};
|
||||
} } // namespace v8::internal
|
||||
|
||||
|
@ -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<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
|
||||
if (context_size_ == 0) {
|
||||
return Handle<Context>();
|
||||
}
|
||||
SnapshotByteSource source(context_raw_data_,
|
||||
context_raw_size_);
|
||||
Deserializer deserializer(&source);
|
||||
if (context_size_ == 0) return Handle<Context>();
|
||||
|
||||
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>(Context::cast(root));
|
||||
|
@ -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
|
||||
|
@ -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<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
|
||||
if (!HaveASnapshotToStartFrom())
|
||||
return Handle<Context>();
|
||||
if (!HaveASnapshotToStartFrom()) return Handle<Context>();
|
||||
|
||||
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<const byte*>(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);
|
||||
}
|
||||
|
||||
|
@ -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<int>((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<byte>(data, number_of_bytes));
|
||||
data_.AddAll(Vector<byte>(const_cast<byte*>(data), number_of_bytes));
|
||||
}
|
||||
|
||||
void SnapshotByteSink::PutBlob(byte* data, int number_of_bytes,
|
||||
|
||||
void SnapshotByteSink::PutBlob(Vector<const byte> 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<const byte> 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<const byte> blob, const char* description);
|
||||
int Position() { return data_.length(); }
|
||||
|
||||
const List<byte>& data() const { return data_; }
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -114,7 +114,7 @@ TEST(ExternalReferenceDecoder) {
|
||||
}
|
||||
|
||||
|
||||
void WritePayload(const List<byte>& payload, const char* file_name) {
|
||||
void WritePayload(const Vector<const byte>& 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<byte>& payload, const char* file_name) {
|
||||
}
|
||||
|
||||
|
||||
void WriteSpaceUsed(Serializer* ser, const char* file_name) {
|
||||
int file_name_length = StrLength(file_name) + 10;
|
||||
Vector<char> name = Vector<char>::New(file_name_length + 1);
|
||||
SNPrintF(name, "%s.size", file_name);
|
||||
FILE* fp = v8::base::OS::FOpen(name.start(), "w");
|
||||
name.Dispose();
|
||||
|
||||
Vector<const uint32_t> 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<char> name = Vector<char>::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<v8::Isolate*>(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<Isolate*>(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<Isolate*>(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);
|
||||
|
Loading…
Reference in New Issue
Block a user