Unreviewed, rolling out r141548.
authorharaken@chromium.org <haraken@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 1 Feb 2013 11:49:35 +0000 (11:49 +0000)
committerharaken@chromium.org <haraken@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 1 Feb 2013 11:49:35 +0000 (11:49 +0000)
http://trac.webkit.org/changeset/141548
https://bugs.webkit.org/show_bug.cgi?id=108579

userscript-plugin-document.html is flaky

* bindings/v8/DOMDataStore.h:
(WebCore::DOMDataStore::setWrapperInObject):
* bindings/v8/V8GCController.cpp:
(WebCore):
(WebCore::gcTree):
(WebCore::V8GCController::didCreateWrapperForNode):
(WebCore::V8GCController::gcPrologue):
(WebCore::V8GCController::minorGCPrologue):
(WebCore::V8GCController::majorGCPrologue):
* bindings/v8/V8GCController.h:
(V8GCController):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@141577 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/bindings/v8/DOMDataStore.h
Source/WebCore/bindings/v8/V8GCController.cpp
Source/WebCore/bindings/v8/V8GCController.h

index 307f287..1e879cd 100644 (file)
@@ -1,3 +1,23 @@
+2013-02-01  Kentaro Hara  <haraken@chromium.org>
+
+        Unreviewed, rolling out r141548.
+        http://trac.webkit.org/changeset/141548
+        https://bugs.webkit.org/show_bug.cgi?id=108579
+
+        userscript-plugin-document.html is flaky
+
+        * bindings/v8/DOMDataStore.h:
+        (WebCore::DOMDataStore::setWrapperInObject):
+        * bindings/v8/V8GCController.cpp:
+        (WebCore):
+        (WebCore::gcTree):
+        (WebCore::V8GCController::didCreateWrapperForNode):
+        (WebCore::V8GCController::gcPrologue):
+        (WebCore::V8GCController::minorGCPrologue):
+        (WebCore::V8GCController::majorGCPrologue):
+        * bindings/v8/V8GCController.h:
+        (V8GCController):
+
 2013-02-01  Andrey Adaikin  <aandrey@chromium.org>
 
         Web Inspector: fix jscompiler warnings
index abc20c6..416e450 100644 (file)
@@ -164,6 +164,13 @@ private:
         object->setWrapper(wrapper);
         wrapper.MakeWeak(object, weakCallback);
     }
+    static void setWrapperInObject(Node* object, v8::Persistent<v8::Object> wrapper)
+    {
+        ASSERT(object->wrapper().IsEmpty());
+        object->setWrapper(wrapper);
+        V8GCController::didCreateWrapperForNode(object);
+        wrapper.MakeWeak(static_cast<ScriptWrappable*>(object), weakCallback);
+    }
 
     static void weakCallback(v8::Persistent<v8::Value>, void* context);
 
index 9e1c13a..c8eae5e 100644 (file)
@@ -178,98 +178,7 @@ Node* V8GCController::opaqueRootForGC(Node* node)
     return node;
 }
 
