Title: [141999] trunk/Source/WebCore
Revision
141999
Author
commit-qu...@webkit.org
Date
2013-02-06 07:50:56 -0800 (Wed, 06 Feb 2013)

Log Message

Unreviewed, rolling out r141983.
http://trac.webkit.org/changeset/141983
https://bugs.webkit.org/show_bug.cgi?id=109055

lots of new crashes in handlescope (Requested by gavinp on
#webkit).

Patch by Sheriff Bot <webkit.review....@gmail.com> on 2013-02-06

* bindings/v8/DOMDataStore.h:
(WebCore::DOMDataStore::setWrapperInObject):
* bindings/v8/DOMWrapperWorld.h:
(DOMWrapperWorld):
(WebCore::DOMWrapperWorld::isolated):
* bindings/v8/V8Binding.h:
(WebCore):
(WebCore::worldForEnteredContextIfIsolated):
* bindings/v8/V8DOMWindowShell.cpp:
(WebCore::V8DOMWindowShell::initializeIfNeeded):
* bindings/v8/V8GCController.cpp:
(WebCore::WrapperVisitor::WrapperVisitor):
(WebCore):
(WebCore::gcTree):
(WebCore::V8GCController::didCreateWrapperForNode):
(WebCore::V8GCController::gcPrologue):
(WebCore::V8GCController::minorGCPrologue):
(WebCore::V8GCController::majorGCPrologue):
* bindings/v8/V8GCController.h:
(V8GCController):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (141998 => 141999)


--- trunk/Source/WebCore/ChangeLog	2013-02-06 14:43:55 UTC (rev 141998)
+++ trunk/Source/WebCore/ChangeLog	2013-02-06 15:50:56 UTC (rev 141999)
@@ -1,3 +1,33 @@
+2013-02-06  Sheriff Bot  <webkit.review....@gmail.com>
+
+        Unreviewed, rolling out r141983.
+        http://trac.webkit.org/changeset/141983
+        https://bugs.webkit.org/show_bug.cgi?id=109055
+
+        lots of new crashes in handlescope (Requested by gavinp on
+        #webkit).
+
+        * bindings/v8/DOMDataStore.h:
+        (WebCore::DOMDataStore::setWrapperInObject):
+        * bindings/v8/DOMWrapperWorld.h:
+        (DOMWrapperWorld):
+        (WebCore::DOMWrapperWorld::isolated):
+        * bindings/v8/V8Binding.h:
+        (WebCore):
+        (WebCore::worldForEnteredContextIfIsolated):
+        * bindings/v8/V8DOMWindowShell.cpp:
+        (WebCore::V8DOMWindowShell::initializeIfNeeded):
+        * bindings/v8/V8GCController.cpp:
+        (WebCore::WrapperVisitor::WrapperVisitor):
+        (WebCore):
+        (WebCore::gcTree):
+        (WebCore::V8GCController::didCreateWrapperForNode):
+        (WebCore::V8GCController::gcPrologue):
+        (WebCore::V8GCController::minorGCPrologue):
+        (WebCore::V8GCController::majorGCPrologue):
+        * bindings/v8/V8GCController.h:
+        (V8GCController):
+
 2013-02-06  Andreas Kling  <akl...@apple.com>
 
         Optimize GlyphPage for case where all glyphs are available in the same font.

Modified: trunk/Source/WebCore/bindings/v8/DOMDataStore.h (141998 => 141999)


--- trunk/Source/WebCore/bindings/v8/DOMDataStore.h	2013-02-06 14:43:55 UTC (rev 141998)
+++ trunk/Source/WebCore/bindings/v8/DOMDataStore.h	2013-02-06 15:50:56 UTC (rev 141999)
@@ -164,6 +164,13 @@
         object->setWrapper(wrapper);
         wrapper.MakeWeak(isolate, object, weakCallback);
     }
+    static void setWrapperInObject(Node* object, v8::Persistent<v8::Object> wrapper, v8::Isolate* isolate)
+    {
+        ASSERT(object->wrapper().IsEmpty());
+        object->setWrapper(wrapper);
+        V8GCController::didCreateWrapperForNode(object);
+        wrapper.MakeWeak(isolate, static_cast<ScriptWrappable*>(object), weakCallback);
+    }
 
     static void weakCallback(v8::Isolate*, v8::Persistent<v8::Value>, void* context);
 

Modified: trunk/Source/WebCore/bindings/v8/DOMWrapperWorld.h (141998 => 141999)


--- trunk/Source/WebCore/bindings/v8/DOMWrapperWorld.h	2013-02-06 14:43:55 UTC (rev 141998)
+++ trunk/Source/WebCore/bindings/v8/DOMWrapperWorld.h	2013-02-06 15:50:56 UTC (rev 141999)
@@ -63,7 +63,6 @@
 #ifndef NDEBUG
     static void assertContextHasCorrectPrototype(v8::Handle<v8::Context>);
 #endif
-    // FIXME: Rename this method to getWorld().
     static DOMWrapperWorld* isolated(v8::Handle<v8::Context> context)
     {
 #ifndef NDEBUG
@@ -71,10 +70,6 @@
 #endif
         return static_cast<DOMWrapperWorld*>(context->GetAlignedPointerFromEmbedderData(v8ContextIsolatedWorld));
     }
-    static DOMWrapperWorld* getWorldWithoutContextCheck(v8::Handle<v8::Context> context)
-    {
-        return static_cast<DOMWrapperWorld*>(context->GetAlignedPointerFromEmbedderData(v8ContextIsolatedWorld));
-    }
 
     // Associates an isolated world (see above for description) with a security
     // origin. XMLHttpRequest instances used in that world will be considered

Modified: trunk/Source/WebCore/bindings/v8/V8Binding.h (141998 => 141999)


--- trunk/Source/WebCore/bindings/v8/V8Binding.h	2013-02-06 14:43:55 UTC (rev 141998)
+++ trunk/Source/WebCore/bindings/v8/V8Binding.h	2013-02-06 15:50:56 UTC (rev 141999)
@@ -437,31 +437,13 @@
     // a context, if the window is currently being displayed in the Frame.
     Frame* toFrameIfNotDetached(v8::Handle<v8::Context>);
 
-    // FIXME: Rename this method to worldForEnteredContext().
     inline DOMWrapperWorld* worldForEnteredContextIfIsolated()
     {
-        v8::Handle<v8::Context> context = v8::Context::GetEntered();
-        if (context.IsEmpty())
+        if (!v8::Context::InContext())
             return 0;
-        return DOMWrapperWorld::isolated(context);
+        return DOMWrapperWorld::isolated(v8::Context::GetEntered());
     }
 
-    // This is a slightly different version of worldForEnteredContext().
-    // The difference is just that worldForEnteredContextWithoutContextCheck()
-    // does not call assertContextHasCorrectPrototype() (which is enabled on
-    // Debug builds only). Because assertContextHasCorrectPrototype() crashes
-    // if it is called when a current context is not completely initialized,
-    // you have to use worldForEnteredContextWithoutContextCheck() if you need
-    // to get a DOMWrapperWorld while a current context is being initialized.
-    // See https://bugs.webkit.org/show_bug.cgi?id=108579#c15 for more details.
-    inline DOMWrapperWorld* worldForEnteredContextWithoutContextCheck()
-    {
-        v8::Handle<v8::Context> context = v8::Context::GetEntered();
-        if (context.IsEmpty())
-            return 0;
-        return DOMWrapperWorld::getWorldWithoutContextCheck(context);
-    }
-
     // If the current context causes out of memory, _javascript_ setting
     // is disabled and it returns true.
     bool handleOutOfMemory();

Modified: trunk/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp (141998 => 141999)


--- trunk/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp	2013-02-06 14:43:55 UTC (rev 141998)
+++ trunk/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp	2013-02-06 15:50:56 UTC (rev 141999)
@@ -208,13 +208,13 @@
     if (m_context.isEmpty())
         return false;
 
-    m_world->setIsolatedWorldField(m_context.get());
-
     bool isMainWorld = m_world->isMainWorld();
 
     v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context.get());
     v8::Context::Scope contextScope(context);
 
