Title: [97642] trunk/Source/_javascript_Core
Revision
97642
Author
[email protected]
Date
2011-10-17 13:43:43 -0700 (Mon, 17 Oct 2011)

Log 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.

* _javascript_Core.exp:
* heap/HandleStack.cpp: Build!

* 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.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (97641 => 97642)


--- trunk/Source/_javascript_Core/ChangeLog	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-10-17 20:43:43 UTC (rev 97642)
@@ -1,3 +1,68 @@
+2011-10-17  Geoffrey Garen  <[email protected]>
+
+        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.
+
+        * _javascript_Core.exp:
+        * heap/HandleStack.cpp: Build!
+
+        * 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.
+
 2011-10-17  Adam Roben  <[email protected]>
 
         Windows build fix after r97536, part 3

Modified: trunk/Source/_javascript_Core/_javascript_Core.exp (97641 => 97642)


--- trunk/Source/_javascript_Core/_javascript_Core.exp	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/_javascript_Core.exp	2011-10-17 20:43:43 UTC (rev 97642)
@@ -172,6 +172,7 @@
 __ZN3JSC14JSGlobalObject6s_infoE
 __ZN3JSC14JSGlobalObjectD2Ev
 __ZN3JSC14MachineThreads16addCurrentThreadEv
+__ZN3JSC14MarkStackArray6expandEv
 __ZN3JSC14SamplingThread4stopEv
 __ZN3JSC14SamplingThread5startEj
 __ZN3JSC14ScopeChainNode6s_infoE
@@ -260,9 +261,9 @@
 __ZN3JSC6JSCell11getCallDataEPS0_RNS_8CallDataE
 __ZN3JSC6JSCell21deletePropertyVirtualEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC6JSCell21deletePropertyVirtualEPNS_9ExecStateEj
+__ZN3JSC6JSCell23getConstructDataVirtualERNS_13ConstructDataE
 __ZN3JSC6JSCell25getOwnPropertySlotVirtualEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC6JSCell25getOwnPropertySlotVirtualEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC6JSCell23getConstructDataVirtualERNS_13ConstructDataE
 __ZN3JSC6JSCell9getObjectEv
 __ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
 __ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
@@ -340,7 +341,6 @@
 __ZN3JSC8evaluateEPNS_9ExecStateEPNS_14ScopeChainNodeERKNS_10SourceCodeENS_7JSValueEPS7_
 __ZN3JSC9CodeBlockD1Ev
 __ZN3JSC9CodeBlockD2Ev
-__ZN3JSC9MarkStack13validateValueENS_7JSValueE
 __ZN3JSC9Structure21addPropertyTransitionERNS_12JSGlobalDataEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
 __ZN3JSC9Structure22materializePropertyMapERNS_12JSGlobalDataE
 __ZN3JSC9Structure25changePrototypeTransitionERNS_12JSGlobalDataEPS0_NS_7JSValueE

Modified: trunk/Source/_javascript_Core/heap/HandleStack.cpp (97641 => 97642)


--- trunk/Source/_javascript_Core/heap/HandleStack.cpp	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/heap/HandleStack.cpp	2011-10-17 20:43:43 UTC (rev 97642)
@@ -27,6 +27,8 @@
 #include "HandleStack.h"
 
 #include "HeapRootVisitor.h"
+#include "JSValueInlineMethods.h"
+#include "Structure.h"
 
 namespace JSC {
 

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (97641 => 97642)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2011-10-17 20:43:43 UTC (rev 97642)
@@ -315,7 +315,7 @@
     , m_markListSet(0)
     , m_activityCallback(DefaultGCActivityCallback::create(this))
     , m_machineThreads(this)
-    , m_slotVisitor(globalData->jsArrayVPtr)
+    , m_slotVisitor(globalData->jsArrayVPtr, globalData->jsFinalObjectVPtr, globalData->jsStringVPtr)
     , m_handleHeap(globalData)
     , m_isSafeToCollect(false)
     , m_globalData(globalData)

Modified: trunk/Source/_javascript_Core/heap/HeapRootVisitor.h (97641 => 97642)


--- trunk/Source/_javascript_Core/heap/HeapRootVisitor.h	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/heap/HeapRootVisitor.h	2011-10-17 20:43:43 UTC (rev 97642)
@@ -43,7 +43,6 @@
         void visit(JSValue*, size_t);
         void visit(JSString**);
         void visit(JSCell**);
-        void visitChildren(JSCell*);
 
         SlotVisitor& visitor();
 
@@ -76,11 +75,6 @@
         m_visitor.append(slot);
     }
 
