Ignore:
Timestamp:
Oct 17, 2011, 1:43:43 PM (14 years ago)
Author:
[email protected]
Message:

Simplified GC marking logic
https://bugs.webkit.org/show_bug.cgi?id=70258

Reviewed by Filip Pizlo.

No perf. change.

This is a first step toward GC allocating string backing stores, starting
with ropes. It also enables future simplifications and optimizations.

  • Replaced some complex mark stack logic with a simple linear stack of

JSCell pointers.

  • Replaced logic for short-circuiting marking based on JSType and/or

Structure flags with special cases for object, array, and string.

  • Fiddled with inlining for better codegen.
  • heap/Heap.cpp:

(JSC::Heap::Heap): Provide more vptrs to SlotVisitor, for use in marking.

  • heap/HeapRootVisitor.h: Removed unused functions that no longer build.
  • heap/MarkStack.cpp:

(JSC::MarkStackArray::MarkStackArray):
(JSC::MarkStackArray::~MarkStackArray):
(JSC::MarkStackArray::expand):
(JSC::MarkStackArray::shrinkAllocation):
(JSC::MarkStack::reset):
(JSC::visitChildren):
(JSC::SlotVisitor::drain):

  • heap/MarkStack.h:

(JSC::MarkStack::MarkStack):
(JSC::MarkStack::~MarkStack):
(JSC::MarkStackArray::append):
(JSC::MarkStackArray::removeLast):
(JSC::MarkStackArray::isEmpty):
(JSC::MarkStack::append):
(JSC::MarkStack::appendUnbarrieredPointer):
(JSC::MarkStack::internalAppend): Replaced complex mark set logic with
simple linear stack.

  • heap/SlotVisitor.h:

(JSC::SlotVisitor::SlotVisitor): Updated for above changes.

  • runtime/JSArray.cpp:

(JSC::JSArray::visitChildren):

  • runtime/JSArray.h:
  • runtime/JSObject.cpp:

(JSC::JSObject::visitChildren):

  • runtime/JSObject.h: Don't inline visitChildren; it's too big.
  • runtime/Structure.h:

(JSC::MarkStack::internalAppend): Nixed the short-circuit for CompoundType
because it prevented strings from owning GC pointers.

  • runtime/WriteBarrier.h:

(JSC::MarkStack::appendValues): No need to validate; internalAppend will
do that for us.

File:
1 edited

