⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 267481 in webkit


Ignore:
Timestamp:
Sep 23, 2020, 9:41:03 AM (6 years ago)
Author:
Alan Coon
Message:

Cherry-pick r267304. rdar://problem/69439749

[JSC] PreciseAllocation's isNewlyAllocated flag should be propagated from isMarked at GC begin phase to make isLive correct
https://bugs.webkit.org/show_bug.cgi?id=216717

Reviewed by Mark Lam.

When starting full GC, at beginMarking, PreciseAllocation's mark bit is cleared to be usable for upcoming marking.
However, this means that HeapCell::isLive will see this object as dead until it is marked.
Let's consider that this object is not newly allocated one. Then, its isNewlyAllocated is false. And now mark bit

is also cleared. Since PreciseAllocation::isLive is isNewlyAllocated
isMarked, then it looks dead, while it is live.

This confuses HeapCell:isLive function and makes some of watchpoints perform wrong decisions (e.g. this condition is
no longer valid, let's just discard it).
At the beginning of full collection, we should propagate the old mark bit to isNewlyAllocated so that it looks live
during marking. This is similar trick to MarkedBlock::aboutToMark.

  • heap/PreciseAllocation.cpp: (JSC::PreciseAllocation::flip):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@267304 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Location:
branches/safari-610.2.6.1-branch/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-610.2.6.1-branch/Source/JavaScriptCore/ChangeLog

    r266879 r267481  
     12020-09-23  Russell Epstein  <repstein@apple.com>
     2
     3        Cherry-pick r267304. rdar://problem/69439749
     4
     5    [JSC] PreciseAllocation's isNewlyAllocated flag should be propagated from isMarked at GC begin phase to make isLive correct
     6    https://bugs.webkit.org/show_bug.cgi?id=216717
     7   
     8    Reviewed by Mark Lam.
     9   
     10    When starting full GC, at beginMarking, PreciseAllocation's mark bit is cleared to be usable for upcoming marking.
     11    However, this means that HeapCell::isLive will see this object as dead until it is marked.
     12    Let's consider that this object is not newly allocated one. Then, its isNewlyAllocated is false. And now mark bit
     13    is also cleared. Since PreciseAllocation::isLive is isNewlyAllocated || isMarked, then it looks dead, while it is live.
     14    This confuses HeapCell:isLive function and makes some of watchpoints perform wrong decisions (e.g. this condition is
     15    no longer valid, let's just discard it).
     16    At the beginning of full collection, we should propagate the old mark bit to isNewlyAllocated so that it looks live
     17    during marking. This is similar trick to MarkedBlock::aboutToMark.
     18   
     19    * heap/PreciseAllocation.cpp:
     20    (JSC::PreciseAllocation::flip):
     21   
     22    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@267304 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     23
     24    2020-09-18  Yusuke Suzuki  <ysuzuki@apple.com>
     25
     26            [JSC] PreciseAllocation's isNewlyAllocated flag should be propagated from isMarked at GC begin phase to make isLive correct
     27            https://bugs.webkit.org/show_bug.cgi?id=216717
     28
     29            Reviewed by Mark Lam.
     30
     31            When starting full GC, at beginMarking, PreciseAllocation's mark bit is cleared to be usable for upcoming marking.
     32            However, this means that HeapCell::isLive will see this object as dead until it is marked.
     33            Let's consider that this object is not newly allocated one. Then, its isNewlyAllocated is false. And now mark bit
     34            is also cleared. Since PreciseAllocation::isLive is isNewlyAllocated || isMarked, then it looks dead, while it is live.
     35            This confuses HeapCell:isLive function and makes some of watchpoints perform wrong decisions (e.g. this condition is
     36            no longer valid, let's just discard it).
     37            At the beginning of full collection, we should propagate the old mark bit to isNewlyAllocated so that it looks live
     38            during marking. This is similar trick to MarkedBlock::aboutToMark.
     39
     40            * heap/PreciseAllocation.cpp:
     41            (JSC::PreciseAllocation::flip):
     42
    1432020-09-10  Alan Coon  <alancoon@apple.com>
    244
  • branches/safari-610.2.6.1-branch/Source/JavaScriptCore/heap/PreciseAllocation.cpp

    r262570 r267481  
    214214{
    215215    ASSERT(heap()->collectionScope() == CollectionScope::Full);
    216     clearMarked();
     216    // Propagate the last time's mark bit to m_isNewlyAllocated so that `isLive` will say "yes" until this GC cycle finishes.
     217    // After that, m_isNewlyAllocated is cleared again. So only previously marked or actually newly created objects survive.
     218    // We do not need to care about concurrency here since marking thread is stopped right now. This is equivalent to the logic
     219    // of MarkedBlock::aboutToMarkSlow.
     220    // We invoke this function only when this is full collection. This ensures that at the end of upcoming cycle, we will
     221    // clear NewlyAllocated bits of all objects. So this works correctly.
     222    //
     223    //                                      N: NewlyAllocated, M: Marked
     224    //                                                 after this         at the end        When cycle
     225    //                                            N M  function    N M     of cycle    N M  is finished   N M
     226    // The live object survives the last cycle    0 1      =>      1 0        =>       1 1       =>       0 1    => live
     227    // The dead object in the last cycle          0 0      =>      0 0        =>       0 0       =>       0 0    => dead
     228    // The live object newly created after this            =>      1 0        =>       1 1       =>       0 1    => live
     229    // The dead object newly created after this            =>      1 0        =>       1 0       =>       0 0    => dead
     230    // The live object newly created before this  1 0      =>      1 0        =>       1 1       =>       0 1    => live
     231    // The dead object newly created before this  1 0      =>      1 0        =>       1 0       =>       0 0    => dead
     232    //                                                                                                    ^
     233    //                                                              This is ensured since this function is used only for full GC.
     234    m_isNewlyAllocated |= isMarked();
     235    m_isMarked.store(false, std::memory_order_relaxed);
    217236}
    218237
Note: See TracChangeset for help on using the changeset viewer.