Index: src/snapshot/serialize.cc |
diff --git a/src/snapshot/serialize.cc b/src/snapshot/serialize.cc |
index ace8225b8246caf958f3bf335b2c33c423e19576..293834cee2bacf293b5df9bd296abd8911dc75ea 100644 |
--- a/src/snapshot/serialize.cc |
+++ b/src/snapshot/serialize.cc |
@@ -516,10 +516,18 @@ void Deserializer::DecodeReservation( |
void Deserializer::FlushICacheForNewCodeObjects() { |
- PageIterator it(isolate_->heap()->code_space()); |
- while (it.has_next()) { |
- Page* p = it.next(); |
- CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start()); |
+ if (!deserializing_user_code_) { |
+ // The entire isolate is newly deserialized. Simply flush all code pages. |
+ PageIterator it(isolate_->heap()->code_space()); |
+ while (it.has_next()) { |
+ Page* p = it.next(); |
+ CpuFeatures::FlushICache(p->area_start(), |
+ p->area_end() - p->area_start()); |
+ } |
+ } |
+ for (Code* code : new_code_objects_) { |
+ CpuFeatures::FlushICache(code->instruction_start(), |
+ code->instruction_size()); |
} |
} |
@@ -612,9 +620,9 @@ MaybeHandle<Object> Deserializer::DeserializePartial( |
VisitPointer(&outdated_contexts); |
DeserializeDeferredObjects(); |
- // There's no code deserialized here. If this assert fires |
- // then that's changed and logging should be added to notify |
- // the profiler et al of the new code. |
+ // There's no code deserialized here. If this assert fires then that's |
+ // changed and logging should be added to notify the profiler et al of the |
+ // new code, which also has to be flushed from instruction cache. |
CHECK_EQ(start_address, code_space->top()); |
CHECK(outdated_contexts->IsFixedArray()); |
*outdated_contexts_out = |
@@ -667,9 +675,8 @@ void Deserializer::DeserializeDeferredObjects() { |
Object** end = reinterpret_cast<Object**>(obj_address + size); |
bool filled = ReadData(start, end, space, obj_address); |
CHECK(filled); |
- if (object->IsAllocationSite()) { |
- RelinkAllocationSite(AllocationSite::cast(object)); |
- } |
+ DCHECK(CanBeDeferred(object)); |
+ PostProcessNewObject(object, space); |
} |
} |
@@ -705,43 +712,52 @@ class StringTableInsertionKey : public HashTableKey { |
}; |
-HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj) { |
- DCHECK(deserializing_user_code()); |
- if (obj->IsString()) { |
- String* string = String::cast(obj); |
- // Uninitialize hash field as the hash seed may have changed. |
- string->set_hash_field(String::kEmptyHashField); |
- if (string->IsInternalizedString()) { |
- DisallowHeapAllocation no_gc; |
- HandleScope scope(isolate_); |
- StringTableInsertionKey key(string); |
- String* canonical = *StringTable::LookupKey(isolate_, &key); |
- string->SetForwardedInternalizedString(canonical); |
- return canonical; |
+HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj, int space) { |
+ if (deserializing_user_code()) { |
+ if (obj->IsString()) { |
+ String* string = String::cast(obj); |
+ // Uninitialize hash field as the hash seed may have changed. |
+ string->set_hash_field(String::kEmptyHashField); |
+ if (string->IsInternalizedString()) { |
+ // Canonicalize the internalized string. If it already exists in the |
+ // string table, set it to forward to the existing one. |
+ DisallowHeapAllocation no_gc; |
+ HandleScope scope(isolate_); |
+ StringTableInsertionKey key(string); |
+ String* canonical = *StringTable::LookupKey(isolate_, &key); |
+ string->SetForwardedInternalizedString(canonical); |
+ return canonical; |
+ } |
+ } else if (obj->IsScript()) { |
+ // Assign a new script id to avoid collision. |
+ Script::cast(obj)->set_id(isolate_->heap()->NextScriptId()); |
+ } else { |
+ DCHECK(CanBeDeferred(obj)); |
} |
- } else if (obj->IsScript()) { |
- Script::cast(obj)->set_id(isolate_->heap()->NextScriptId()); |
- } else { |
- DCHECK(CanBeDeferred(obj)); |
} |
- return obj; |
-} |
- |
- |
-void Deserializer::RelinkAllocationSite(AllocationSite* obj) { |
- DCHECK(obj->IsAllocationSite()); |
- // Allocation sites are present in the snapshot, and must be linked into |
- // a list at deserialization time. |
- AllocationSite* site = AllocationSite::cast(obj); |
- // TODO(mvstanton): consider treating the heap()->allocation_sites_list() |
- // as a (weak) root. If this root is relocated correctly, |
- // RelinkAllocationSite() isn't necessary. |
- if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { |
- site->set_weak_next(isolate_->heap()->undefined_value()); |
- } else { |
- site->set_weak_next(isolate_->heap()->allocation_sites_list()); |
+ if (obj->IsAllocationSite()) { |
+ DCHECK(obj->IsAllocationSite()); |
+ // Allocation sites are present in the snapshot, and must be linked into |
+ // a list at deserialization time. |
+ AllocationSite* site = AllocationSite::cast(obj); |
+ // TODO(mvstanton): consider treating the heap()->allocation_sites_list() |
+ // as a (weak) root. If this root is relocated correctly, this becomes |
+ // unnecessary. |
+ if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { |
+ site->set_weak_next(isolate_->heap()->undefined_value()); |
+ } else { |
+ site->set_weak_next(isolate_->heap()->allocation_sites_list()); |
+ } |
+ isolate_->heap()->set_allocation_sites_list(site); |
+ } else if (obj->IsCode()) { |
+ // We flush all code pages after deserializing the startup snapshot. In that |
+ // case, we only need to remember code objects in the large object space. |
+ // When deserializing user code, remember each individual code object. |
+ if (deserializing_user_code() || space == LO_SPACE) { |
+ new_code_objects_.Add(Code::cast(obj)); |
+ } |
} |
- isolate_->heap()->set_allocation_sites_list(site); |
+ return obj; |
} |
@@ -803,11 +819,7 @@ void Deserializer::ReadObject(int space_number, Object** write_back) { |
if (ReadData(current, limit, space_number, address)) { |
// Only post process if object content has not been deferred. |
- if (obj->IsAllocationSite()) { |
- RelinkAllocationSite(AllocationSite::cast(obj)); |
- } |
- |
- if (deserializing_user_code()) obj = PostProcessNewObject(obj); |
+ obj = PostProcessNewObject(obj, space_number); |
} |
Object* write_back_obj = obj; |