Bug 73982 - Zapping a block that is Marked leads to dead objects being mistaken for live ones
Summary: Zapping a block that is Marked leads to dead objects being mistaken for live ...
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P2 Normal
Assignee: Nobody
Keywords: InRadar
Depends on:
Reported: 2011-12-06 21:10 PST by Filip Pizlo
Modified: 2011-12-06 21:26 PST (History)
0 users

See Also:

the patch (3.66 KB, patch)
2011-12-06 21:15 PST, Filip Pizlo
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Filip Pizlo 2011-12-06 21:10:20 PST
Consider the following chain of state transitions for some MarkedBlock M, containing object O, and two collection cycles C1 and C2.

1) Allocation causes M to be swept, and ending up in the FreeListed state.

2) GC cycle C1 starts with M still being the currentBlock for its size class. M first transitions FreeListed->Zapped and then Zapped->Marked. C1 does not mark O, leading it to have 0 in the mark bit. M happens to also be the first block in its size class, so currentBlock still refers to M.

3) GC cycle C2 starts with M still being the currentBlock. No allocations have occurred in M between C1 and C2. So, M is zapped again. But this time, its free list is empty and its non-free-listed objects may be dead from the previous collection. This is true of O, which has a clear mark bit, but is not on the free list, since M could not possibly have a free list.  (Free lists are only created when a sweep occurs, and a sweep only occurs if you allocate, and nobody allocated in M or M's size class.)

4) We now have a scenario that is ripe for disaster: O has a non-zero vtable pointer (hence, it is not zapped) and a clear mark bit, but the block thinks it is Zapped. Hence conservative marking logic believes that O's non-zero vtable is proof that O is a valid object that was marked in the previous collection cycle, and hence must have valid outgoing references. But neither of these things is true; O is not a valid object (it is in fact dead) and does not have valid outgoing references, because, since it was not marked in C1, its outgoing references were not marked in C1, and hence its outgoing references may point to nonsense (free memory, other objects, or zapped objects).  At this point, we are lucky of the GC completes safely.

The solution is that zapping a block in the Marked state should not do anything. Only zapping a block in the FreeListed state should lead to the block becoming Zapped.
Comment 1 Filip Pizlo 2011-12-06 21:15:22 PST
Created attachment 118168 [details]
the patch
Comment 2 Geoffrey Garen 2011-12-06 21:16:56 PST
Comment on attachment 118168 [details]
the patch

Comment 3 Filip Pizlo 2011-12-06 21:20:28 PST
Comment 4 Filip Pizlo 2011-12-06 21:26:29 PST
Landed in http://trac.webkit.org/changeset/102220
Comment 5 Filip Pizlo 2011-12-06 21:26:50 PST
Comment on attachment 118168 [details]
the patch

Clearing flags