Chromium Code Reviews| Index: Source/bindings/v8/V8GCController.cpp |
| diff --git a/Source/bindings/v8/V8GCController.cpp b/Source/bindings/v8/V8GCController.cpp |
| index f5cb623c115512b71d9427d26f5eb2af60e08f73..2cdfd956e141951462a06f0fc2a63201a0c08ab1 100644 |
| --- a/Source/bindings/v8/V8GCController.cpp |
| +++ b/Source/bindings/v8/V8GCController.cpp |
| @@ -47,145 +47,14 @@ |
| namespace WebCore { |
| -class ImplicitConnection { |
| -public: |
| - ImplicitConnection(void* root, v8::Persistent<v8::Object> wrapper) |
| - : m_root(root) |
| - , m_wrapper(wrapper) |
| - , m_rootNode(0) |
| - { |
| - } |
| - ImplicitConnection(Node* root, v8::Persistent<v8::Object> wrapper) |
| - : m_root(root) |
| - , m_wrapper(wrapper) |
| - , m_rootNode(root) |
| - { |
| - } |
| - |
| - void* root() const { return m_root; } |
| - v8::Persistent<v8::Object> wrapper() const { return m_wrapper; } |
| - |
| - PassOwnPtr<RetainedObjectInfo> retainedObjectInfo() |
| - { |
| - if (!m_rootNode) |
| - return nullptr; |
| - return adoptPtr(new RetainedDOMInfo(m_rootNode)); |
| - } |
| - |
| -private: |
| - void* m_root; |
| - v8::Persistent<v8::Object> m_wrapper; |
| - Node* m_rootNode; |
| -}; |
| - |
| -bool operator<(const ImplicitConnection& left, const ImplicitConnection& right) |
| -{ |
| - return left.root() < right.root(); |
| -} |
| - |
| -struct ImplicitReference { |
| - ImplicitReference(void* parent, v8::Persistent<v8::Object> child) |
| - : parent(parent) |
| - , child(child) |
| - { |
| - } |
| - |
| - void* parent; |
| - v8::Persistent<v8::Object> child; |
| -}; |
| - |
| -bool operator<(const ImplicitReference& left, const ImplicitReference& right) |
| -{ |
| - return left.parent < right.parent; |
| -} |
| - |
| -class WrapperGrouper { |
| -public: |
| - WrapperGrouper() |
| - { |
| - m_liveObjects.append(V8PerIsolateData::current()->ensureLiveRoot()); |
| - } |
| - |
| - void addObjectWrapperToGroup(void* root, v8::Persistent<v8::Object> wrapper) |
| - { |
| - m_connections.append(ImplicitConnection(root, wrapper)); |
| - } |
| - |
| - void addNodeWrapperToGroup(Node* root, v8::Persistent<v8::Object> wrapper) |
| - { |
| - m_connections.append(ImplicitConnection(root, wrapper)); |
| - } |
| - |
| - void addImplicitReference(void* parent, v8::Persistent<v8::Object> child) |
| - { |
| - m_references.append(ImplicitReference(parent, child)); |
| - m_rootGroupMap.add(parent, v8::Persistent<v8::Object>()); |
| - } |
| - |
| - void keepAlive(v8::Persistent<v8::Value> wrapper) |
| - { |
| - m_liveObjects.append(wrapper); |
| - } |
| - |
| - void apply() |
| - { |
| - if (m_liveObjects.size() > 1) |
| - v8::V8::AddObjectGroup(m_liveObjects.data(), m_liveObjects.size()); |
| - |
| - std::sort(m_connections.begin(), m_connections.end()); |
| - Vector<v8::Persistent<v8::Value> > group; |
| - size_t i = 0; |
| - while (i < m_connections.size()) { |
| - void* root = m_connections[i].root(); |
| - v8::Persistent<v8::Object> groupRepresentativeWrapper = m_connections[i].wrapper(); |
| - OwnPtr<RetainedObjectInfo> retainedObjectInfo = m_connections[i].retainedObjectInfo(); |
| - |
| - do { |
| - group.append(m_connections[i++].wrapper()); |
| - } while (i < m_connections.size() && root == m_connections[i].root()); |
| - |
| - if (group.size() > 1) |
| - v8::V8::AddObjectGroup(group.data(), group.size(), retainedObjectInfo.leakPtr()); |
| - |
| - HashMap<void*, v8::Persistent<v8::Object> >::iterator iter = m_rootGroupMap.find(root); |
| - if (iter != m_rootGroupMap.end()) |
| - iter->value = groupRepresentativeWrapper; |
| - |
| - group.shrink(0); |
| - } |
| - |
| - std::sort(m_references.begin(), m_references.end()); |
| - i = 0; |
| - while (i < m_references.size()) { |
| - void* parent = m_references[i].parent; |
| - v8::Persistent<v8::Object> parentWrapper = m_rootGroupMap.get(parent); |
| - if (parentWrapper.IsEmpty()) { |
| - ++i; |
| - continue; |
| - } |
| - |
| - Vector<v8::Persistent<v8::Value> > children; |
| - do { |
| - children.append(m_references[i++].child); |
| - } while (i < m_references.size() && parent == m_references[i].parent); |
| - |
| - v8::V8::AddImplicitReferences(parentWrapper, children.data(), children.size()); |
| - } |
| - } |
| - |
| -private: |
| - Vector<v8::Persistent<v8::Value> > m_liveObjects; |
| - Vector<ImplicitConnection> m_connections; |
| - Vector<ImplicitReference> m_references; |
| - HashMap<void*, v8::Persistent<v8::Object> > m_rootGroupMap; |
| -}; |
| - |
| // FIXME: This should use opaque GC roots. |
| -static void addImplicitReferencesForNodeWithEventListeners(Node* node, v8::Persistent<v8::Object> wrapper) |
| +static void addImplicitReferencesForNodeWithEventListeners(v8::Isolate* isolate, Node* node, v8::Persistent<v8::Object> wrapper) |
| { |
| ASSERT(node->hasEventListeners()); |
| - Vector<v8::Persistent<v8::Value> > listeners; |
| + // Add a new object group just for the wrapper. |
| + v8::UniqueId id(reinterpret_cast<intptr_t>(*wrapper)); |
| + v8::V8::SetObjectGroupId(isolate, wrapper, id); |
| EventListenerIterator iterator(node); |
| while (EventListener* listener = iterator.nextListener()) { |
| @@ -194,13 +63,9 @@ static void addImplicitReferencesForNodeWithEventListeners(Node* node, v8::Persi |
| V8AbstractEventListener* v8listener = static_cast<V8AbstractEventListener*>(listener); |
| if (!v8listener->hasExistingListenerObject()) |
| continue; |
| - listeners.append(v8listener->existingListenerObjectPersistentHandle()); |
| - } |
| - |
| - if (listeners.isEmpty()) |
| - return; |
| - v8::V8::AddImplicitReferences(wrapper, listeners.data(), listeners.size()); |
| + v8::V8::AddImplicitReference(isolate, id, v8listener->existingListenerObjectPersistentHandle()); |
| + } |
| } |
| Node* V8GCController::opaqueRootForGC(Node* node, v8::Isolate*) |
| @@ -361,17 +226,17 @@ public: |
| // implementation can't tell the difference. |
| MessagePort* port = static_cast<MessagePort*>(object); |
| if (port->isEntangled() || port->hasPendingActivity()) |
| - m_grouper.keepAlive(wrapper); |
| + SetObjectGroupId(wrapper, *V8PerIsolateData::current()->ensureLiveRoot()); |
| } else if (V8MutationObserver::info.equals(type)) { |
| // FIXME: Allow opaqueRootForGC to operate on multiple roots and move this logic into V8MutationObserverCustom. |
| MutationObserver* observer = static_cast<MutationObserver*>(object); |
| HashSet<Node*> observedNodes = observer->getObservedNodes(); |
| for (HashSet<Node*>::iterator it = observedNodes.begin(); it != observedNodes.end(); ++it) |
| - m_grouper.addImplicitReference(V8GCController::opaqueRootForGC(*it, m_isolate), wrapper); |
| + v8::V8::AddImplicitReference(m_isolate, v8::UniqueId(reinterpret_cast<intptr_t>(V8GCController::opaqueRootForGC(*it, m_isolate))), wrapper); |
| } else { |
| ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(wrapper); |
| if (activeDOMObject && activeDOMObject->hasPendingActivity()) |
| - m_grouper.keepAlive(wrapper); |
| + SetObjectGroupId(wrapper, *V8PerIsolateData::current()->ensureLiveRoot()); |
| } |
| if (classId == v8DOMNodeClassId) { |
| @@ -382,24 +247,40 @@ public: |
| Node* node = static_cast<Node*>(object); |
| if (node->hasEventListeners()) |
| - addImplicitReferencesForNodeWithEventListeners(node, wrapper); |
| - |
| - m_grouper.addNodeWrapperToGroup(V8GCController::opaqueRootForGC(node, m_isolate), wrapper); |
| + addImplicitReferencesForNodeWithEventListeners(m_isolate, node, wrapper); |
| + Node* root = V8GCController::opaqueRootForGC(node, m_isolate); |
| + SetObjectGroupId(wrapper, root); |
| + MaybeAddRetainedObjectInfo(root); |
| } else if (classId == v8DOMObjectClassId) { |
| - m_grouper.addObjectWrapperToGroup(type->opaqueRootForGC(object, wrapper, m_isolate), wrapper); |
| + void* root = type->opaqueRootForGC(object, wrapper, m_isolate); |
| + SetObjectGroupId(wrapper, root); |
| } else { |
| ASSERT_NOT_REACHED(); |
| } |
| } |
| - void notifyFinished() |
| + void MaybeAddRetainedObjectInfo(Node* root) |
|
abarth-chromium
2013/04/12 17:23:44
MaybeAddRetainedObjectInfo -> maybeAddRetainedObje
|
| + { |
| + if (root && !groups_with_retained_info_.contains(root)) { |
| + v8::V8::SetRetainedObjectInfo(m_isolate, v8::UniqueId(reinterpret_cast<intptr_t>(root)), new RetainedDOMInfo(root)); |
| + groups_with_retained_info_.add(root); |
| + } |
| + } |
| + |
| + void SetObjectGroupId(const v8::Persistent<v8::Object>& object, void* root) |
|
abarth-chromium
2013/04/12 17:23:44
SetObjectGroupId -> setObjectGroupId
|
| { |
| - m_grouper.apply(); |
| + v8::UniqueId id(reinterpret_cast<intptr_t>(root)); |
| + v8::V8::SetObjectGroupId(m_isolate, object, id); |
| + if (!groups_with_representative_objects_.contains(root)) { |
| + v8::V8::SetObjectGroupRepresentativeObject(m_isolate, id, object); |
| + groups_with_representative_objects_.add(root); |
| + } |
| } |
| private: |
| - WrapperGrouper m_grouper; |
| v8::Isolate* m_isolate; |
| + HashSet<Node*> groups_with_retained_info_; |
|
abarth-chromium
2013/04/12 17:23:44
m_groupsWithRetainedInfo
|
| + HashSet<void*> groups_with_representative_objects_; |
|
abarth-chromium
2013/04/12 17:23:44
m_groupsWithRepresentiveObjects
|
| }; |
| void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags) |
| @@ -436,7 +317,6 @@ void V8GCController::majorGCPrologue() |
| MajorGCWrapperVisitor visitor(isolate); |
| v8::V8::VisitHandlesWithClassIds(&visitor); |
| - visitor.notifyFinished(); |
| V8PerIsolateData::from(isolate)->stringCache()->clearOnGC(); |
| } |