void notifyFinished() { if (!m_constructRetainedObjectInfos) return; std::sort(m_groupsWhichNeedRetainerInfo.begin(), m_groupsWhichNeedRetainerInfo.end()); Node* alreadyAdded = 0; v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); for (size_t i = 0; i < m_groupsWhichNeedRetainerInfo.size(); ++i) { Node* root = m_groupsWhichNeedRetainerInfo[i]; if (root != alreadyAdded) { profiler->SetRetainedObjectInfo(v8::UniqueId(reinterpret_cast<intptr_t>(root)), new RetainedDOMInfo(root)); alreadyAdded = root; } } if (m_liveRootGroupIdSet) profiler->SetRetainedObjectInfo(liveRootId(), new ActiveDOMObjectsInfo(m_domObjectsWithPendingActivity)); }
virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override { if (classId != WrapperTypeInfo::NodeClassId && classId != WrapperTypeInfo::ObjectClassId) return; // Casting to a Handle is safe here, since the Persistent doesn't get GCd // during the GC prologue. ASSERT((*reinterpret_cast<v8::Handle<v8::Value>*>(value))->IsObject()); v8::Handle<v8::Object>* wrapper = reinterpret_cast<v8::Handle<v8::Object>*>(value); ASSERT(V8DOMWrapper::isDOMWrapper(*wrapper)); if (value->IsIndependent()) return; const WrapperTypeInfo* type = toWrapperTypeInfo(*wrapper); ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(*wrapper); if (activeDOMObject && activeDOMObject->hasPendingActivity()) { m_isolate->SetObjectGroupId(*value, liveRootId()); ++m_domObjectsWithPendingActivity; } if (classId == WrapperTypeInfo::NodeClassId) { ASSERT(V8Node::hasInstance(*wrapper, m_isolate)); Node* node = V8Node::toImpl(*wrapper); if (node->hasEventListeners()) addReferencesForNodeWithEventListeners(m_isolate, node, v8::Persistent<v8::Object>::Cast(*value)); Node* root = V8GCController::opaqueRootForGC(m_isolate, node); m_isolate->SetObjectGroupId(*value, v8::UniqueId(reinterpret_cast<intptr_t>(root))); if (m_constructRetainedObjectInfos) m_groupsWhichNeedRetainerInfo.append(root); } else if (classId == WrapperTypeInfo::ObjectClassId) { type->visitDOMWrapper(m_isolate, toScriptWrappableBase(*wrapper), v8::Persistent<v8::Object>::Cast(*value)); } else { ASSERT_NOT_REACHED(); } }
void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override { if (classId != WrapperTypeInfo::NodeClassId && classId != WrapperTypeInfo::ObjectClassId) return; v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(m_isolate, v8::Persistent<v8::Object>::Cast(*value)); ASSERT(V8DOMWrapper::hasInternalFieldsSet(wrapper)); const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper); if (type != npObjectTypeInfo() && toScriptWrappable(wrapper)->hasPendingActivity()) { // If you hit this assert, you'll need to add a [DependentiLifetime] // extended attribute to the DOM interface. A DOM interface that // overrides hasPendingActivity must be marked as [DependentiLifetime]. RELEASE_ASSERT(!value->IsIndependent()); m_isolate->SetObjectGroupId(*value, liveRootId()); ++m_domObjectsWithPendingActivity; } if (value->IsIndependent()) return; if (classId == WrapperTypeInfo::NodeClassId) { ASSERT(V8Node::hasInstance(wrapper, m_isolate)); Node* node = V8Node::toImpl(wrapper); if (node->hasEventListeners()) addReferencesForNodeWithEventListeners(m_isolate, node, v8::Persistent<v8::Object>::Cast(*value)); Node* root = V8GCController::opaqueRootForGC(m_isolate, node); m_isolate->SetObjectGroupId(*value, v8::UniqueId(reinterpret_cast<intptr_t>(root))); if (m_constructRetainedObjectInfos) m_groupsWhichNeedRetainerInfo.append(root); } else if (classId == WrapperTypeInfo::ObjectClassId) { type->visitDOMWrapper(m_isolate, toScriptWrappable(wrapper), v8::Persistent<v8::Object>::Cast(*value)); } else { ASSERT_NOT_REACHED(); } }