Index: src/serialize.cc |
diff --git a/src/serialize.cc b/src/serialize.cc |
index 843f97631ef3fddde06a9795940465663f32a89d..894a1be261c1affd9a6e6f02451ac3cdb3c6b3d9 100644 |
--- a/src/serialize.cc |
+++ b/src/serialize.cc |
@@ -596,8 +596,9 @@ Deserializer::Deserializer(SnapshotByteSource* source) |
: isolate_(NULL), |
attached_objects_(NULL), |
source_(source), |
- external_reference_decoder_(NULL) { |
- for (int i = 0; i < LAST_SPACE + 1; i++) { |
+ external_reference_decoder_(NULL), |
+ deserialized_large_objects_(0) { |
+ for (int i = 0; i < kNumberOfSpaces; i++) { |
reservations_[i] = kUninitializedReservation; |
} |
} |
@@ -615,7 +616,7 @@ void Deserializer::FlushICacheForNewCodeObjects() { |
void Deserializer::Deserialize(Isolate* isolate) { |
isolate_ = isolate; |
DCHECK(isolate_ != NULL); |
- isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]); |
+ isolate_->heap()->ReserveSpace(reservations_, high_water_); |
// No active threads. |
DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse()); |
// No active handles. |
@@ -662,7 +663,8 @@ void Deserializer::DeserializePartial(Isolate* isolate, Object** root) { |
for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) { |
DCHECK(reservations_[i] != kUninitializedReservation); |
} |
- isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]); |
+ Heap* heap = isolate->heap(); |
+ heap->ReserveSpace(reservations_, high_water_); |
if (external_reference_decoder_ == NULL) { |
external_reference_decoder_ = new ExternalReferenceDecoder(isolate); |
} |
@@ -798,11 +800,40 @@ void Deserializer::ReadObject(int space_number, |
*write_back = obj; |
#ifdef DEBUG |
- bool is_codespace = (space_number == CODE_SPACE); |
- DCHECK(obj->IsCode() == is_codespace); |
+ if (obj->IsCode()) { |
+ DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); |
+ } else { |
+ DCHECK(space_number != CODE_SPACE); |
+ } |
#endif |
} |
+ |
+// We know the space requirements before deserialization and can |
+// 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. |
+// 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 |
+// reference large objects by index. |
+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_->GetInt()); |
+ AllocationResult result = lo_space->AllocateRaw(size, exec); |
+ HeapObject* obj = HeapObject::cast(result.ToObjectChecked()); |
+ deserialized_large_objects_.Add(obj); |
+ return obj->address(); |
+ } else { |
+ DCHECK(space_index < kNumberOfPreallocatedSpaces); |
+ Address address = high_water_[space_index]; |
+ high_water_[space_index] = address + size; |
+ return address; |
+ } |
+} |
+ |
void Deserializer::ReadChunk(Object** current, |
Object** limit, |
int source_space, |
@@ -925,15 +956,16 @@ void Deserializer::ReadChunk(Object** current, |
// This generates a case and a body for the new space (which has to do extra |
// write barrier handling) and handles the other spaces with 8 fall-through |
// cases and one body. |
-#define ALL_SPACES(where, how, within) \ |
- CASE_STATEMENT(where, how, within, NEW_SPACE) \ |
- CASE_BODY(where, how, within, NEW_SPACE) \ |
- CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \ |
- CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \ |
- CASE_STATEMENT(where, how, within, CODE_SPACE) \ |
- CASE_STATEMENT(where, how, within, CELL_SPACE) \ |
- CASE_STATEMENT(where, how, within, PROPERTY_CELL_SPACE) \ |
- CASE_STATEMENT(where, how, within, MAP_SPACE) \ |
+#define ALL_SPACES(where, how, within) \ |
+ CASE_STATEMENT(where, how, within, NEW_SPACE) \ |
+ CASE_BODY(where, how, within, NEW_SPACE) \ |
+ CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \ |
+ CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \ |
+ CASE_STATEMENT(where, how, within, CODE_SPACE) \ |
+ CASE_STATEMENT(where, how, within, MAP_SPACE) \ |
+ CASE_STATEMENT(where, how, within, CELL_SPACE) \ |
+ CASE_STATEMENT(where, how, within, PROPERTY_CELL_SPACE) \ |
+ CASE_STATEMENT(where, how, within, LO_SPACE) \ |
CASE_BODY(where, how, within, kAnyOldSpace) |
#define FOUR_CASES(byte_code) \ |
@@ -1184,12 +1216,11 @@ Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink) |
sink_(sink), |
external_reference_encoder_(new ExternalReferenceEncoder(isolate)), |
root_index_wave_front_(0), |
- code_address_map_(NULL) { |
+ code_address_map_(NULL), |
+ 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 <= LAST_SPACE; i++) { |
- fullness_[i] = 0; |
- } |
+ for (int i = 0; i < kNumberOfSpaces; i++) fullness_[i] = 0; |
} |
@@ -1324,10 +1355,7 @@ void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object, |
WhereToPoint where_to_point, |
int skip) { |
int space = SpaceOfObject(heap_object); |
- int address = address_mapper_.MappedTo(heap_object); |
- int offset = CurrentAllocationAddress(space) - address; |
- // Shift out the bits that are always 0. |
- offset >>= kObjectAlignmentBits; |
+ |
if (skip == 0) { |
sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer"); |
} else { |
@@ -1335,7 +1363,17 @@ void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object, |
"BackRefSerWithSkip"); |
sink_->PutInt(skip, "BackRefSkipDistance"); |
} |
- sink_->PutInt(offset, "offset"); |
+ |
+ if (space == LO_SPACE) { |
+ int index = address_mapper_.MappedTo(heap_object); |
+ sink_->PutInt(index, "large object index"); |
+ } else { |
+ int address = address_mapper_.MappedTo(heap_object); |
+ int offset = CurrentAllocationAddress(space) - address; |
+ // Shift out the bits that are always 0. |
+ offset >>= kObjectAlignmentBits; |
+ sink_->PutInt(offset, "offset"); |
+ } |
} |
@@ -1494,8 +1532,18 @@ void Serializer::ObjectSerializer::Serialize() { |
} |
// Mark this object as already serialized. |
- int offset = serializer_->Allocate(space, size); |
- serializer_->address_mapper()->AddMapping(object_, offset); |
+ if (space == LO_SPACE) { |
+ if (object_->IsCode()) { |
+ sink_->PutInt(EXECUTABLE, "executable large object"); |
+ } else { |
+ sink_->PutInt(NOT_EXECUTABLE, "not executable large object"); |
+ } |
+ int index = serializer_->AllocateLargeObject(size); |
+ serializer_->address_mapper()->AddMapping(object_, index); |
+ } else { |
+ int offset = serializer_->Allocate(space, size); |
+ serializer_->address_mapper()->AddMapping(object_, offset); |
+ } |
// Serialize the map (first word of the object). |
serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject, 0); |
@@ -1747,8 +1795,14 @@ int Serializer::SpaceOfObject(HeapObject* object) { |
} |
+int Serializer::AllocateLargeObject(int size) { |
+ fullness_[LO_SPACE] += size; |
+ return seen_large_objects_index_++; |
+} |
+ |
+ |
int Serializer::Allocate(int space, int size) { |
- CHECK(space >= 0 && space < kNumberOfSpaces); |
+ CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); |
int allocation_address = fullness_[space]; |
fullness_[space] = allocation_address + size; |
return allocation_address; |
@@ -1840,11 +1894,11 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, |
if (heap_object->IsCode()) { |
Code* code_object = Code::cast(heap_object); |
+ DCHECK(!code_object->is_optimized_code()); |
if (code_object->kind() == Code::BUILTIN) { |
SerializeBuiltin(code_object, how_to_code, where_to_point, skip); |
return; |
- } |
- if (code_object->IsCodeStubOrIC()) { |
+ } else if (code_object->IsCodeStubOrIC()) { |
SerializeCodeStub(code_object, how_to_code, where_to_point, skip); |
return; |
} |
@@ -1991,7 +2045,7 @@ Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate, |
SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); |
Deserializer deserializer(&payload); |
STATIC_ASSERT(NEW_SPACE == 0); |
- for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { |
+ for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) { |
deserializer.set_reservation(i, scd.GetReservation(i)); |
} |
@@ -2041,7 +2095,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs) |
SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); |
SetHeaderValue(kPayloadLengthOffset, payload->length()); |
STATIC_ASSERT(NEW_SPACE == 0); |
- for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { |
+ for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) { |
SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i)); |
} |