Ignore:
Timestamp:
Feb 4, 2014, 4:08:40 PM (11 years ago)
Author:
[email protected]
Message:

Refactor MarkStackArray to allow more than JSCells to be stored
https://bugs.webkit.org/show_bug.cgi?id=128203

Reviewed by Geoffrey Garen.

This patch refactors MarkStackArray into a separate template class named GCSegmentedArray.
This class allows subclassing to add functionality that only MarkStackArray wants.
Since it uses the JSC BlockAllocator instead of FastMalloc, this class can be used during
conservative stack scanning, which disallows using FastMalloc.

  • GNUmakefile.list.am:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • heap/BlockAllocator.h:
  • heap/GCSegmentedArray.h: Added.

(JSC::GCArraySegment::GCArraySegment):
(JSC::GCArraySegment::data):

  • heap/GCSegmentedArrayInlines.h: Added.

(JSC::GCSegmentedArray<T>::GCSegmentedArray):
(JSC::GCSegmentedArray<T>::~GCSegmentedArray):
(JSC::GCSegmentedArray<T>::clear):
(JSC::GCSegmentedArray<T>::expand):
(JSC::GCSegmentedArray<T>::refill):
(JSC::GCSegmentedArray<T>::fillVector):
(JSC::GCArraySegment<T>::create):
(JSC::GCSegmentedArray<T>::postIncTop):
(JSC::GCSegmentedArray<T>::preDecTop):
(JSC::GCSegmentedArray<T>::setTopForFullSegment):
(JSC::GCSegmentedArray<T>::setTopForEmptySegment):
(JSC::GCSegmentedArray<T>::top):
(JSC::GCSegmentedArray<T>::validatePrevious):
(JSC::GCSegmentedArray<T>::append):
(JSC::GCSegmentedArray<T>::canRemoveLast):
(JSC::GCSegmentedArray<T>::removeLast):
(JSC::GCSegmentedArray<T>::isEmpty):
(JSC::GCSegmentedArray<T>::size):

  • heap/MarkStack.cpp:

(JSC::MarkStackArray::MarkStackArray):
(JSC::MarkStackArray::~MarkStackArray):
(JSC::MarkStackArray::donateSomeCellsTo):
(JSC::MarkStackArray::stealSomeCellsFrom):

  • heap/MarkStack.h:
  • heap/MarkStackInlines.h:
File:
1 edited

