Ignore:
Timestamp:
Nov 9, 2012, 9:58:19 AM (13 years ago)
Author:
[email protected]
Message:

MarkStackArray should use the BlockAllocator instead of the MarkStackSegmentAllocator
https://bugs.webkit.org/show_bug.cgi?id=101642

Reviewed by Filip Pizlo.

MarkStackSegmentAllocator is like a miniature version of the BlockAllocator. Now that the BlockAllocator has support
for a variety of block sizes, we should get rid of the MarkStackSegmentAllocator in favor of the BlockAllocator.

  • heap/BlockAllocator.h: Add new specializations of regionSetFor for the new MarkStackSegments.

(JSC):
(JSC::MarkStackSegment):

  • heap/GCThreadSharedData.cpp:

(JSC::GCThreadSharedData::GCThreadSharedData):
(JSC::GCThreadSharedData::reset):

  • heap/GCThreadSharedData.h:

(GCThreadSharedData):

  • heap/MarkStack.cpp:

(JSC::MarkStackArray::MarkStackArray): We now have a doubly linked list of MarkStackSegments, so we need to refactor
all the places that used the old custom tail/previous logic.
(JSC::MarkStackArray::~MarkStackArray):
(JSC::MarkStackArray::expand):
(JSC::MarkStackArray::refill):
(JSC::MarkStackArray::donateSomeCellsTo): Refactor to use the new linked list.
(JSC::MarkStackArray::stealSomeCellsFrom): Ditto.

  • heap/MarkStack.h:

(JSC):
(MarkStackSegment):
(JSC::MarkStackSegment::MarkStackSegment):
(JSC::MarkStackSegment::sizeFromCapacity):
(MarkStackArray):

  • heap/MarkStackInlines.h:

(JSC::MarkStackSegment::create):
(JSC):
(JSC::MarkStackArray::postIncTop):
(JSC::MarkStackArray::preDecTop):
(JSC::MarkStackArray::setTopForFullSegment):
(JSC::MarkStackArray::setTopForEmptySegment):
(JSC::MarkStackArray::top):
(JSC::MarkStackArray::validatePrevious):
(JSC::MarkStackArray::append):
(JSC::MarkStackArray::removeLast):
(JSC::MarkStackArray::isEmpty):
(JSC::MarkStackArray::size):

  • heap/SlotVisitor.cpp:

