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

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: rebased 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
« no previous file with comments | « 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 e6aae7fe8de90260da6f3e1e1463ab3544de8cea..f0bd68e659bc1a0377011bce6b544e2dcdc61ed5 100644
--- a/src/serialize.cc
+++ b/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.
+ 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();
}
@@ -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(
}
+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));
+}
+
+
+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,
- CodeSerializer* cs)
- : script_data_(NULL), 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;
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
« no previous file with comments | « src/serialize.h ('k') | src/snapshot.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698