-    inline void HeapRootVisitor::visitChildren(JSCell* cell)
-    {
-        m_visitor.visitChildren(cell);
-    }
-
     inline SlotVisitor& HeapRootVisitor::visitor()
     {
         return m_visitor;

Modified: trunk/Source/_javascript_Core/heap/MarkStack.cpp (97641 => 97642)


--- trunk/Source/_javascript_Core/heap/MarkStack.cpp	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/heap/MarkStack.cpp	2011-10-17 20:43:43 UTC (rev 97642)
@@ -33,14 +33,56 @@
 #include "JSObject.h"
 #include "ScopeChain.h"
 #include "Structure.h"
+#include "WriteBarrier.h"
 
 namespace JSC {
 
+MarkStackArray::MarkStackArray()
+    : m_top(0)
+    , m_allocated(pageSize())
+{
+    m_data = static_cast<const JSCell**>(MarkStack::allocateStack(m_allocated));
+    m_capacity = m_allocated / sizeof(JSCell*);
+}
+
+MarkStackArray::~MarkStackArray()
+{
+    MarkStack::releaseStack(m_data, m_allocated);
+}
+
+void MarkStackArray::expand()
+{
+    size_t oldAllocation = m_allocated;
+    m_allocated *= 2;
+    m_capacity = m_allocated / sizeof(JSCell*);
+    void* newData = MarkStack::allocateStack(m_allocated);
+    memcpy(newData, m_data, oldAllocation);
+    MarkStack::releaseStack(m_data, oldAllocation);
+    m_data = static_cast<const JSCell**>(newData);
+}
+
+void MarkStackArray::shrinkAllocation(size_t size)
+{
+    ASSERT(size <= m_allocated);
+    ASSERT(isPageAligned(size));
+    if (size == m_allocated)
+        return;
+#if OS(WINDOWS)
+    // We cannot release a part of a region with VirtualFree. To get around this,
+    // we'll release the entire region and reallocate the size that we want.
+    MarkStack::releaseStack(m_data, m_allocated);
+    m_data = static_cast<JSCell*>(MarkStack::allocateStack(size));
+#else
+    MarkStack::releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size);
+#endif
+    m_allocated = size;
+    m_capacity = m_allocated / sizeof(JSCell*);
+}
+
 void MarkStack::reset()
 {
     m_visitCount = 0;
-    m_values.shrinkAllocation(pageSize());
-    m_markSets.shrinkAllocation(pageSize());
+    m_stack.shrinkAllocation(pageSize());
     m_opaqueRoots.clear();
 }
 
@@ -52,89 +94,38 @@
         internalAppend(roots[i]);
 }
 