+    m_world->setIsolatedWorldField(m_context.get());
+
     if (m_global.isEmpty()) {
         m_global.set(context->Global());
         if (m_global.isEmpty()) {

Modified: trunk/Source/WebCore/bindings/v8/V8GCController.cpp (141998 => 141999)


--- trunk/Source/WebCore/bindings/v8/V8GCController.cpp	2013-02-06 14:43:55 UTC (rev 141998)
+++ trunk/Source/WebCore/bindings/v8/V8GCController.cpp	2013-02-06 15:50:56 UTC (rev 141999)
@@ -178,116 +178,18 @@
     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 {
+class WrapperVisitor : public v8::PersistentHandleVisitor {
 public:
-    explicit MinorGCWrapperVisitor(v8::Isolate* isolate)
+    explicit WrapperVisitor(v8::Isolate* isolate)
         : m_isolate(isolate)
     {
-        UNUSED_PARAM(m_isolate);
     }
 
     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, m_isolate));
-        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;
-    v8::Isolate* m_isolate;
-};
-
-class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor {
-public:
-    explicit MajorGCWrapperVisitor(v8::Isolate* isolate)
-        : m_isolate(isolate)
-    {
-    }
-
-    virtual void VisitPersistentHandle(v8::Persistent<v8::Value> value, uint16_t classId) OVERRIDE
-    {
-        ASSERT(value->IsObject());
-        v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value);
-
         if (classId != v8DOMNodeClassId && classId != v8DOMObjectClassId)
             return;
 
@@ -346,28 +248,105 @@
     v8::Isolate* m_isolate;
 };
 
+// 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::Isolate* isolate = v8::Isolate::GetCurrent();
-
-    // A minor GC can handle the main world only.
-    DOMWrapperWorld* world = worldForEnteredContextWithoutContextCheck();
-    if (world && world->isMainWorld()) {
-        v8::HandleScope scope;
-
-        MinorGCWrapperVisitor visitor(isolate);
-        v8::V8::VisitHandlesForPartialDependence(isolate, &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));
+        }
     }
 }
 
@@ -379,7 +358,7 @@
     v8::Isolate* isolate = v8::Isolate::GetCurrent();
     v8::HandleScope scope;
 
-    MajorGCWrapperVisitor visitor(isolate);
+    WrapperVisitor visitor(isolate);
     v8::V8::VisitHandlesWithClassIds(&visitor);
     visitor.notifyFinished();
 

Modified: trunk/Source/WebCore/bindings/v8/V8GCController.h (141998 => 141999)


--- trunk/Source/WebCore/bindings/v8/V8GCController.h	2013-02-06 14:43:55 UTC (rev 141998)
+++ trunk/Source/WebCore/bindings/v8/V8GCController.h	2013-02-06 15:50:56 UTC (rev 141999)
@@ -52,6 +52,7 @@
     static void collectGarbage();
 
     static Node* opaqueRootForGC(Node*, v8::Isolate*);
+    static void didCreateWrapperForNode(Node*);
 
 private:
     static Vector<Node*>* m_edenNodes;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to