[heap, deserializer] Restore marking invariant for deserialized maps

when black allocation is on.

The scenario:
1) Incremental marking is off.
2) Partial deserialization starts and calls Heap::ReserveSpace.
2) ReserveSpace creates (white) reservations in old space.
3) ReserveSpace allocates map placeholders. One of these allocations
starts incremental marking, which starts black allocation (currently
when concurrent marking is on). Subsequent maps are black allocated.
4) ReserveSpace succeeds without triggering a GC.
5) Deserialization continues. Some maps are black. Note that
deserialization emits only old->new write barriers and skips
marking write barriers.
6) Deserialization finishes and re-visits the black allocated
reservations and large object. This misses black allocated maps.
7) There is black->white descriptor array pointer in one of these map.

BUG=chromium:723600

Change-Id: Ifffe46f22a7d7dbc5cff2e882190234fcc722ccb
Reviewed-on: https://chromium-review.googlesource.com/581187
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46816}
This commit is contained in:
Ulan Degenbaev 2017-07-21 12:07:34 +02:00 committed by Commit Bot
parent a9428d527e
commit 250ba28a57
3 changed files with 14 additions and 7 deletions

View File

@ -4481,10 +4481,10 @@ void Heap::FinalizeIncrementalMarkingIfComplete(
} }
void Heap::RegisterDeserializedObjectsForBlackAllocation( void Heap::RegisterDeserializedObjectsForBlackAllocation(
Reservation* reservations, List<HeapObject*>* large_objects) { Reservation* reservations, List<HeapObject*>* large_objects,
// TODO(hpayer): We do not have to iterate reservations on black objects List<Address>* maps) {
// for marking. We just have to execute the special visiting side effect // TODO(ulan): pause black allocation during deserialization to avoid
// code that adds objects to global data structures, e.g. for array buffers. // iterating all these objects in one go.
if (!incremental_marking()->black_allocation()) return; if (!incremental_marking()->black_allocation()) return;
@ -4514,6 +4514,12 @@ void Heap::RegisterDeserializedObjectsForBlackAllocation(
for (HeapObject* object : *large_objects) { for (HeapObject* object : *large_objects) {
incremental_marking()->ProcessBlackAllocatedObject(object); incremental_marking()->ProcessBlackAllocatedObject(object);
} }
// Map space doesn't use reservations, so it needs custom handling.
for (Address addr : *maps) {
incremental_marking()->ProcessBlackAllocatedObject(
HeapObject::FromAddress(addr));
}
} }
void Heap::NotifyObjectLayoutChange(HeapObject* object, void Heap::NotifyObjectLayoutChange(HeapObject* object,

View File

@ -1184,7 +1184,8 @@ class Heap {
void FinalizeIncrementalMarkingIfComplete(GarbageCollectionReason gc_reason); void FinalizeIncrementalMarkingIfComplete(GarbageCollectionReason gc_reason);
void RegisterDeserializedObjectsForBlackAllocation( void RegisterDeserializedObjectsForBlackAllocation(
Reservation* reservations, List<HeapObject*>* large_objects); Reservation* reservations, List<HeapObject*>* large_objects,
List<Address>* maps);
IncrementalMarking* incremental_marking() { return incremental_marking_; } IncrementalMarking* incremental_marking() { return incremental_marking_; }

View File

@ -153,7 +153,7 @@ MaybeHandle<Object> Deserializer::DeserializePartial(
DeserializeEmbedderFields(embedder_fields_deserializer); DeserializeEmbedderFields(embedder_fields_deserializer);
isolate->heap()->RegisterDeserializedObjectsForBlackAllocation( isolate->heap()->RegisterDeserializedObjectsForBlackAllocation(
reservations_, &deserialized_large_objects_); reservations_, &deserialized_large_objects_, &allocated_maps_);
// There's no code deserialized here. If this assert fires then that's // 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 // changed and logging should be added to notify the profiler et al of the
@ -181,7 +181,7 @@ MaybeHandle<HeapObject> Deserializer::DeserializeObject(Isolate* isolate) {
FlushICacheForNewCodeObjectsAndRecordEmbeddedObjects(); FlushICacheForNewCodeObjectsAndRecordEmbeddedObjects();
result = Handle<HeapObject>(HeapObject::cast(root)); result = Handle<HeapObject>(HeapObject::cast(root));
isolate->heap()->RegisterDeserializedObjectsForBlackAllocation( isolate->heap()->RegisterDeserializedObjectsForBlackAllocation(
reservations_, &deserialized_large_objects_); reservations_, &deserialized_large_objects_, &allocated_maps_);
} }
CommitPostProcessedObjects(isolate); CommitPostProcessedObjects(isolate);
return scope.CloseAndEscape(result); return scope.CloseAndEscape(result);