Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / core / v8 / V8GCController.cpp
index e2c0a2e..dbc27db 100644 (file)
@@ -73,7 +73,7 @@ static void addReferencesForNodeWithEventListeners(v8::Isolate* isolate, Node* n
     }
 }
 
-Node* V8GCController::opaqueRootForGC(Node* node, v8::Isolate*)
+Node* V8GCController::opaqueRootForGC(v8::Isolate*, Node* node)
 {
     ASSERT(node);
     // FIXME: Remove the special handling for image elements.
@@ -108,7 +108,7 @@ public:
         : m_isolate(isolate)
     { }
 
-    virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) OVERRIDE
+    virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override
     {
         // A minor DOM GC can collect only Nodes.
         if (classId != WrapperTypeInfo::NodeClassId)
@@ -175,37 +175,37 @@ private:
         // To make each minor GC time bounded, we might need to give up
         // traversing at some point for a large DOM tree. That being said,
         // I could not observe the need even in pathological test cases.
-        for (Node* node = rootNode; node; node = NodeTraversal::next(*node)) {
-            if (node->containsWrapper()) {
-                if (!node->isV8CollectableDuringMinorGC()) {
+        for (Node& node : NodeTraversal::startsAt(rootNode)) {
+            if (node.containsWrapper()) {
+                if (!node.isV8CollectableDuringMinorGC()) {
                     // This node is not in the new space of V8. This indicates that
                     // the minor GC cannot anyway judge reachability of this DOM tree.
                     // Thus we give up traversing the DOM tree.
                     return false;
                 }
-                node->clearV8CollectableDuringMinorGC();
-                partiallyDependentNodes->append(node);
+                node.clearV8CollectableDuringMinorGC();
+                partiallyDependentNodes->append(&node);
             }
-            if (ShadowRoot* shadowRoot = node->youngestShadowRoot()) {
+            if (ShadowRoot* shadowRoot = node.youngestShadowRoot()) {
                 if (!traverseTree(shadowRoot, partiallyDependentNodes))
                     return false;
-            } else if (node->isShadowRoot()) {
-                if (ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowRoot()) {
+            } else if (node.isShadowRoot()) {
+                if (ShadowRoot* shadowRoot = toShadowRoot(node).olderShadowRoot()) {
                     if (!traverseTree(shadowRoot, partiallyDependentNodes))
                         return false;
                 }
             }
             // <template> has a |content| property holding a DOM fragment which we must traverse,
             // just like we do for the shadow trees above.
-            if (isHTMLTemplateElement(*node)) {
-                if (!traverseTree(toHTMLTemplateElement(*node).content(), partiallyDependentNodes))
+            if (isHTMLTemplateElement(node)) {
+                if (!traverseTree(toHTMLTemplateElement(node).content(), partiallyDependentNodes))
                     return false;
             }
 
             // Document maintains the list of imported documents through HTMLImportsController.
-            if (node->isDocumentNode()) {
-                Document* document = toDocument(node);
-                HTMLImportsController* controller = document->importsController();
+            if (node.isDocumentNode()) {
+                Document& document = toDocument(node);
+                HTMLImportsController* controller = document.importsController();
                 if (controller && document == controller->master()) {
                     for (unsigned i = 0; i < controller->loaderCount(); ++i) {
                         if (!traverseTree(controller->loaderDocumentAt(i), partiallyDependentNodes))
@@ -247,12 +247,13 @@ class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor {
 public:
     explicit MajorGCWrapperVisitor(v8::Isolate* isolate, bool constructRetainedObjectInfos)
         : m_isolate(isolate)
+        , m_domObjectsWithPendingActivity(0)
         , m_liveRootGroupIdSet(false)
         , m_constructRetainedObjectInfos(constructRetainedObjectInfos)
     {
     }
 
-    virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) OVERRIDE
+    virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override
     {
         if (classId != WrapperTypeInfo::NodeClassId && classId != WrapperTypeInfo::ObjectClassId)
             return;
@@ -269,20 +270,22 @@ public:
         const WrapperTypeInfo* type = toWrapperTypeInfo(*wrapper);
 
         ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(*wrapper);
-        if (activeDOMObject && activeDOMObject->hasPendingActivity())
+        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(node, m_isolate);
+            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(toScriptWrappableBase(*wrapper), v8::Persistent<v8::Object>::Cast(*value), m_isolate);
+            type->visitDOMWrapper(m_isolate, toScriptWrappableBase(*wrapper), v8::Persistent<v8::Object>::Cast(*value));
         } else {
             ASSERT_NOT_REACHED();
         }
@@ -302,6 +305,8 @@ public:
                 alreadyAdded = root;
             }
         }
+        if (m_liveRootGroupIdSet)
+            profiler->SetRetainedObjectInfo(liveRootId(), new ActiveDOMObjectsInfo(m_domObjectsWithPendingActivity));
     }
 
 private:
@@ -313,12 +318,14 @@ private:
         if (!m_liveRootGroupIdSet) {
             m_isolate->SetObjectGroupId(liveRoot, id);
             m_liveRootGroupIdSet = true;
+            ++m_domObjectsWithPendingActivity;
         }
         return id;
     }
 
     v8::Isolate* m_isolate;
     WillBePersistentHeapVector<RawPtrWillBeMember<Node> > m_groupsWhichNeedRetainerInfo;
+    int m_domObjectsWithPendingActivity;
     bool m_liveRootGroupIdSet;
     bool m_constructRetainedObjectInfos;
 };
@@ -338,7 +345,7 @@ void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags)
     if (type == v8::kGCTypeScavenge)
         minorGCPrologue(isolate);
     else if (type == v8::kGCTypeMarkSweepCompact)
-        majorGCPrologue(flags & v8::kGCCallbackFlagConstructRetainedObjectInfos, isolate);
+        majorGCPrologue(isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos);
 }
 
 void V8GCController::minorGCPrologue(v8::Isolate* isolate)
@@ -359,7 +366,7 @@ void V8GCController::minorGCPrologue(v8::Isolate* isolate)
 }
 
 // Create object groups for DOM tree nodes.
-void V8GCController::majorGCPrologue(bool constructRetainedObjectInfos, v8::Isolate* isolate)
+void V8GCController::majorGCPrologue(v8::Isolate* isolate, bool constructRetainedObjectInfos)
 {
     v8::HandleScope scope(isolate);
     TRACE_EVENT_BEGIN0("v8", "majorGC");
@@ -368,14 +375,14 @@ void V8GCController::majorGCPrologue(bool constructRetainedObjectInfos, v8::Isol
         {
             TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "DOMMajorGC");
             MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos);
-            v8::V8::VisitHandlesWithClassIds(&visitor);
+            v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
             visitor.notifyFinished();
         }
         V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE());
         TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8MajorGC");
     } else {
         MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos);
-        v8::V8::VisitHandlesWithClassIds(&visitor);
+        v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
         visitor.notifyFinished();
     }
 }
@@ -470,4 +477,35 @@ void V8GCController::reportDOMMemoryUsageToV8(v8::Isolate* isolate)
     lastUsageReportedToV8 = currentUsage;
 }
 
+class DOMWrapperTracer : public v8::PersistentHandleVisitor {
+public:
+    explicit DOMWrapperTracer(Visitor* visitor)
+        : m_visitor(visitor)
+    {
+    }
+
+    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 tracing.
+        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 (m_visitor)
+            toWrapperTypeInfo(*wrapper)->trace(m_visitor, toScriptWrappableBase(*wrapper));
+    }
+
+private:
+    Visitor* m_visitor;
+};
+
+void V8GCController::traceDOMWrappers(v8::Isolate* isolate, Visitor* visitor)
+{
+    DOMWrapperTracer tracer(visitor);
+    v8::V8::VisitHandlesWithClassIds(isolate, &tracer);
+}
+
 } // namespace blink