Changeset 141577 in webkit


Ignore:
Timestamp:
Feb 1, 2013 3:49:35 AM (11 years ago)
Author:
haraken@chromium.org
Message:

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):

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r141574 r141577  
     12013-02-01  Kentaro Hara  <haraken@chromium.org>
     2
     3        Unreviewed, rolling out r141548.
     4        http://trac.webkit.org/changeset/141548
     5        https://bugs.webkit.org/show_bug.cgi?id=108579
     6
     7        userscript-plugin-document.html is flaky
     8
     9        * bindings/v8/DOMDataStore.h:
     10        (WebCore::DOMDataStore::setWrapperInObject):
     11        * bindings/v8/V8GCController.cpp:
     12        (WebCore):
     13        (WebCore::gcTree):
     14        (WebCore::V8GCController::didCreateWrapperForNode):
     15        (WebCore::V8GCController::gcPrologue):
     16        (WebCore::V8GCController::minorGCPrologue):
     17        (WebCore::V8GCController::majorGCPrologue):
     18        * bindings/v8/V8GCController.h:
     19        (V8GCController):
     20
    1212013-02-01  Andrey Adaikin  <aandrey@chromium.org>
    222
  • trunk/Source/WebCore/bindings/v8/DOMDataStore.h

    r141548 r141577  
    165165        wrapper.MakeWeak(object, weakCallback);
    166166    }
     167    static void setWrapperInObject(Node* object, v8::Persistent<v8::Object> wrapper)
     168    {
     169        ASSERT(object->wrapper().IsEmpty());
     170        object->setWrapper(wrapper);
     171        V8GCController::didCreateWrapperForNode(object);
     172        wrapper.MakeWeak(static_cast<ScriptWrappable*>(object), weakCallback);
     173    }
    167174
    168175    static void weakCallback(v8::Persistent<v8::Value>, void* context);
  • trunk/Source/WebCore/bindings/v8/V8GCController.cpp

    r141548 r141577  
    179179}
    180180
    181 static void gcTree(Node* startNode)
    182 {
    183     Vector<v8::Persistent<v8::Value>, initialNodeVectorSize> newSpaceWrappers;
    184 
    185     // We traverse a DOM tree in the DFS order starting from startNode.
    186     // The traversal order does not matter for correctness but does matter for performance.
    187     Node* node = startNode;
    188     // To make each minor GC time bounded, we might need to give up
    189     // traversing at some point for a large DOM tree. That being said,
    190     // I could not observe the need even in pathological test cases.
    191     do {
    192         ASSERT(node);
    193         if (!node->wrapper().IsEmpty()) {
    194             // FIXME: Remove the special handling for image elements.
    195             // The same special handling is in V8GCController::opaqueRootForGC().
    196             // Maybe should image elements be active DOM nodes?
    197             // See https://code.google.com/p/chromium/issues/detail?id=164882
    198             if (!node->isV8CollectableDuringMinorGC() || (node->hasTagName(HTMLNames::imgTag) && static_cast<HTMLImageElement*>(node)->hasPendingActivity())) {
    199                 // This node is not in the new space of V8. This indicates that
    200                 // the minor GC cannot anyway judge reachability of this DOM tree.
    201                 // Thus we give up traversing the DOM tree.
    202                 return;
    203             }
    204             node->setV8CollectableDuringMinorGC(false);
    205             newSpaceWrappers.append(node->wrapper());
    206         }
    207         if (node->firstChild()) {
    208             node = node->firstChild();
    209             continue;
    210         }
    211         while (!node->nextSibling()) {
    212             if (!node->parentNode())
    213                 break;
    214             node = node->parentNode();
    215         }
    216         if (node->parentNode())
    217             node = node->nextSibling();
    218     } while (node != startNode);
    219 
    220     // We completed the DOM tree traversal. All wrappers in the DOM tree are
    221     // stored in newSpaceWrappers and are expected to exist in the new space of V8.
    222     // We report those wrappers to V8 as an object group.
    223     for (size_t i = 0; i < newSpaceWrappers.size(); i++)
    224         newSpaceWrappers[i].MarkPartiallyDependent();
    225     if (newSpaceWrappers.size() > 0)
    226         v8::V8::AddObjectGroup(&newSpaceWrappers[0], newSpaceWrappers.size());
    227 }
    228 
    229 // Regarding a minor GC algorithm for DOM nodes, see this document:
    230 // https://docs.google.com/a/google.com/presentation/d/1uifwVYGNYTZDoGLyCb7sXa7g49mWNMW2gaWvMN5NLk8/edit#slide=id.p
    231 class MinorGCWrapperVisitor : public v8::PersistentHandleVisitor {
    232 public:
    233     virtual void VisitPersistentHandle(v8::Persistent<v8::Value> value, uint16_t classId) OVERRIDE
    234     {
    235         // A minor DOM GC can collect only Nodes.
    236         if (classId != v8DOMNodeClassId)
    237             return;
    238 
    239         // To make minor GC cycle time bounded, we limit the number of wrappers handled
    240         // by each minor GC cycle to 10000. This value was selected so that the minor
    241         // GC cycle time is bounded to 20 ms in a case where the new space size
    242         // is 16 MB and it is full of wrappers (which is almost the worst case).
    243         // Practically speaking, as far as I crawled real web applications,
    244         // the number of wrappers handled by each minor GC cycle is at most 3000.
    245         // So this limit is mainly for pathological micro benchmarks.
    246         const unsigned wrappersHandledByEachMinorGC = 10000;
    247         if (m_nodesInNewSpace.size() >= wrappersHandledByEachMinorGC)
    248             return;
    249 
    250         ASSERT(value->IsObject());
    251         v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value);
    252         ASSERT(V8DOMWrapper::maybeDOMWrapper(value));
    253         ASSERT(V8Node::HasInstance(wrapper));
    254         Node* node = V8Node::toNative(wrapper);
    255         m_nodesInNewSpace.append(node);
    256         node->setV8CollectableDuringMinorGC(true);
    257     }
    258 
    259     void notifyFinished()
    260     {
    261         for (size_t i = 0; i < m_nodesInNewSpace.size(); i++) {
    262             ASSERT(!m_nodesInNewSpace[i]->wrapper().IsEmpty());
    263             if (m_nodesInNewSpace[i]->isV8CollectableDuringMinorGC()) // This branch is just for performance.
    264                 gcTree(m_nodesInNewSpace[i]);
    265         }
    266     }
    267 
    268 private:
    269     Vector<Node*> m_nodesInNewSpace;
    270 };
    271 
    272 class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor {
     181class WrapperVisitor : public v8::PersistentHandleVisitor {
    273182public:
    274183    virtual void VisitPersistentHandle(v8::Persistent<v8::Value> value, uint16_t classId) OVERRIDE
     
    333242};
    334243
     244// Regarding a minor GC algorithm for DOM nodes, see this document:
     245// https://docs.google.com/a/google.com/presentation/d/1uifwVYGNYTZDoGLyCb7sXa7g49mWNMW2gaWvMN5NLk8/edit#slide=id.p
     246//
     247// m_edenNodes stores nodes that have wrappers that have been created since the last minor/major GC.
     248Vector<Node*>* V8GCController::m_edenNodes = 0;
     249
     250static void gcTree(Node* startNode)
     251{
     252    Vector<v8::Persistent<v8::Value>, initialNodeVectorSize> newSpaceWrappers;
     253
     254    // We traverse a DOM tree in the DFS order starting from startNode.
     255    // The traversal order does not matter for correctness but does matter for performance.
     256    Node* node = startNode;
     257    // To make each minor GC time bounded, we might need to give up
     258    // traversing at some point for a large DOM tree. That being said,
     259    // I could not observe the need even in pathological test cases.
     260    do {
     261        ASSERT(node);
     262        if (!node->wrapper().IsEmpty()) {
     263            // FIXME: Remove the special handling for image elements.
     264            // The same special handling is in V8GCController::opaqueRootForGC().
     265            // Maybe should image elements be active DOM nodes?
     266            // See https://code.google.com/p/chromium/issues/detail?id=164882
     267            if (!node->isV8CollectableDuringMinorGC() || (node->hasTagName(HTMLNames::imgTag) && static_cast<HTMLImageElement*>(node)->hasPendingActivity())) {
     268                // The fact that we encounter a node that is not in the Eden space
     269                // implies that its wrapper might be in the old space of V8.
     270                // This indicates that the minor GC cannot anyway judge reachability
     271                // of this DOM tree. Thus we give up traversing the DOM tree.
     272                return;
     273            }
     274            // A once traversed node is removed from the Eden space.
     275            node->setV8CollectableDuringMinorGC(false);
     276            newSpaceWrappers.append(node->wrapper());
     277        }
     278        if (node->firstChild()) {
     279            node = node->firstChild();
     280            continue;
     281        }
     282        while (!node->nextSibling()) {
     283            if (!node->parentNode())
     284                break;
     285            node = node->parentNode();
     286        }
     287        if (node->parentNode())
     288            node = node->nextSibling();
     289    } while (node != startNode);
     290
     291    // We completed the DOM tree traversal. All wrappers in the DOM tree are
     292    // stored in newSpaceWrappers and are expected to exist in the new space of V8.
     293    // We report those wrappers to V8 as an object group.
     294    for (size_t i = 0; i < newSpaceWrappers.size(); i++)
     295        newSpaceWrappers[i].MarkPartiallyDependent();
     296    if (newSpaceWrappers.size() > 0)
     297        v8::V8::AddObjectGroup(&newSpaceWrappers[0], newSpaceWrappers.size());
     298}
     299
     300void V8GCController::didCreateWrapperForNode(Node* node)
     301{
     302    // To make minor GC cycle time bounded, we limit the number of wrappers handled
     303    // by each minor GC cycle to 10000. This value was selected so that the minor
     304    // GC cycle time is bounded to 20 ms in a case where the new space size
     305    // is 16 MB and it is full of wrappers (which is almost the worst case).
     306    // Practically speaking, as far as I crawled real web applications,
     307    // the number of wrappers handled by each minor GC cycle is at most 3000.
     308    // So this limit is mainly for pathological micro benchmarks.
     309    const unsigned wrappersHandledByEachMinorGC = 10000;
     310    ASSERT(!node->wrapper().IsEmpty());
     311    if (!m_edenNodes)
     312        m_edenNodes = adoptPtr(new Vector<Node*>).leakPtr();
     313    if (m_edenNodes->size() <= wrappersHandledByEachMinorGC) {
     314        // A node of a newly created wrapper is put into the Eden space.
     315        m_edenNodes->append(node);
     316        node->setV8CollectableDuringMinorGC(true);
     317    }
     318}
     319
    335320void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags)
    336321{
     
    339324    else if (type == v8::kGCTypeMarkSweepCompact)
    340325        majorGCPrologue();
     326
     327    if (isMainThreadOrGCThread() && m_edenNodes) {
     328        // The Eden space is cleared at every minor/major GC.
     329        m_edenNodes->clear();
     330    }
    341331}
    342332
     
    345335    TRACE_EVENT_BEGIN0("v8", "GC");
    346336
    347     v8::HandleScope scope;
    348 
    349     MinorGCWrapperVisitor visitor;
    350     v8::V8::VisitHandlesForPartialDependence(v8::Isolate::GetCurrent(), &visitor);
    351     visitor.notifyFinished();
     337    if (isMainThreadOrGCThread() && m_edenNodes) {
     338        for (size_t i = 0; i < m_edenNodes->size(); i++) {
     339            ASSERT(!m_edenNodes->at(i)->wrapper().IsEmpty());
     340            if (m_edenNodes->at(i)->isV8CollectableDuringMinorGC()) // This branch is just for performance.
     341                gcTree(m_edenNodes->at(i));
     342        }
     343    }
    352344}
    353345
     
    359351    v8::HandleScope scope;
    360352
    361     MajorGCWrapperVisitor visitor;
     353    WrapperVisitor visitor;
    362354    v8::V8::VisitHandlesWithClassIds(&visitor);
    363355    visitor.notifyFinished();
  • trunk/Source/WebCore/bindings/v8/V8GCController.h

    r141548 r141577  
    5353
    5454    static Node* opaqueRootForGC(Node*);
     55    static void didCreateWrapperForNode(Node*);
    5556
    5657private:
Note: See TracChangeset for help on using the changeset viewer.