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

Unified Diff: src/serialize.cc

Issue 654243003: Revert "Break deserializer reservations into chunks that fit onto a page." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 2 months 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-common.cc » ('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 4c9675e43f5275ac69d5446cabcc11905b5e3f0f..42ca6b9b228c1055f26f4e34e8ee84a000a62e80 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -598,7 +598,9 @@ Deserializer::Deserializer(SnapshotByteSource* source)
source_(source),
external_reference_decoder_(NULL),
deserialized_large_objects_(0) {
- for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0;
+ for (int i = 0; i < kNumberOfSpaces; i++) {
+ reservations_[i] = kUninitializedReservation;
+ }
}
@@ -611,19 +613,10 @@ void Deserializer::FlushICacheForNewCodeObjects() {
}
-bool Deserializer::ReserveSpace() {
- if (!isolate_->heap()->ReserveSpace(reservations_)) return false;
- for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
- high_water_[i] = reservations_[i][0].start;
- }
- return true;
-}
-
-
void Deserializer::Deserialize(Isolate* isolate) {
isolate_ = isolate;
DCHECK(isolate_ != NULL);
- if (!ReserveSpace()) FatalProcessOutOfMemory("deserializing context");
+ isolate_->heap()->ReserveSpace(reservations_, high_water_);
// No active threads.
DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
// No active handles.
@@ -665,17 +658,13 @@ void Deserializer::Deserialize(Isolate* isolate) {
}
-void Deserializer::DeserializePartial(Isolate* isolate, Object** root,
- OnOOM on_oom) {
+void Deserializer::DeserializePartial(Isolate* isolate, Object** root) {
isolate_ = isolate;
for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
- DCHECK(reservations_[i].length() > 0);
- }
- if (!ReserveSpace()) {
- if (on_oom == FATAL_ON_OOM) FatalProcessOutOfMemory("deserialize context");
- *root = NULL;
- return;
+ DCHECK(reservations_[i] != kUninitializedReservation);
}
+ Heap* heap = isolate->heap();
+ heap->ReserveSpace(reservations_, high_water_);
if (external_reference_decoder_ == NULL) {
external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
}
@@ -711,7 +700,7 @@ Deserializer::~Deserializer() {
void Deserializer::VisitPointers(Object** start, Object** end) {
// The space must be new space. Any other space would cause ReadChunk to try
// to update the remembered using NULL as the address.
- ReadData(start, end, NEW_SPACE, NULL);
+ ReadChunk(start, end, NEW_SPACE, NULL);
}
@@ -799,7 +788,7 @@ void Deserializer::ReadObject(int space_number,
if (FLAG_log_snapshot_positions) {
LOG(isolate_, SnapshotPositionEvent(address, source_->position()));
}
- ReadData(current, limit, space_number, address);
+ ReadChunk(current, limit, space_number, address);
// TODO(mvstanton): consider treating the heap()->allocation_sites_list()
// as a (weak) root. If this root is relocated correctly,
@@ -824,9 +813,6 @@ void Deserializer::ReadObject(int space_number,
// pre-allocate that reserved space. During deserialization, all we need
// to do is to bump up the pointer for each space in the reserved
// space. This is also used for fixing back references.
-// We may have to split up the pre-allocation into several chunks
-// because it would not fit onto a single page, we have to keep track
-// of when to move to the next chunk.
// Since multiple large objects cannot be folded into one large object
// space allocation, we have to do an actual allocation when deserializing
// each large object. Instead of tracking offset for back references, we
@@ -835,7 +821,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_->GetInt());
AllocationResult result = lo_space->AllocateRaw(size, exec);
HeapObject* obj = HeapObject::cast(result.ToObjectChecked());
deserialized_large_objects_.Add(obj);
@@ -843,28 +829,16 @@ Address Deserializer::Allocate(int space_index, int size) {
} else {
DCHECK(space_index < kNumberOfPreallocatedSpaces);
Address address = high_water_[space_index];
- DCHECK_NE(NULL, address);
- const Heap::Reservation& reservation = reservations_[space_index];
- int chunk_index = current_chunk_[space_index];
- if (address + size > reservation[chunk_index].end) {
- // The last chunk size matches exactly the already deserialized data.
- DCHECK_EQ(address, reservation[chunk_index].end);
- // Move to next reserved chunk.
- chunk_index = ++current_chunk_[space_index];
- DCHECK_LT(chunk_index, reservation.length());
- // Prepare for next allocation in the next chunk.
- address = reservation[chunk_index].start;
- } else {
- high_water_[space_index] = address + size;
- }
high_water_[space_index] = address + size;
return address;
}
}
-void Deserializer::ReadData(Object** current, Object** limit, int source_space,
- Address current_object_address) {
+void Deserializer::ReadChunk(Object** current,
+ Object** limit,
+ int source_space,
+ Address current_object_address) {
Isolate* const isolate = isolate_;
// Write barrier support costs around 1% in startup time. In fact there
// are no new space objects in current boot snapshots, so it's not needed,
@@ -916,7 +890,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
new_object = reinterpret_cast<Object*>(address); \
} else if (where == kBackref) { \
emit_write_barrier = (space_number == NEW_SPACE); \
- new_object = GetBackReferencedObject(data & kSpaceMask); \
+ new_object = GetAddressFromEnd(data & kSpaceMask); \
if (deserializing_user_code()) { \
new_object = ProcessBackRefInSerializedCode(new_object); \
} \
@@ -939,7 +913,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
current = reinterpret_cast<Object**>( \
reinterpret_cast<Address>(current) + skip); \
emit_write_barrier = (space_number == NEW_SPACE); \
- new_object = GetBackReferencedObject(data & kSpaceMask); \
+ new_object = GetAddressFromEnd(data & kSpaceMask); \
if (deserializing_user_code()) { \
new_object = ProcessBackRefInSerializedCode(new_object); \
} \
@@ -1247,7 +1221,7 @@ Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
seen_large_objects_index_(0) {
// The serializer is meant to be used only to generate initial heap images
// from a context in which there is only one isolate.
- for (int i = 0; i < kNumberOfSpaces; i++) pending_chunk_[i] = 0;
+ for (int i = 0; i < kNumberOfSpaces; i++) fullness_[i] = 0;
}
@@ -1309,19 +1283,6 @@ void Serializer::VisitPointers(Object** start, Object** end) {
}
-void Serializer::FinalizeAllocation() {
- DCHECK_EQ(0, completed_chunks_[LO_SPACE].length()); // Not yet finalized.
- for (int i = 0; i < kNumberOfSpaces; 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;
- }
- }
-}
-
-
// This ensures that the partial snapshot cache keeps things alive during GC and
// tracks their movement. When it is called during serialization of the startup
// snapshot nothing happens. When the partial (context) snapshot is created,
@@ -1408,10 +1369,11 @@ void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object,
int index = address_mapper_.MappedTo(heap_object);
sink_->PutInt(index, "large object index");
} else {
- uint32_t existing_allocation = address_mapper_.MappedTo(heap_object);
+ int address = address_mapper_.MappedTo(heap_object);
+ int offset = CurrentAllocationAddress(space) - address;
// Shift out the bits that are always 0.
- existing_allocation >>= kObjectAlignmentBits;
- sink_->PutInt(existing_allocation, "allocation");
+ offset >>= kObjectAlignmentBits;
+ sink_->PutInt(offset, "offset");
}
}
@@ -1571,15 +1533,15 @@ void Serializer::ObjectSerializer::SerializePrologue(int space, int size,
// Mark this object as already serialized.
if (space == LO_SPACE) {
if (object_->IsCode()) {
- sink_->Put(EXECUTABLE, "executable large object");
+ sink_->PutInt(EXECUTABLE, "executable large object");
} else {
- sink_->Put(NOT_EXECUTABLE, "not executable large object");
+ sink_->PutInt(NOT_EXECUTABLE, "not executable large object");
}
int index = serializer_->AllocateLargeObject(size);
serializer_->address_mapper()->AddMapping(object_, index);
} else {
- int allocation = serializer_->Allocate(space, size);
- serializer_->address_mapper()->AddMapping(object_, allocation);
+ int offset = serializer_->Allocate(space, size);
+ serializer_->address_mapper()->AddMapping(object_, offset);
}
// Serialize the map (first word of the object).
@@ -1905,32 +1867,17 @@ int Serializer::SpaceOfObject(HeapObject* object) {
}
-uint32_t Serializer::AllocateLargeObject(int size) {
- // Large objects are allocated one-by-one when deserializing. We do not
- // have to keep track of multiple chunks.
- pending_chunk_[LO_SPACE] += size;
+int Serializer::AllocateLargeObject(int size) {
+ fullness_[LO_SPACE] += size;
return seen_large_objects_index_++;
}
-uint32_t Serializer::Allocate(int space, int size) {
+int Serializer::Allocate(int space, int size) {
CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
- DCHECK(size > 0 && size < Page::kMaxRegularHeapObjectSize);
- uint32_t new_chunk_size = pending_chunk_[space] + size;
- uint32_t allocation;
- if (new_chunk_size > Page::kMaxRegularHeapObjectSize) {
- // The new chunk size would not fit onto a single page. Complete the
- // current chunk and start a new one.
- completed_chunks_[space].Add(pending_chunk_[space]);
- pending_chunk_[space] = 0;
- new_chunk_size = size;
- }
- // For back-referencing, each allocation is encoded as a combination
- // of chunk index and offset inside the chunk.
- allocation = ChunkIndexBits::encode(completed_chunks_[space].length()) |
- OffsetBits::encode(pending_chunk_[space]);
- pending_chunk_[space] = new_chunk_size;
- return allocation;
+ int allocation_address = fullness_[space];
+ fullness_[space] = allocation_address + size;
+ return allocation_address;
}
@@ -1976,7 +1923,6 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
Object** location = Handle<Object>::cast(info).location();
cs.VisitPointer(location);
cs.Pad();
- cs.FinalizeAllocation();
SerializedCodeData data(&payload, &cs);
ScriptData* script_data = data.GetScriptData();
@@ -2147,8 +2093,9 @@ void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
}
-MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
- Isolate* isolate, ScriptData* data, Handle<String> source) {
+Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate,
+ ScriptData* data,
+ Handle<String> source) {
base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start();
@@ -2160,15 +2107,10 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
SerializedCodeData scd(data, *source);
SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
Deserializer deserializer(&payload);
-
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++;
+ for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
+ deserializer.set_reservation(i, scd.GetReservation(i));
}
- DCHECK_EQ(kNumberOfSpaces, current_space);
// Prepare and register list of attached objects.
Vector<const uint32_t> code_stub_keys = scd.CodeStubKeys();
@@ -2182,12 +2124,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
deserializer.SetAttachedObjects(&attached_objects);
// Deserialize.
- deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM);
- if (root == NULL) {
- // Deserializing may fail if the reservations cannot be fulfilled.
- if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
- return MaybeHandle<SharedFunctionInfo>();
- }
+ deserializer.DeserializePartial(isolate, &root);
deserializer.FlushICacheForNewCodeObjects();
}
@@ -2207,25 +2144,10 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
DisallowHeapAllocation no_gc;
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++) {
- DCHECK(i == LO_SPACE || chunks[j] < Page::kMaxRegularHeapObjectSize);
- uint32_t chunk = ChunkSizeBits::encode(chunks[j]) |
- IsLastChunkBits::encode(j == chunks.length() - 1);
- reservations.Add(chunk);
- }
- }
-
// 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 data_length = kHeaderSize + stub_keys_size + payload->length();
// Allocate backing store and create result data.
byte* data = NewArray<byte>(data_length);
@@ -2235,21 +2157,20 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
// Set header values.
SetHeaderValue(kCheckSumOffset, CheckSum(cs->source()));
- 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()),
- reservation_size);
+ STATIC_ASSERT(NEW_SPACE == 0);
+ for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) {
+ SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i));
+ }
// Copy code stub keys.
- CopyBytes(data + kHeaderSize + reservation_size,
- reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size);
+ CopyBytes(data + kHeaderSize, reinterpret_cast<byte*>(stub_keys->begin()),
+ stub_keys_size);
// Copy serialized data.
- CopyBytes(data + kHeaderSize + reservation_size + stub_keys_size,
- payload->begin(), static_cast<size_t>(payload->length()));
+ CopyBytes(data + kHeaderSize + stub_keys_size, payload->begin(),
+ static_cast<size_t>(payload->length()));
}
« no previous file with comments | « src/serialize.h ('k') | src/snapshot-common.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698