-void SlotVisitor::visitChildren(JSCell* cell)
+ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell, void* jsFinalObjectVPtr, void* jsArrayVPtr, void* jsStringVPtr)
 {
 #if ENABLE(SIMPLE_HEAP_PROFILING)
     m_visitedTypeCounts.count(cell);
 #endif
 
     ASSERT(Heap::isMarked(cell));
-    if (cell->structure()->typeInfo().type() < CompoundType) {
-        JSCell::visitChildren(cell, *this);
+
+    if (cell->vptr() == jsStringVPtr)
         return;
-    }
 
-    if (!cell->structure()->typeInfo().overridesVisitChildren()) {
-        ASSERT(cell->isObject());
-#ifdef NDEBUG
-        asObject(cell)->visitChildrenDirect(*this);
-#else
-        ASSERT(!m_isCheckingForDefaultMarkViolation);
-        m_isCheckingForDefaultMarkViolation = true;
-        cell->methodTable()->visitChildren(cell, *this);
-        ASSERT(m_isCheckingForDefaultMarkViolation);
-        m_isCheckingForDefaultMarkViolation = false;
-#endif
+    if (cell->vptr() == jsFinalObjectVPtr) {
+        JSObject::visitChildren(const_cast<JSCell*>(cell), visitor);
         return;
     }
-    if (cell->vptr() == m_jsArrayVPtr) {
-        asArray(cell)->visitChildrenDirect(*this);
+
+    if (cell->vptr() == jsArrayVPtr) {
+        JSArray::visitChildren(const_cast<JSCell*>(cell), visitor);
         return;
     }
-    cell->methodTable()->visitChildren(cell, *this);
+
+    cell->methodTable()->visitChildren(const_cast<JSCell*>(cell), visitor);
 }
 
 void SlotVisitor::drain()
 {
-#if !ASSERT_DISABLED
-    ASSERT(!m_isDraining);
-    m_isDraining = true;
-#endif
-    while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
-        while (!m_markSets.isEmpty() && m_values.size() < 50) {
-            ASSERT(!m_markSets.isEmpty());
-            MarkSet& current = m_markSets.last();
-            ASSERT(current.m_values);
-            JSValue* end = current.m_end;
-            ASSERT(current.m_values);
-            ASSERT(current.m_values != end);
-        findNextUnmarkedNullValue:
-            ASSERT(current.m_values != end);
-            JSValue value = *current.m_values;
-            current.m_values++;
+    void* jsFinalObjectVPtr = m_jsFinalObjectVPtr;
+    void* jsArrayVPtr = m_jsArrayVPtr;
+    void* jsStringVPtr = m_jsStringVPtr;
 
-            JSCell* cell;
-            if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) {
-                if (current.m_values == end) {
-                    m_markSets.removeLast();
-                    continue;
-                }
-                goto findNextUnmarkedNullValue;
-            }
-
-            if (cell->structure()->typeInfo().type() < CompoundType) {
-#if ENABLE(SIMPLE_HEAP_PROFILING)
-                m_visitedTypeCounts.count(cell);
-#endif
-                JSCell::visitChildren(cell, *this);
-                if (current.m_values == end) {
-                    m_markSets.removeLast();
-                    continue;
-                }
-                goto findNextUnmarkedNullValue;
-            }
-
-            if (current.m_values == end)
-                m_markSets.removeLast();
-
-            visitChildren(cell);
-        }
-        while (!m_values.isEmpty())
-            visitChildren(m_values.removeLast());
-    }
-#if !ASSERT_DISABLED
-    m_isDraining = false;
-#endif
+    while (!m_stack.isEmpty())
+        visitChildren(*this, m_stack.removeLast(), jsFinalObjectVPtr, jsArrayVPtr, jsStringVPtr);
 }
 
 void SlotVisitor::harvestWeakReferences()
@@ -149,21 +140,8 @@
 }
 
 #if ENABLE(GC_VALIDATION)
-void MarkStack::validateSet(JSValue* values, size_t count)
+void MarkStack::validate(JSCell* cell)
 {
-    for (size_t i = 0; i < count; i++) {
-        if (values[i])
-            validateValue(values[i]);
-    }
-}
-
-void MarkStack::validateValue(JSValue value)
-{
-    if (!value)
-        CRASH();
-    if (!value.isCell())
-        return;
-    JSCell* cell = value.asCell();
     if (!cell)
         CRASH();
 
@@ -176,9 +154,9 @@
         CRASH();
 }
 #else
-void MarkStack::validateValue(JSValue)
+void MarkStack::validate(JSCell*)
 {
-} 
+}
 #endif
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/heap/MarkStack.h (97641 => 97642)


