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