Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(432)

Unified Diff: src/serialize.cc

Issue 781443002: Encode reservation meta data in the snapshot blob. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@snapshotformat
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/serialize.h ('K') | « src/serialize.h ('k') | src/snapshot.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/serialize.cc
diff --git a/src/serialize.cc b/src/serialize.cc
index 8464bc86a9abeee479b8506540dd5a52edbf7559..699448c133324d0f8438874813d456bf231ada52 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -611,12 +611,21 @@ class CodeAddressMap: public CodeEventLogger {
};
-Deserializer::Deserializer(SnapshotByteSource* source)
+Deserializer::Deserializer(SerializedData* sd)
: isolate_(NULL),
attached_objects_(NULL),
- source_(source),
+ source_(sd->Payload()),
external_reference_decoder_(NULL),
deserialized_large_objects_(0) {
+ // Set reservations.
+ STATIC_ASSERT(NEW_SPACE == 0);
+ int current_space = NEW_SPACE;
+ Vector<const SerializedData::Reservation> res = sd->Reservations();
+ 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 +725,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;
@@ -810,12 +819,12 @@ Object* Deserializer::ProcessBackRefInSerializedCode(Object* obj) {
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);
@@ -832,7 +841,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);
@@ -870,7 +879,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);
@@ -904,7 +913,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
source_space != CODE_SPACE &&
source_space != OLD_DATA_SPACE);
while (current < limit) {
- int data = source_->Get();
+ int data = source_.Get();
switch (data) {
#define CASE_STATEMENT(where, how, within, space_number) \
case where + how + within + space_number: \
@@ -928,18 +937,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) { \
@@ -950,7 +959,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
} \
} 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); \
@@ -958,12 +967,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); \
@@ -1070,23 +1079,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;
}
@@ -1102,7 +1110,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];
@@ -1112,7 +1120,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
}
case kRepeat: {
- 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;
@@ -1230,14 +1238,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(),
@@ -1248,7 +1256,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];
@@ -1363,15 +1371,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.
+ 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) {
- completed_chunks_[i].Add(pending_chunk_[i]);
- pending_chunk_[i] = 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();
}
@@ -1663,7 +1677,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.
@@ -1960,6 +1974,7 @@ BackReference Serializer::Allocate(AllocationSpace space, int size) {
sink_->Put(kNextChunk, "move to next chunk");
sink_->Put(space, "space of next chunk");
completed_chunks_[space].Add(pending_chunk_[space]);
+ DCHECK_LE(completed_chunks_[space].length(), BackReference::kMaxChunkIndex);
pending_chunk_[space] = 0;
new_chunk_size = size;
}
@@ -2004,16 +2019,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) {
@@ -2240,23 +2247,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(
@@ -2266,6 +2261,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.
@@ -2301,23 +2298,64 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
}
+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;
+ size_ = kHeaderSize + reservation_size + payload.length();
+
+ // Allocate backing store and create result data.
+ data_ = NewArray<byte>(size_);
vogelheim 2014/12/03 18:49:25 Related to the comment in serialize.h: I was tryi
Yang 2014/12/04 08:51:43 I moved allocation into a helper method in the par
+ DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment));
+
+ // 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,
- CodeSerializer* cs)
- : data_(NULL), size_(0), owns_script_data_(true) {
+ const CodeSerializer& cs) {
DisallowHeapAllocation no_gc;
- List<uint32_t>* stub_keys = cs->stub_keys();
+ const List<uint32_t>* stub_keys = cs.stub_keys();
- // 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);
- }
- }
+ List<Reservation> reservations;
+ cs.EncodeReservations(&reservations);
// Calculate sizes.
int reservation_size = reservations.length() * kInt32Size;
@@ -2330,8 +2368,8 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment));
// 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());
@@ -2352,11 +2390,52 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
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;
+ return result;
vogelheim 2014/12/03 18:49:25 Is this expected to the last method call on a part
Yang 2014/12/04 08:51:43 Done.
+}
+
+
+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
« src/serialize.h ('K') | « src/serialize.h ('k') | src/snapshot.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698