--- trunk/Source/_javascript_Core/heap/MarkStack.h	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/heap/MarkStack.h	2011-10-17 20:43:43 UTC (rev 97642)
@@ -47,34 +47,25 @@
     template<typename T> class WriteBarrierBase;
     template<typename T> class JITWriteBarrier;
     
-    struct MarkSet {
-        MarkSet(JSValue* values, JSValue* end);
-
-        JSValue* m_values;
-        JSValue* m_end;
-    };
-
-    template<typename T> class MarkStackArray {
+    class MarkStackArray {
     public:
         MarkStackArray();
         ~MarkStackArray();
 
         void expand();
-        void append(const T&);
+        void append(const JSCell*);
 
-        T removeLast();
-        T& last();
+        const JSCell* removeLast();
 
         bool isEmpty();
-        size_t size();
 
         void shrinkAllocation(size_t);
 
     private:
+        const JSCell** m_data;
         size_t m_top;
-        size_t m_allocated;
         size_t m_capacity;
-        T* m_data;
+        size_t m_allocated;
     };
 
     class MarkStack {
@@ -85,17 +76,17 @@
         static void* allocateStack(size_t);
         static void releaseStack(void*, size_t);
 
-        MarkStack(void* jsArrayVPtr);
+        MarkStack(void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr);
         ~MarkStack();
 
         void append(ConservativeRoots&);
         
-        template<typename T> inline void append(JITWriteBarrier<T>*);
-        template<typename T> inline void append(WriteBarrierBase<T>*);
-        inline void appendValues(WriteBarrierBase<Unknown>*, size_t count);
+        template<typename T> void append(JITWriteBarrier<T>*);
+        template<typename T> void append(WriteBarrierBase<T>*);
+        void appendValues(WriteBarrierBase<Unknown>*, size_t count);
         
         template<typename T>
-        inline void appendUnbarrieredPointer(T**);
+        void appendUnbarrieredPointer(T**);
         
         bool addOpaqueRoot(void*);
         bool containsOpaqueRoot(void*);
@@ -118,10 +109,7 @@
         }
 
     protected:
-#if ENABLE(GC_VALIDATION)
-        static void validateSet(JSValue*, size_t);
-#endif
-        static void validateValue(JSValue);
+        static void validate(JSCell*);
 
         void append(JSValue*);
         void append(JSValue*, size_t count);
@@ -130,9 +118,10 @@
         void internalAppend(JSCell*);
         void internalAppend(JSValue);
 
+        MarkStackArray m_stack;
         void* m_jsArrayVPtr;
-        MarkStackArray<MarkSet> m_markSets;
-        MarkStackArray<JSCell*> m_values;
+        void* m_jsFinalObjectVPtr;
+        void* m_jsStringVPtr;
         HashSet<void*> m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
         WeakReferenceHarvester* m_firstWeakReferenceHarvester;
         
@@ -145,8 +134,10 @@
         size_t m_visitCount;
     };
 
-    inline MarkStack::MarkStack(void* jsArrayVPtr)
+    inline MarkStack::MarkStack(void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr)
         : m_jsArrayVPtr(jsArrayVPtr)
+        , m_jsFinalObjectVPtr(jsFinalObjectVPtr)
+        , m_jsStringVPtr(jsStringVPtr)
         , m_firstWeakReferenceHarvester(0)
 #if !ASSERT_DISABLED
         , m_isCheckingForDefaultMarkViolation(false)
@@ -158,8 +149,7 @@
 
     inline MarkStack::~MarkStack()
     {
-        ASSERT(m_markSets.isEmpty());
-        ASSERT(m_values.isEmpty());
+        ASSERT(m_stack.isEmpty());
     }
 
     inline bool MarkStack::addOpaqueRoot(void* root)
@@ -177,13 +167,6 @@
         return m_opaqueRoots.size();
     }
 