-static void gcTree(Node* startNode)
-{
-    Vector<v8::Persistent<v8::Value>, initialNodeVectorSize> newSpaceWrappers;
-
-    // We traverse a DOM tree in the DFS order starting from startNode.
-    // The traversal order does not matter for correctness but does matter for performance.
-    Node* node = startNode;
-    // 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.
-    do {
-        ASSERT(node);
-        if (!node->wrapper().IsEmpty()) {
-            // FIXME: Remove the special handling for image elements.
-            // The same special handling is in V8GCController::opaqueRootForGC().
-            // Maybe should image elements be active DOM nodes?
-            // See https://code.google.com/p/chromium/issues/detail?id=164882
-            if (!node->isV8CollectableDuringMinorGC() || (node->hasTagName(HTMLNames::imgTag) && static_cast<HTMLImageElement*>(node)->hasPendingActivity())) {
-                // 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;
-            }
-            node->setV8CollectableDuringMinorGC(false);
-            newSpaceWrappers.append(node->wrapper());
-        }
-        if (node->firstChild()) {
-            node = node->firstChild();
-            continue;
-        }
-        while (!node->nextSibling()) {
-            if (!node->parentNode())
-                break;
-            node = node->parentNode();
-        }
-        if (node->parentNode())
-            node = node->nextSibling();
-    } while (node != startNode);
-
-    // We completed the DOM tree traversal. All wrappers in the DOM tree are
-    // stored in newSpaceWrappers and are expected to exist in the new space of V8.
-    // We report those wrappers to V8 as an object group.
-    for (size_t i = 0; i < newSpaceWrappers.size(); i++)
-        newSpaceWrappers[i].MarkPartiallyDependent();
-    if (newSpaceWrappers.size() > 0)
-        v8::V8::AddObjectGroup(&newSpaceWrappers[0], newSpaceWrappers.size());
-}
-
-// Regarding a minor GC algorithm for DOM nodes, see this document:
-// https://docs.google.com/a/google.com/presentation/d/1uifwVYGNYTZDoGLyCb7sXa7g49mWNMW2gaWvMN5NLk8/edit#slide=id.p
-class MinorGCWrapperVisitor : public v8::PersistentHandleVisitor {
-public:
-    virtual void VisitPersistentHandle(v8::Persistent<v8::Value> value, uint16_t classId) OVERRIDE
-    {
-        // A minor DOM GC can collect only Nodes.
-        if (classId != v8DOMNodeClassId)
-            return;
-
-        // To make minor GC cycle time bounded, we limit the number of wrappers handled
-        // by each minor GC cycle to 10000. This value was selected so that the minor
-        // GC cycle time is bounded to 20 ms in a case where the new space size
-        // is 16 MB and it is full of wrappers (which is almost the worst case).
-        // Practically speaking, as far as I crawled real web applications,
-        // the number of wrappers handled by each minor GC cycle is at most 3000.
-        // So this limit is mainly for pathological micro benchmarks.
-        const unsigned wrappersHandledByEachMinorGC = 10000;
-        if (m_nodesInNewSpace.size() >= wrappersHandledByEachMinorGC)
-            return;
-
-        ASSERT(value->IsObject());
-        v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value);
-        ASSERT(V8DOMWrapper::maybeDOMWrapper(value));
-        ASSERT(V8Node::HasInstance(wrapper));
-        Node* node = V8Node::toNative(wrapper);
-        m_nodesInNewSpace.append(node);
-        node->setV8CollectableDuringMinorGC(true);
-    }
-
-    void notifyFinished()
-    {
-        for (size_t i = 0; i < m_nodesInNewSpace.size(); i++) {
-            ASSERT(!m_nodesInNewSpace[i]->wrapper().IsEmpty());
-            if (m_nodesInNewSpace[i]->isV8CollectableDuringMinorGC()) // This branch is just for performance.
-                gcTree(m_nodesInNewSpace[i]);
-        }
-    }
-
-private:
-    Vector<Node*> m_nodesInNewSpace;
-};
-
-class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor {
+class WrapperVisitor : public v8::PersistentHandleVisitor {
 public:
     virtual void VisitPersistentHandle(v8::Persistent<v8::Value> value, uint16_t classId) OVERRIDE
     {
@@ -332,23 +241,106 @@ private:
     WrapperGrouper m_grouper;
 };
 
+// Regarding a minor GC algorithm for DOM nodes, see this document:
+// https://docs.google.com/a/google.com/presentation/d/1uifwVYGNYTZDoGLyCb7sXa7g49mWNMW2gaWvMN5NLk8/edit#slide=id.p
+//
+// m_edenNodes stores nodes that have wrappers that have been created since the last minor/major GC.
+Vector<Node*>* V8GCController::m_edenNodes = 0;
+
+static void gcTree(Node* startNode)
+{
+    Vector<v8::Persistent<v8::Value>, initialNodeVectorSize> newSpaceWrappers;
+
+    // We traverse a DOM tree in the DFS order starting from startNode.
+    // The traversal order does not matter for correctness but does matter for performance.
+    Node* node = startNode;
+    // 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.
+    do {
+        ASSERT(node);
+        if (!node->wrapper().IsEmpty()) {
+            // FIXME: Remove the special handling for image elements.
+            // The same special handling is in V8GCController::opaqueRootForGC().
+            // Maybe should image elements be active DOM nodes?
+            // See https://code.google.com/p/chromium/issues/detail?id=164882
+            if (!node->isV8CollectableDuringMinorGC() || (node->hasTagName(HTMLNames::imgTag) && static_cast<HTMLImageElement*>(node)->hasPendingActivity())) {
+                // The fact that we encounter a node that is not in the Eden space
+                // implies that its wrapper might be in the old 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;
+            }
+            // A once traversed node is removed from the Eden space.
+            node->setV8CollectableDuringMinorGC(false);
+            newSpaceWrappers.append(node->wrapper());
+        }
+        if (node->firstChild()) {
+            node = node->firstChild();
+            continue;
+        }
+        while (!node->nextSibling()) {
+            if (!node->parentNode())
+                break;
+            node = node->parentNode();
+        }
+        if (node->parentNode())
+            node = node->nextSibling();
+    } while (node != startNode);
+
+    // We completed the DOM tree traversal. All wrappers in the DOM tree are
+    // stored in newSpaceWrappers and are expected to exist in the new space of V8.
+    // We report those wrappers to V8 as an object group.
+    for (size_t i = 0; i < newSpaceWrappers.size(); i++)
+        newSpaceWrappers[i].MarkPartiallyDependent();
+    if (newSpaceWrappers.size() > 0)
+        v8::V8::AddObjectGroup(&newSpaceWrappers[0], newSpaceWrappers.size());
+}
+
+void V8GCController::didCreateWrapperForNode(Node* node)
+{
+    // To make minor GC cycle time bounded, we limit the number of wrappers handled
+    // by each minor GC cycle to 10000. This value was selected so that the minor
+    // GC cycle time is bounded to 20 ms in a case where the new space size
+    // is 16 MB and it is full of wrappers (which is almost the worst case).
+    // Practically speaking, as far as I crawled real web applications,
+    // the number of wrappers handled by each minor GC cycle is at most 3000.
+    // So this limit is mainly for pathological micro benchmarks.
+    const unsigned wrappersHandledByEachMinorGC = 10000;
+    ASSERT(!node->wrapper().IsEmpty());
+    if (!m_edenNodes)
+        m_edenNodes = adoptPtr(new Vector<Node*>).leakPtr();
+    if (m_edenNodes->size() <= wrappersHandledByEachMinorGC) {
+        // A node of a newly created wrapper is put into the Eden space.
+        m_edenNodes->append(node);
+        node->setV8CollectableDuringMinorGC(true);
+    }
+}
+
 void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags)
 {
     if (type == v8::kGCTypeScavenge)
         minorGCPrologue();
     else if (type == v8::kGCTypeMarkSweepCompact)
         majorGCPrologue();
+
+    if (isMainThreadOrGCThread() && m_edenNodes) {
+        // The Eden space is cleared at every minor/major GC.
+        m_edenNodes->clear();
+    }
 }
 
 void V8GCController::minorGCPrologue()
 {
     TRACE_EVENT_BEGIN0("v8", "GC");
 
-    v8::HandleScope scope;
-
-    MinorGCWrapperVisitor visitor;
-    v8::V8::VisitHandlesForPartialDependence(v8::Isolate::GetCurrent(), &visitor);
-    visitor.notifyFinished();
+    if (isMainThreadOrGCThread() && m_edenNodes) {
+        for (size_t i = 0; i < m_edenNodes->size(); i++) {
+            ASSERT(!m_edenNodes->at(i)->wrapper().IsEmpty());
+            if (m_edenNodes->at(i)->isV8CollectableDuringMinorGC()) // This branch is just for performance.
+                gcTree(m_edenNodes->at(i));
+        }
+    }
 }
 
 // Create object groups for DOM tree nodes.
@@ -358,7 +350,7 @@ void V8GCController::majorGCPrologue()
 
     v8::HandleScope scope;
 
-    MajorGCWrapperVisitor visitor;
+    WrapperVisitor visitor;
     v8::V8::VisitHandlesWithClassIds(&visitor);
     visitor.notifyFinished();
 
index d767c96..def12c6 100644 (file)
@@ -52,6 +52,7 @@ public:
     static void collectGarbage();
 
     static Node* opaqueRootForGC(Node*);
+    static void didCreateWrapperForNode(Node*);
 
 private:
     static Vector<Node*>* m_edenNodes;