void WeakBlock::visit(HeapRootVisitor& heapRootVisitor) { // If a block is completely empty, a visit won't have any effect. if (isEmpty()) return; // If this WeakBlock doesn't belong to a MarkedBlock, we won't even be here. ASSERT(m_markedBlock); // We only visit after marking. ASSERT(m_markedBlock->isMarkedOrRetired()); SlotVisitor& visitor = heapRootVisitor.visitor(); for (size_t i = 0; i < weakImplCount(); ++i) { WeakImpl* weakImpl = &weakImpls()[i]; if (weakImpl->state() != WeakImpl::Live) continue; WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner(); if (!weakHandleOwner) continue; const JSValue& jsValue = weakImpl->jsValue(); if (m_markedBlock->isMarkedOrNewlyAllocated(jsValue.asCell())) continue; if (!weakHandleOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(jsValue)), weakImpl->context(), visitor)) continue; heapRootVisitor.visit(&const_cast<JSValue&>(jsValue)); } }
void SmallStrings::visitChildren(HeapRootVisitor& heapRootMarker) { /* Our hypothesis is that small strings are very common. So, we cache them to avoid GC churn. However, in cases where this hypothesis turns out to be false -- including the degenerate case where all JavaScript execution has terminated -- we don't want to waste memory. To test our hypothesis, we check if any small string has been marked. If so, it's probably reasonable to mark the rest. If not, we clear the cache. */ bool isAnyStringMarked = isMarked(m_emptyString); for (unsigned i = 0; i < singleCharacterStringCount && !isAnyStringMarked; ++i) isAnyStringMarked = isMarked(m_singleCharacterStrings[i]); if (!isAnyStringMarked) { clear(); return; } if (m_emptyString) heapRootMarker.mark(&m_emptyString); for (unsigned i = 0; i < singleCharacterStringCount; ++i) { if (m_singleCharacterStrings[i]) heapRootMarker.mark(&m_singleCharacterStrings[i]); } }
void WeakBlock::specializedVisit(ContainerType& container, HeapRootVisitor& heapRootVisitor) { SlotVisitor& visitor = heapRootVisitor.visitor(); HeapVersion markingVersion = visitor.markingVersion(); for (size_t i = 0; i < weakImplCount(); ++i) { WeakImpl* weakImpl = &weakImpls()[i]; if (weakImpl->state() != WeakImpl::Live) continue; WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner(); if (!weakHandleOwner) continue; const JSValue& jsValue = weakImpl->jsValue(); if (container.isMarkedConcurrently(markingVersion, jsValue.asCell())) continue; if (!weakHandleOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(jsValue)), weakImpl->context(), visitor)) continue; heapRootVisitor.visit(&const_cast<JSValue&>(jsValue)); } }
void WeakBlock::visitLiveWeakImpls(HeapRootVisitor& heapRootVisitor) { // If a block is completely empty, a visit won't have any effect. if (!m_sweepResult.isNull() && m_sweepResult.blockIsFree) return; SlotVisitor& visitor = heapRootVisitor.visitor(); for (size_t i = 0; i < weakImplCount(); ++i) { WeakImpl* weakImpl = &weakImpls()[i]; if (weakImpl->state() != WeakImpl::Live) continue; const JSValue& jsValue = weakImpl->jsValue(); if (Heap::isMarked(jsValue.asCell())) continue; WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner(); if (!weakHandleOwner) continue; if (!weakHandleOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(jsValue)), weakImpl->context(), visitor)) continue; heapRootVisitor.visit(&const_cast<JSValue&>(jsValue)); } }
void Heap::visitException(HeapRootVisitor& visitor) { GCPHASE(MarkingException); if (!m_vm->exception() && !m_vm->lastException()) return; visitor.visit(m_vm->addressOfException()); visitor.visit(m_vm->addressOfLastException()); if (Options::logGC() == GCLogging::Verbose) dataLog("Exceptions:\n", m_slotVisitor); m_slotVisitor.donateAndDrain(); }
void MarkedArgumentBuffer::markLists(HeapRootVisitor& heapRootVisitor, ListSet& markSet) { ListSet::iterator end = markSet.end(); for (ListSet::iterator it = markSet.begin(); it != end; ++it) { MarkedArgumentBuffer* list = *it; for (int i = 0; i < list->m_size; ++i) heapRootVisitor.visit(reinterpret_cast<JSValue*>(&list->slotFor(i))); } }
void HandleSet::visitStrongHandles(HeapRootVisitor& heapRootVisitor) { Node* end = m_strongList.end(); for (Node* node = m_strongList.begin(); node != end; node = node->next()) { #if ENABLE(GC_VALIDATION) RELEASE_ASSERT(isLiveNode(node)); #endif heapRootVisitor.visit(node->slot()); } }
void Heap::visitProtectedObjects(HeapRootVisitor& heapRootVisitor) { GCPHASE(VisitProtectedObjects); for (auto& pair : m_protectedValues) heapRootVisitor.visit(&pair.key); if (Options::logGC() == GCLogging::Verbose) dataLog("Protected Objects:\n", m_slotVisitor); m_slotVisitor.donateAndDrain(); }
void HandleHeap::markWeakHandles(HeapRootVisitor& heapRootVisitor) { SlotVisitor& visitor = heapRootVisitor.visitor(); Node* end = m_weakList.end(); for (Node* node = m_weakList.begin(); node != end; node = node->next()) { ASSERT(isValidWeakNode(node)); JSCell* cell = node->slot()->asCell(); if (Heap::isMarked(cell)) continue; WeakHandleOwner* weakOwner = node->weakOwner(); if (!weakOwner) continue; if (!weakOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext(), visitor)) continue; heapRootVisitor.mark(node->slot()); } }
void HandleHeap::visitWeakHandles(HeapRootVisitor& heapRootVisitor) { SlotVisitor& visitor = heapRootVisitor.visitor(); Node* end = m_weakList.end(); for (Node* node = m_weakList.begin(); node != end; node = node->next()) { #if ENABLE(GC_VALIDATION) if (!isValidWeakNode(node)) CRASH(); #endif JSCell* cell = node->slot()->asCell(); if (Heap::isMarked(cell)) continue; WeakHandleOwner* weakOwner = node->weakOwner(); if (!weakOwner) continue; if (!weakOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext(), visitor)) continue; heapRootVisitor.visit(node->slot()); } }
void Heap::markTempSortVectors(HeapRootVisitor& heapRootVisitor) { typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors; VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end(); for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) { Vector<ValueStringPair>* tempSortingVector = *it; Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end(); for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) { if (vectorIt->first) heapRootVisitor.visit(&vectorIt->first); } } }
void Heap::markProtectedObjects(HeapRootVisitor& heapRootVisitor) { ProtectCountSet::iterator end = m_protectedValues.end(); for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) heapRootVisitor.visit(&it->first); }
void HandleHeap::markStrongHandles(HeapRootVisitor& heapRootMarker) { Node* end = m_strongList.end(); for (Node* node = m_strongList.begin(); node != end; node = node->next()) heapRootMarker.mark(node->slot()); }