-MarkStackThreadSharedData::MarkStackThreadSharedData(JSGlobalData* globalData)
- : m_globalData(globalData)
- , m_copiedSpace(&globalData->heap.m_storageSpace)
- , m_sharedMarkStack(m_segmentAllocator)
- , m_numberOfActiveParallelMarkers(0)
- , m_parallelMarkersShouldExit(false)
-{
-#if ENABLE(PARALLEL_GC)
- for (unsigned i = 1; i < Options::numberOfGCMarkers; ++i) {
- m_markingThreads.append(createThread(markingThreadStartFunc, this, "JavaScriptCore::Marking"));
- ASSERT(m_markingThreads.last());
- }
-#endif
-}
-
-MarkStackThreadSharedData::~MarkStackThreadSharedData()
-{
-#if ENABLE(PARALLEL_GC)
- // Destroy our marking threads.
- {
- MutexLocker locker(m_markingLock);
- m_parallelMarkersShouldExit = true;
- m_markingCondition.broadcast();
- }
- for (unsigned i = 0; i < m_markingThreads.size(); ++i)
- waitForThreadCompletion(m_markingThreads[i]);
-#endif
-}
-
-void MarkStackThreadSharedData::reset()
-{
- ASSERT(!m_numberOfActiveParallelMarkers);
- ASSERT(!m_parallelMarkersShouldExit);
- ASSERT(m_sharedMarkStack.isEmpty());
-
-#if ENABLE(PARALLEL_GC)
- m_segmentAllocator.shrinkReserve();
- m_opaqueRoots.clear();
-#else
- ASSERT(m_opaqueRoots.isEmpty());
-#endif
-
- m_weakReferenceHarvesters.removeAll();
-}
-
-void MarkStack::reset()
-{
- m_visitCount = 0;
- ASSERT(m_stack.isEmpty());
-#if ENABLE(PARALLEL_GC)
- ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now.
-#else
- m_opaqueRoots.clear();
-#endif
-}
-
-void MarkStack::append(ConservativeRoots& conservativeRoots)
-{
- JSCell** roots = conservativeRoots.roots();
- size_t size = conservativeRoots.size();
- for (size_t i = 0; i < size; ++i)
- internalAppend(roots[i]);
-}
-
-ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell)
-{
-#if ENABLE(SIMPLE_HEAP_PROFILING)
- m_visitedTypeCounts.count(cell);
-#endif
-
- ASSERT(Heap::isMarked(cell));
-
- if (isJSString(cell)) {
- JSString::visitChildren(const_cast<JSCell*>(cell), visitor);
- return;
- }
-
- if (isJSFinalObject(cell)) {
- JSObject::visitChildren(const_cast<JSCell*>(cell), visitor);
- return;
- }
-
- if (isJSArray(cell)) {
- JSArray::visitChildren(const_cast<JSCell*>(cell), visitor);
- return;
- }
-
- cell->methodTable()->visitChildren(const_cast<JSCell*>(cell), visitor);
-}
-
-void SlotVisitor::donateSlow()
-{
- // Refuse to donate if shared has more entries than I do.
- if (m_shared.m_sharedMarkStack.size() > m_stack.size())
- return;
- MutexLocker locker(m_shared.m_markingLock);
- if (m_stack.donateSomeCellsTo(m_shared.m_sharedMarkStack)) {
- // Only wake up threads if the shared stack is big enough; otherwise assume that
- // it's more profitable for us to just scan this ourselves later.
- if (m_shared.m_sharedMarkStack.size() >= Options::sharedStackWakeupThreshold)
- m_shared.m_markingCondition.broadcast();
- }
-}
-
-void SlotVisitor::drain()
-{
- ASSERT(m_isInParallelMode);
-
-#if ENABLE(PARALLEL_GC)
- if (Options::numberOfGCMarkers > 1) {
- while (!m_stack.isEmpty()) {
- m_stack.refill();
- for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance; m_stack.canRemoveLast() && countdown--;)
- visitChildren(*this, m_stack.removeLast());
- donateKnownParallel();
- }