Legend:

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

    r97557 r97642  
    4848    template<typename T> class JITWriteBarrier;
    4949   
    50     struct MarkSet {
    51         MarkSet(JSValue* values, JSValue* end);
    52 
    53         JSValue* m_values;
    54         JSValue* m_end;
    55     };
    56 
    57     template<typename T> class MarkStackArray {
     50    class MarkStackArray {
    5851    public:
    5952        MarkStackArray();
     
    6154
    6255        void expand();
    63         void append(const T&);
    64 
    65         T removeLast();
    66         T& last();
     56        void append(const JSCell*);
     57
     58        const JSCell* removeLast();
    6759
    6860        bool isEmpty();
    69         size_t size();
    7061
    7162        void shrinkAllocation(size_t);
    7263
    7364    private:
     65        const JSCell** m_data;
    7466        size_t m_top;
     67        size_t m_capacity;
    7568        size_t m_allocated;
    76         size_t m_capacity;
    77         T* m_data;
    7869    };
    7970
     
    8677        static void releaseStack(void*, size_t);
    8778
    88         MarkStack(void* jsArrayVPtr);
     79        MarkStack(void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr);
    8980        ~MarkStack();
    9081
    9182        void append(ConservativeRoots&);
    9283       
    93         template<typename T> inline void append(JITWriteBarrier<T>*);
    94         template<typename T> inline void append(WriteBarrierBase<T>*);
    95         inline void appendValues(WriteBarrierBase<Unknown>*, size_t count);
     84        template<typename T> void append(JITWriteBarrier<T>*);
     85        template<typename T> void append(WriteBarrierBase<T>*);
     86        void appendValues(WriteBarrierBase<Unknown>*, size_t count);
    9687       
    9788        template<typename T>
    98         inline void appendUnbarrieredPointer(T**);
     89        void appendUnbarrieredPointer(T**);
    9990       
    10091        bool addOpaqueRoot(void*);
     
    119110
    120111    protected:
    121 #if ENABLE(GC_VALIDATION)
    122         static void validateSet(JSValue*, size_t);
    123 #endif
    124         static void validateValue(JSValue);
     112        static void validate(JSCell*);
    125113
    126114        void append(JSValue*);
     
    131119        void internalAppend(JSValue);
    132120
     121        MarkStackArray m_stack;
    133122        void* m_jsArrayVPtr;
    134         MarkStackArray<MarkSet> m_markSets;
    135         MarkStackArray<JSCell*> m_values;
     123        void* m_jsFinalObjectVPtr;
     124        void* m_jsStringVPtr;
    136125        HashSet<void*> m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
    137126        WeakReferenceHarvester* m_firstWeakReferenceHarvester;
     
    146135    };
    147136
    148     inline MarkStack::MarkStack(void* jsArrayVPtr)
     137    inline MarkStack::MarkStack(void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr)
    149138        : m_jsArrayVPtr(jsArrayVPtr)
     139        , m_jsFinalObjectVPtr(jsFinalObjectVPtr)
     140        , m_jsStringVPtr(jsStringVPtr)
    150141        , m_firstWeakReferenceHarvester(0)
    151142#if !ASSERT_DISABLED
     
    159150    inline MarkStack::~MarkStack()
    160151    {
    161         ASSERT(m_markSets.isEmpty());
    162         ASSERT(m_values.isEmpty());
     152        ASSERT(m_stack.isEmpty());
    163153    }
    164154
     
    178168    }
    179169
    180     inline MarkSet::MarkSet(JSValue* values, JSValue* end)
    181             : m_values(values)
    182             , m_end(end)
    183         {
    184             ASSERT(values);
    185         }
    186 
    187170    inline void* MarkStack::allocateStack(size_t size)
    188171    {
     
    195178    }
    196179
    197     template <typename T> inline MarkStackArray<T>::MarkStackArray()
    198         : m_top(0)
    199         , m_allocated(pageSize())
    200         , m_capacity(m_allocated / sizeof(T))
    201     {
    202         m_data = reinterpret_cast<T*>(MarkStack::allocateStack(m_allocated));
    203     }
    204 
    205     template <typename T> inline MarkStackArray<T>::~MarkStackArray()
    206     {
    207         MarkStack::releaseStack(m_data, m_allocated);
    208     }
    209 
    210     template <typename T> inline void MarkStackArray<T>::expand()
    211     {
    212         size_t oldAllocation = m_allocated;
    213         m_allocated *= 2;
    214         m_capacity = m_allocated / sizeof(T);
    215         void* newData = MarkStack::allocateStack(m_allocated);
    216         memcpy(newData, m_data, oldAllocation);
    217         MarkStack::releaseStack(m_data, oldAllocation);
    218         m_data = reinterpret_cast<T*>(newData);
    219     }
    220 
    221     template <typename T> inline void MarkStackArray<T>::append(const T& v)
     180    inline void MarkStackArray::append(const JSCell* cell)
    222181    {
    223182        if (m_top == m_capacity)
    224183            expand();
    225         m_data[m_top++] = v;
    226     }
    227 
    228     template <typename T> inline T MarkStackArray<T>::removeLast()
     184        m_data[m_top++] = cell;
     185    }
     186
     187    inline const JSCell* MarkStackArray::removeLast()
    229188    {
    230189        ASSERT(m_top);
     
    232191    }
    233192   
    234     template <typename T> inline T& MarkStackArray<T>::last()
    235     {
    236         ASSERT(m_top);
    237         return m_data[m_top - 1];
    238     }
    239 
    240     template <typename T> inline bool MarkStackArray<T>::isEmpty()
    241     {
    242         return m_top == 0;
    243     }
    244 
    245     template <typename T> inline size_t MarkStackArray<T>::size()
    246     {
    247         return m_top;
    248     }
    249 
    250     template <typename T> inline void MarkStackArray<T>::shrinkAllocation(size_t size)
    251     {
    252         ASSERT(size <= m_allocated);
    253         ASSERT(isPageAligned(size));
    254         if (size == m_allocated)
    255             return;
    256 #if OS(WINDOWS)
    257         // We cannot release a part of a region with VirtualFree.  To get around this,
    258         // we'll release the entire region and reallocate the size that we want.
    259         MarkStack::releaseStack(m_data, m_allocated);
    260         m_data = reinterpret_cast<T*>(MarkStack::allocateStack(size));
    261 #else
    262         MarkStack::releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size);
    263 #endif
    264         m_allocated = size;
    265         m_capacity = m_allocated / sizeof(T);
    266     }
    267 
    268     inline void MarkStack::append(JSValue* slot, size_t count)
    269     {
    270         if (!count)
    271             return;
    272         m_visitCount += count;
    273 #if ENABLE(GC_VALIDATION)
    274         validateSet(slot, count);
    275 #endif
    276         m_markSets.append(MarkSet(slot, slot + count));
     193    inline bool MarkStackArray::isEmpty()
     194    {
     195        return !m_top;
     196    }
     197
     198    ALWAYS_INLINE void MarkStack::append(JSValue* slot, size_t count)
     199    {
     200        for (size_t i = 0; i < count; ++i) {
     201            JSValue& value = slot[i];
     202            if (!value)
     203                continue;
     204            internalAppend(value);
     205        }
    277206    }
    278207
     
    281210    {
    282211        ASSERT(slot);
    283         JSCell* value = *slot;
    284         if (value)
    285             internalAppend(value);
     212        JSCell* cell = *slot;
     213        if (cell)
     214            internalAppend(cell);
    286215    }
    287216   
    288     ALWAYS_INLINE void MarkStack::append(JSValue* value)
     217    ALWAYS_INLINE void MarkStack::append(JSValue* slot)
     218    {
     219        ASSERT(slot);
     220        internalAppend(*slot);
     221    }
     222
     223    ALWAYS_INLINE void MarkStack::append(JSCell** slot)
     224    {
     225        ASSERT(slot);
     226        internalAppend(*slot);
     227    }
     228
     229    ALWAYS_INLINE void MarkStack::internalAppend(JSValue value)
    289230    {
    290231        ASSERT(value);
    291         internalAppend(*value);
    292     }
    293 
    294     ALWAYS_INLINE void MarkStack::append(JSCell** value)
    295     {
    296         ASSERT(value);
    297         internalAppend(*value);
    298     }
    299 
    300     ALWAYS_INLINE void MarkStack::internalAppend(JSValue value)
    301     {
    302         ASSERT(value);
    303 #if ENABLE(GC_VALIDATION)
    304         validateValue(value);
    305 #endif
    306         if (value.isCell())
    307             internalAppend(value.asCell());
     232        if (!value.isCell())
     233            return;
     234        internalAppend(value.asCell());
    308235    }
    309236
Note: See TracChangeset for help on using the changeset viewer.