-    inline MarkSet::MarkSet(JSValue* values, JSValue* end)
-            : m_values(values)
-            , m_end(end)
-        {
-            ASSERT(values);
-        }
-
     inline void* MarkStack::allocateStack(size_t size)
     {
         return OSAllocator::reserveAndCommit(size);
@@ -194,117 +177,61 @@
         OSAllocator::decommitAndRelease(addr, size);
     }
 
-    template <typename T> inline MarkStackArray<T>::MarkStackArray()
-        : m_top(0)
-        , m_allocated(pageSize())
-        , m_capacity(m_allocated / sizeof(T))
+    inline void MarkStackArray::append(const JSCell* cell)
     {
-        m_data = reinterpret_cast<T*>(MarkStack::allocateStack(m_allocated));
-    }
-
-    template <typename T> inline MarkStackArray<T>::~MarkStackArray()
-    {
-        MarkStack::releaseStack(m_data, m_allocated);
-    }
-
-    template <typename T> inline void MarkStackArray<T>::expand()
-    {
-        size_t oldAllocation = m_allocated;
-        m_allocated *= 2;
-        m_capacity = m_allocated / sizeof(T);
-        void* newData = MarkStack::allocateStack(m_allocated);
-        memcpy(newData, m_data, oldAllocation);
-        MarkStack::releaseStack(m_data, oldAllocation);
-        m_data = reinterpret_cast<T*>(newData);
-    }
-
-    template <typename T> inline void MarkStackArray<T>::append(const T& v)
-    {
         if (m_top == m_capacity)
             expand();
-        m_data[m_top++] = v;
+        m_data[m_top++] = cell;
     }
 
-    template <typename T> inline T MarkStackArray<T>::removeLast()
+    inline const JSCell* MarkStackArray::removeLast()
     {
         ASSERT(m_top);
         return m_data[--m_top];
     }
     
-    template <typename T> inline T& MarkStackArray<T>::last()
+    inline bool MarkStackArray::isEmpty()
     {
-        ASSERT(m_top);
-        return m_data[m_top - 1];
+        return !m_top;
     }
 
-    template <typename T> inline bool MarkStackArray<T>::isEmpty()
+    ALWAYS_INLINE void MarkStack::append(JSValue* slot, size_t count)
     {
-        return m_top == 0;
+        for (size_t i = 0; i < count; ++i) {
+            JSValue& value = slot[i];
+            if (!value)
+                continue;
+            internalAppend(value);
+        }
     }
 
-    template <typename T> inline size_t MarkStackArray<T>::size()
-    {
-        return m_top;
-    }
-
-    template <typename T> inline void MarkStackArray<T>::shrinkAllocation(size_t size)
-    {
-        ASSERT(size <= m_allocated);
-        ASSERT(isPageAligned(size));
-        if (size == m_allocated)
-            return;
-#if OS(WINDOWS)
-        // We cannot release a part of a region with VirtualFree.  To get around this,
-        // we'll release the entire region and reallocate the size that we want.
-        MarkStack::releaseStack(m_data, m_allocated);
-        m_data = reinterpret_cast<T*>(MarkStack::allocateStack(size));
-#else
-        MarkStack::releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size);
-#endif
-        m_allocated = size;
-        m_capacity = m_allocated / sizeof(T);
-    }
-
-    inline void MarkStack::append(JSValue* slot, size_t count)
-    {
-        if (!count)
-            return;
-        m_visitCount += count;
-#if ENABLE(GC_VALIDATION)
-        validateSet(slot, count);
-#endif
-        m_markSets.append(MarkSet(slot, slot + count));
-    }
-
     template<typename T>
     inline void MarkStack::appendUnbarrieredPointer(T** slot)
     {
         ASSERT(slot);
-        JSCell* value = *slot;
-        if (value)
-            internalAppend(value);
+        JSCell* cell = *slot;
+        if (cell)
+            internalAppend(cell);
     }
     