Legend:

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

    r161615 r163414  
    2626#include "config.h"
    2727#include "MarkStack.h"
    28 #include "MarkStackInlines.h"
    29 
    30 #include "ConservativeRoots.h"
    31 #include "CopiedSpace.h"
    32 #include "CopiedSpaceInlines.h"
    33 #include "Heap.h"
    34 #include "JSArray.h"
    35 #include "JSCell.h"
    36 #include "JSObject.h"
    37 
    38 #include "SlotVisitorInlines.h"
    39 #include "Structure.h"
    40 #include "WriteBarrier.h"
    41 #include <wtf/Atomics.h>
    42 #include <wtf/DataLog.h>
    43 #include <wtf/MainThread.h>
    4428
    4529namespace JSC {
    4630
    47 COMPILE_ASSERT(MarkStackSegment::blockSize == WeakBlock::blockSize, blockSizeMatch);
    48 
    4931MarkStackArray::MarkStackArray(BlockAllocator& blockAllocator)
    50     : m_blockAllocator(blockAllocator)
    51     , m_top(0)
    52     , m_numberOfSegments(0)
     32    : GCSegmentedArray<const JSCell*>(blockAllocator)
    5333{
    54     m_segments.push(MarkStackSegment::create(m_blockAllocator.allocate<MarkStackSegment>()));
    55     m_numberOfSegments++;
    56 }
    57 
    58 MarkStackArray::~MarkStackArray()
    59 {
    60     ASSERT(m_numberOfSegments == 1);
    61     ASSERT(m_segments.size() == 1);
    62     m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead()));
    63     m_numberOfSegments--;
    64     ASSERT(!m_numberOfSegments);
    65     ASSERT(!m_segments.size());
    66 }
    67 
    68 void MarkStackArray::clear()
    69 {
    70     if (!m_segments.head())
    71         return;
    72     MarkStackSegment* next;
    73     for (MarkStackSegment* current = m_segments.head(); current->next(); current = next) {
    74         next = current->next();
    75         m_segments.remove(current);
    76         m_blockAllocator.deallocate(MarkStackSegment::destroy(current));
    77     }
    78     m_top = 0;
    79     m_numberOfSegments = 1;
    80 #if !ASSERT_DISABLED
    81     m_segments.head()->m_top = 0;
    82 #endif
    83 }
    84 
    85 void MarkStackArray::expand()
    86 {
    87     ASSERT(m_segments.head()->m_top == s_segmentCapacity);
    88    
    89     MarkStackSegment* nextSegment = MarkStackSegment::create(m_blockAllocator.allocate<MarkStackSegment>());
    90     m_numberOfSegments++;
    91    
    92 #if !ASSERT_DISABLED
    93     nextSegment->m_top = 0;
    94 #endif
    95 
    96     m_segments.push(nextSegment);
    97     setTopForEmptySegment();
    98     validatePrevious();
    99 }
    100 
    101 bool MarkStackArray::refill()
    102 {
    103     validatePrevious();
    104     if (top())
    105         return true;
    106     m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead()));
    107     ASSERT(m_numberOfSegments > 1);
    108     m_numberOfSegments--;
    109     setTopForFullSegment();
    110     validatePrevious();
    111     return true;
    11234}
    11335
     
    13456    // Remove our head and the head of the other list before we start moving segments around.
    13557    // We'll add them back on once we're done donating.
    136     MarkStackSegment* myHead = m_segments.removeHead();
    137     MarkStackSegment* otherHead = other.m_segments.removeHead();
     58    GCArraySegment<const JSCell*>* myHead = m_segments.removeHead();
     59    GCArraySegment<const JSCell*>* otherHead = other.m_segments.removeHead();
    13860
    13961    while (segmentsToDonate--) {
    140         MarkStackSegment* current = m_segments.removeHead();
     62        GCArraySegment<const JSCell*>* current = m_segments.removeHead();
    14163        ASSERT(current);
    14264        ASSERT(m_numberOfSegments > 1);
     
    16688    if (other.m_numberOfSegments > 1) {
    16789        // Move the heads of the lists aside. We'll push them back on after.
    168         MarkStackSegment* otherHead = other.m_segments.removeHead();
    169         MarkStackSegment* myHead = m_segments.removeHead();
     90        GCArraySegment<const JSCell*>* otherHead = other.m_segments.removeHead();
     91        GCArraySegment<const JSCell*>* myHead = m_segments.removeHead();
    17092
    17193        ASSERT(other.m_segments.head()->m_top == s_segmentCapacity);
     
    189111}
    190112
    191 void MarkStackArray::fillVector(Vector<const JSCell*>& vector)
    192 {
    193     ASSERT(vector.size() == size());
    194 
    195     MarkStackSegment* currentSegment = m_segments.head();
    196     if (!currentSegment)
    197         return;
    198 
    199     unsigned count = 0;
    200     for (unsigned i = 0; i < m_top; ++i) {
    201         ASSERT(currentSegment->data()[i]);
    202         vector[count++] = currentSegment->data()[i];
    203     }
    204 
    205     currentSegment = currentSegment->next();
    206     while (currentSegment) {
    207         for (unsigned i = 0; i < s_segmentCapacity; ++i) {
    208             ASSERT(currentSegment->data()[i]);
    209             vector[count++] = currentSegment->data()[i];
    210         }
    211         currentSegment = currentSegment->next();
    212     }
    213 }
    214 
    215113} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.