(JSC::SlotVisitor::SlotVisitor):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/heap/MarkStack.cpp

    r133995 r134080  
    4646namespace JSC {
    4747
    48 MarkStackSegmentAllocator::MarkStackSegmentAllocator()
    49     : m_nextFreeSegment(0)
    50 {
    51     m_lock.Init();
    52 }
    53 
    54 MarkStackSegmentAllocator::~MarkStackSegmentAllocator()
    55 {
    56     shrinkReserve();
    57 }
    58 
    59 MarkStackSegment* MarkStackSegmentAllocator::allocate()
    60 {
    61     {
    62         SpinLockHolder locker(&m_lock);
    63         if (m_nextFreeSegment) {
    64             MarkStackSegment* result = m_nextFreeSegment;
    65             m_nextFreeSegment = result->m_previous;
    66             return result;
    67         }
    68     }
    69 
    70     return static_cast<MarkStackSegment*>(OSAllocator::reserveAndCommit(Options::gcMarkStackSegmentSize()));
    71 }
    72 
    73 void MarkStackSegmentAllocator::release(MarkStackSegment* segment)
    74 {
    75     SpinLockHolder locker(&m_lock);
    76     segment->m_previous = m_nextFreeSegment;
    77     m_nextFreeSegment = segment;
    78 }
    79 
    80 void MarkStackSegmentAllocator::shrinkReserve()
    81 {
    82     MarkStackSegment* segments;
    83     {
    84         SpinLockHolder locker(&m_lock);
    85         segments = m_nextFreeSegment;
    86         m_nextFreeSegment = 0;
    87     }
    88     while (segments) {
    89         MarkStackSegment* toFree = segments;
    90         segments = segments->m_previous;
    91         OSAllocator::decommitAndRelease(toFree, Options::gcMarkStackSegmentSize());
    92     }
    93 }
    94 
    95 MarkStackArray::MarkStackArray(MarkStackSegmentAllocator& allocator)
    96     : m_allocator(allocator)
     48MarkStackArray::MarkStackArray(BlockAllocator& blockAllocator)
     49    : m_blockAllocator(blockAllocator)
    9750    , m_segmentCapacity(MarkStackSegment::capacityFromSize(Options::gcMarkStackSegmentSize()))
    9851    , m_top(0)
    99     , m_numberOfPreviousSegments(0)
     52    , m_numberOfSegments(0)
    10053{
    101     m_topSegment = m_allocator.allocate();
    102 #if !ASSERT_DISABLED
    103     m_topSegment->m_top = 0;
    104 #endif
    105     m_topSegment->m_previous = 0;
     54    ASSERT(MarkStackSegment::blockSize == WeakBlock::blockSize);
     55    m_segments.push(MarkStackSegment::create(m_blockAllocator.allocate<MarkStackSegment>()));
     56    m_numberOfSegments++;
    10657}
    10758
    10859MarkStackArray::~MarkStackArray()
    10960{
    110     ASSERT(!m_topSegment->m_previous);
    111     m_allocator.release(m_topSegment);
     61    ASSERT(m_numberOfSegments == 1 && m_segments.size() == 1);
     62    m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead()));
    11263}
    11364
    11465void MarkStackArray::expand()
    11566{
    116     ASSERT(m_topSegment->m_top == m_segmentCapacity);
     67    ASSERT(m_segments.head()->m_top == m_segmentCapacity);
    11768   
    118     m_numberOfPreviousSegments++;
     69    MarkStackSegment* nextSegment = MarkStackSegment::create(m_blockAllocator.allocate<MarkStackSegment>());
     70    m_numberOfSegments++;
    11971   
    120     MarkStackSegment* nextSegment = m_allocator.allocate();
    12172#if !ASSERT_DISABLED
    12273    nextSegment->m_top = 0;
    12374#endif
    124     nextSegment->m_previous = m_topSegment;
    125     m_topSegment = nextSegment;
     75
     76    m_segments.push(nextSegment);
    12677    setTopForEmptySegment();
    12778    validatePrevious();
     
    13384    if (top())
    13485        return true;
    135     MarkStackSegment* toFree = m_topSegment;
    136     MarkStackSegment* previous = m_topSegment->m_previous;
    137     if (!previous)
    138         return false;
    139     ASSERT(m_numberOfPreviousSegments);
    140     m_numberOfPreviousSegments--;
    141     m_topSegment = previous;
    142     m_allocator.release(toFree);
     86    m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead()));
     87    ASSERT(m_numberOfSegments > 1);
     88    m_numberOfSegments--;
    14389    setTopForFullSegment();
    14490    validatePrevious();
     
    154100    ASSERT(m_segmentCapacity == other.m_segmentCapacity);
    155101
    156     size_t segmentsToDonate = (m_numberOfPreviousSegments + 2 - 1) / 2; // Round up to donate 1 / 1 previous segments.
     102    size_t segmentsToDonate = m_numberOfSegments / 2; // If we only have one segment (our head) we don't donate any segments.
    157103
    158104    if (!segmentsToDonate) {
     
    168114    other.validatePrevious();
    169115
    170     MarkStackSegment* previous = m_topSegment->m_previous;
     116    // Remove our head and the head of the other list before we start moving segments around.
     117    // We'll add them back on once we're done donating.
     118    MarkStackSegment* myHead = m_segments.removeHead();
     119    MarkStackSegment* otherHead = other.m_segments.removeHead();
     120
    171121    while (segmentsToDonate--) {
    172         ASSERT(previous);
    173         ASSERT(m_numberOfPreviousSegments);
     122        MarkStackSegment* current = m_segments.removeHead();
     123        ASSERT(current);
     124        ASSERT(m_numberOfSegments > 1);
     125        other.m_segments.push(current);
     126        m_numberOfSegments--;
     127        other.m_numberOfSegments++;
     128    }
    174129
    175         MarkStackSegment* current = previous;
    176         previous = current->m_previous;
    177            
    178         current->m_previous = other.m_topSegment->m_previous;
    179         other.m_topSegment->m_previous = current;
    180            
    181         m_numberOfPreviousSegments--;
    182         other.m_numberOfPreviousSegments++;
    183     }
    184     m_topSegment->m_previous = previous;
     130    // Put the original heads back in their places.
     131    m_segments.push(myHead);
     132    other.m_segments.push(otherHead);
    185133
    186134    validatePrevious();
     
    199147       
    200148    // If other has an entire segment, steal it and return.
    201     if (other.m_topSegment->m_previous) {
    202         ASSERT(other.m_topSegment->m_previous->m_top == m_segmentCapacity);
    203            
    204         // First remove a segment from other.
    205         MarkStackSegment* current = other.m_topSegment->m_previous;
    206         other.m_topSegment->m_previous = current->m_previous;
    207         other.m_numberOfPreviousSegments--;
    208            
    209         ASSERT(!!other.m_numberOfPreviousSegments == !!other.m_topSegment->m_previous);
    210            
    211         // Now add it to this.
    212         current->m_previous = m_topSegment->m_previous;
    213         m_topSegment->m_previous = current;
    214         m_numberOfPreviousSegments++;
    215            
     149    if (other.m_numberOfSegments > 1) {
     150        // Move the heads of the lists aside. We'll push them back on after.
     151        MarkStackSegment* otherHead = other.m_segments.removeHead();
     152        MarkStackSegment* myHead = m_segments.removeHead();
     153
     154        ASSERT(other.m_segments.head()->m_top == m_segmentCapacity);
     155
     156        m_segments.push(other.m_segments.removeHead());
     157
     158        m_numberOfSegments++;
     159        other.m_numberOfSegments--;
     160       
     161        m_segments.push(myHead);
     162        other.m_segments.push(otherHead);
     163   
    216164        validatePrevious();
    217165        other.validatePrevious();
Note: See TracChangeset for help on using the changeset viewer.