-    ALWAYS_INLINE void MarkStack::append(JSValue* value)
+    ALWAYS_INLINE void MarkStack::append(JSValue* slot)
     {
-        ASSERT(value);
-        internalAppend(*value);
+        ASSERT(slot);
+        internalAppend(*slot);
     }
 
-    ALWAYS_INLINE void MarkStack::append(JSCell** value)
+    ALWAYS_INLINE void MarkStack::append(JSCell** slot)
     {
-        ASSERT(value);
-        internalAppend(*value);
+        ASSERT(slot);
+        internalAppend(*slot);
     }
 
     ALWAYS_INLINE void MarkStack::internalAppend(JSValue value)
     {
         ASSERT(value);
-#if ENABLE(GC_VALIDATION)
-        validateValue(value);
-#endif
-        if (value.isCell())
-            internalAppend(value.asCell());
+        if (!value.isCell())
+            return;
+        internalAppend(value.asCell());
     }
 
     class SlotVisitor;

Modified: trunk/Source/_javascript_Core/heap/SlotVisitor.h (97641 => 97642)


--- trunk/Source/_javascript_Core/heap/SlotVisitor.h	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/heap/SlotVisitor.h	2011-10-17 20:43:43 UTC (rev 97642)
@@ -33,17 +33,14 @@
 class SlotVisitor : public MarkStack {
     friend class HeapRootVisitor;
 public:
-    SlotVisitor(void* jsArrayVPtr);
+    SlotVisitor(void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr);
 
     void drain();
     void harvestWeakReferences();
-    
-private:
-    void visitChildren(JSCell*);
 };
 
-inline SlotVisitor::SlotVisitor(void* jsArrayVPtr)
-    : MarkStack(jsArrayVPtr)
+inline SlotVisitor::SlotVisitor(void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr)
+    : MarkStack(jsArrayVPtr, jsFinalObjectVPtr, jsStringVPtr)
 {
 }
 

Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (97641 => 97642)


--- trunk/Source/_javascript_Core/runtime/JSArray.cpp	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp	2011-10-17 20:43:43 UTC (rev 97642)
@@ -913,7 +913,19 @@
     ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
-    thisObject->visitChildrenDirect(visitor);
+
+    JSNonFinalObject::visitChildren(thisObject, visitor);
+    
+    ArrayStorage* storage = thisObject->m_storage;
+
+    unsigned usedVectorLength = std::min(storage->m_length, thisObject->m_vectorLength);
+    visitor.appendValues(storage->m_vector, usedVectorLength);
+
+    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+        SparseArrayValueMap::iterator end = map->end();
+        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
+            visitor.append(&it->second);
+    }
 }
 
 static int compareNumbersForQSort(const void* a, const void* b)

Modified: trunk/Source/_javascript_Core/runtime/JSArray.h (97641 => 97642)


--- trunk/Source/_javascript_Core/runtime/JSArray.h	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/runtime/JSArray.h	2011-10-17 20:43:43 UTC (rev 97642)
@@ -157,8 +157,6 @@
             return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
         
-        inline void visitChildrenDirect(SlotVisitor&);
-
         static ptrdiff_t storageOffset()
         {
             return OBJECT_OFFSETOF(JSArray, m_storage);
@@ -169,6 +167,8 @@
             return OBJECT_OFFSETOF(JSArray, m_vectorLength);
         }
 
+        static void visitChildren(JSCell*, SlotVisitor&);
+
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
         virtual void putVirtual(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
@@ -179,7 +179,6 @@
         virtual bool deletePropertyVirtual(ExecState*, unsigned propertyName);
         static bool deleteProperty(JSCell*, ExecState*, unsigned propertyName);
         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
-        static void visitChildren(JSCell*, SlotVisitor&);
 
         void* subclassData() const;
         void setSubclassData(void*);
@@ -218,22 +217,6 @@
     inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; }
     inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && isJSArray(globalData, v.asCell()); }
 
-    inline void JSArray::visitChildrenDirect(SlotVisitor& visitor)
-    {
-        JSObject::visitChildrenDirect(visitor);
-        
-        ArrayStorage* storage = m_storage;
-
-        unsigned usedVectorLength = std::min(storage->m_length, m_vectorLength);
-        visitor.appendValues(storage->m_vector, usedVectorLength);
-
-        if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
-            SparseArrayValueMap::iterator end = map->end();
-            for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
-                visitor.append(&it->second);
-        }
-    }
-
     // Rule from ECMA 15.2 about what an array index is.
     // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
     inline unsigned Identifier::toArrayIndex(bool& ok) const

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (97641 => 97642)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2011-10-17 20:43:43 UTC (rev 97642)
@@ -79,8 +79,14 @@
     visitor.m_isCheckingForDefaultMarkViolation = false;
 #endif
 
-    thisObject->visitChildrenDirect(visitor);
+    JSCell::visitChildren(thisObject, visitor);
 
+    PropertyStorage storage = thisObject->propertyStorage();
+    size_t storageSize = thisObject->structure()->propertyStorageSize();
+    visitor.appendValues(storage, storageSize);
+    if (thisObject->m_inheritorID)
+        visitor.append(&thisObject->m_inheritorID);
+
 #ifndef NDEBUG
     visitor.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
 #endif

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (97641 => 97642)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2011-10-17 20:43:43 UTC (rev 97642)
@@ -79,7 +79,6 @@
     public:
         typedef JSCell Base;
 
-        ALWAYS_INLINE void visitChildrenDirect(SlotVisitor&);
         static void visitChildren(JSCell*, SlotVisitor&);
 
         virtual UString className() const;
@@ -834,17 +833,6 @@
     asCell()->putVirtual(exec, propertyName, value);
 }
 
-ALWAYS_INLINE void JSObject::visitChildrenDirect(SlotVisitor& visitor)
-{
-    JSCell::visitChildren(this, visitor);
-
-    PropertyStorage storage = propertyStorage();
-    size_t storageSize = structure()->propertyStorageSize();
-    visitor.appendValues(storage, storageSize);
-    if (m_inheritorID)
-        visitor.append(&m_inheritorID);
-}
-
 // --- JSValue inlines ----------------------------
 
 ALWAYS_INLINE JSObject* Register::function() const

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (97641 => 97642)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2011-10-17 20:43:43 UTC (rev 97642)
@@ -355,12 +355,13 @@
     ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell)
     {
         ASSERT(!m_isCheckingForDefaultMarkViolation);
-        ASSERT(cell);
+#if ENABLE(GC_VALIDATION)
+        validate(cell);
+#endif
         m_visitCount++;
         if (Heap::testAndSetMarked(cell))
             return;
-        if (cell->structure() && cell->structure()->typeInfo().type() >= CompoundType)
-            m_values.append(cell);
+        m_stack.append(cell);
     }
 
     inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure)

Modified: trunk/Source/_javascript_Core/runtime/WriteBarrier.h (97641 => 97642)


--- trunk/Source/_javascript_Core/runtime/WriteBarrier.h	2011-10-17 20:29:59 UTC (rev 97641)
+++ trunk/Source/_javascript_Core/runtime/WriteBarrier.h	2011-10-17 20:43:43 UTC (rev 97642)
@@ -221,14 +221,9 @@
     internalAppend(*slot->slot());
 }
 
-inline void MarkStack::appendValues(WriteBarrierBase<Unknown>* barriers, size_t count)
+ALWAYS_INLINE void MarkStack::appendValues(WriteBarrierBase<Unknown>* barriers, size_t count)
 {
-    JSValue* values = barriers->slot();
-#if ENABLE(GC_VALIDATION)
-    validateSet(values, count);
-#endif
-    if (count)
-        m_markSets.append(MarkSet(values, values + count));
+    append(barriers->slot(), count);
 }
 
 } // namespace JSC
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to