Changeset 142103 in webkit


Ignore:
Timestamp:
Feb 7, 2013 5:37:24 AM (11 years ago)
Author:
haraken@chromium.org
Message:

Unreviewed, rolling out r142077.
http://trac.webkit.org/changeset/142077
https://bugs.webkit.org/show_bug.cgi?id=108579

fast/filesystem/workers/file-writer-empty-blob.html is broken

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

Location:
trunk/Source/WebCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r142099 r142103  
     12013-02-07  Kentaro Hara  <haraken@chromium.org>
     2
     3        Unreviewed, rolling out r142077.
     4        http://trac.webkit.org/changeset/142077
     5        https://bugs.webkit.org/show_bug.cgi?id=108579
     6
     7        fast/filesystem/workers/file-writer-empty-blob.html is broken
     8
     9        * bindings/v8/DOMDataStore.h:
     10        (WebCore::DOMDataStore::setWrapperInObject):
     11        * bindings/v8/DOMWrapperWorld.h:
     12        (DOMWrapperWorld):
     13        (WebCore::DOMWrapperWorld::isolated):
     14        * bindings/v8/V8Binding.h:
     15        (WebCore):
     16        (WebCore::worldForEnteredContextIfIsolated):
     17        * bindings/v8/V8DOMWindowShell.cpp:
     18        (WebCore::V8DOMWindowShell::initializeIfNeeded):
     19        * bindings/v8/V8GCController.cpp:
     20        (WebCore::WrapperVisitor::WrapperVisitor):
     21        (WebCore):
     22        (WebCore::gcTree):
     23        (WebCore::V8GCController::didCreateWrapperForNode):
     24        (WebCore::V8GCController::gcPrologue):
     25        (WebCore::V8GCController::minorGCPrologue):
     26        (WebCore::V8GCController::majorGCPrologue):
     27        * bindings/v8/V8GCController.h:
     28        (V8GCController):
     29
    1302013-02-07  Tony Gentilcore  <tonyg@chromium.org>
    231
  • trunk/Source/WebCore/bindings/v8/DOMDataStore.h

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

    r142077 r142103  
    6464    static void assertContextHasCorrectPrototype(v8::Handle<v8::Context>);
    6565#endif
    66     // FIXME: Rename this method to getWorld().
    6766    static DOMWrapperWorld* isolated(v8::Handle<v8::Context> context)
    6867    {
     
    7069        assertContextHasCorrectPrototype(context);
    7170#endif
    72         return static_cast<DOMWrapperWorld*>(context->GetAlignedPointerFromEmbedderData(v8ContextIsolatedWorld));
    73     }
    74     static DOMWrapperWorld* getWorldWithoutContextCheck(v8::Handle<v8::Context> context)
    75     {
    7671        return static_cast<DOMWrapperWorld*>(context->GetAlignedPointerFromEmbedderData(v8ContextIsolatedWorld));
    7772    }
  • trunk/Source/WebCore/bindings/v8/V8Binding.h

    r142077 r142103  
    438438    Frame* toFrameIfNotDetached(v8::Handle<v8::Context>);
    439439
    440     // FIXME: Rename this method to worldForEnteredContext().
    441440    inline DOMWrapperWorld* worldForEnteredContextIfIsolated()
    442441    {
    443         v8::Handle<v8::Context> context = v8::Context::GetEntered();
    444         if (context.IsEmpty())
     442        if (!v8::Context::InContext())
    445443            return 0;
    446         return DOMWrapperWorld::isolated(context);
    447     }
    448 
    449     // This is a slightly different version of worldForEnteredContext().
    450     // The difference is just that worldForEnteredContextWithoutContextCheck()
    451     // does not call assertContextHasCorrectPrototype() (which is enabled on
    452     // Debug builds only). Because assertContextHasCorrectPrototype() crashes
    453     // if it is called when a current context is not completely initialized,
    454     // you have to use worldForEnteredContextWithoutContextCheck() if you need
    455     // to get a DOMWrapperWorld while a current context is being initialized.
    456     // See https://bugs.webkit.org/show_bug.cgi?id=108579#c15 for more details.
    457     inline DOMWrapperWorld* worldForEnteredContextWithoutContextCheck()
    458     {
    459         v8::Handle<v8::Context> context = v8::Context::GetEntered();
    460         if (context.IsEmpty())
    461             return 0;
    462         return DOMWrapperWorld::getWorldWithoutContextCheck(context);
     444        return DOMWrapperWorld::isolated(v8::Context::GetEntered());
    463445    }
    464446
  • trunk/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp

    r142077 r142103  
    209209        return false;
    210210
    211     m_world->setIsolatedWorldField(m_context.get());
    212 
    213211    bool isMainWorld = m_world->isMainWorld();
    214212
    215213    v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context.get());
    216214    v8::Context::Scope contextScope(context);
     215
     216    m_world->setIsolatedWorldField(m_context.get());
    217217
    218218    if (m_global.isEmpty()) {
  • trunk/Source/WebCore/bindings/v8/V8GCController.cpp

    r142077 r142103  
    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 {
     181class WrapperVisitor : public v8::PersistentHandleVisitor {
    232182public:
    233     explicit MinorGCWrapperVisitor(v8::Isolate* isolate)
    234         : m_isolate(isolate)
    235     {
    236         UNUSED_PARAM(m_isolate);
    237     }
    238 
    239     virtual void VisitPersistentHandle(v8::Persistent<v8::Value> value, uint16_t classId) OVERRIDE
    240     {
    241         // A minor DOM GC can collect only Nodes.
    242         if (classId != v8DOMNodeClassId)
    243             return;
    244 
    245         // To make minor GC cycle time bounded, we limit the number of wrappers handled
    246         // by each minor GC cycle to 10000. This value was selected so that the minor
    247         // GC cycle time is bounded to 20 ms in a case where the new space size
    248         // is 16 MB and it is full of wrappers (which is almost the worst case).
    249         // Practically speaking, as far as I crawled real web applications,
    250         // the number of wrappers handled by each minor GC cycle is at most 3000.
    251         // So this limit is mainly for pathological micro benchmarks.
    252         const unsigned wrappersHandledByEachMinorGC = 10000;
    253         if (m_nodesInNewSpace.size() >= wrappersHandledByEachMinorGC)
    254             return;
    255 
    256         ASSERT(value->IsObject());
    257         v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value);
    258         ASSERT(V8DOMWrapper::maybeDOMWrapper(value));
    259         ASSERT(V8Node::HasInstance(wrapper, m_isolate));
    260         Node* node = V8Node::toNative(wrapper);
    261         m_nodesInNewSpace.append(node);
    262         node->setV8CollectableDuringMinorGC(true);
    263     }
    264 
    265     void notifyFinished()
    266     {
    267         for (size_t i = 0; i < m_nodesInNewSpace.size(); i++) {
    268             ASSERT(!m_nodesInNewSpace[i]->wrapper().IsEmpty());
    269             if (m_nodesInNewSpace[i]->isV8CollectableDuringMinorGC()) // This branch is just for performance.
    270                 gcTree(m_nodesInNewSpace[i]);
    271         }
    272     }
    273 
    274 private:
    275     Vector<Node*> m_nodesInNewSpace;
    276     v8::Isolate* m_isolate;
    277 };
    278 
    279 class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor {
    280 public:
    281     explicit MajorGCWrapperVisitor(v8::Isolate* isolate)
     183    explicit WrapperVisitor(v8::Isolate* isolate)
    282184        : m_isolate(isolate)
    283185    {
     
    347249};
    348250
     251// Regarding a minor GC algorithm for DOM nodes, see this document:
     252// https://docs.google.com/a/google.com/presentation/d/1uifwVYGNYTZDoGLyCb7sXa7g49mWNMW2gaWvMN5NLk8/edit#slide=id.p
     253//
     254// m_edenNodes stores nodes that have wrappers that have been created since the last minor/major GC.
     255Vector<Node*>* V8GCController::m_edenNodes = 0;
     256
     257static void gcTree(Node* startNode)
     258{
     259    Vector<v8::Persistent<v8::Value>, initialNodeVectorSize> newSpaceWrappers;
     260
     261    // We traverse a DOM tree in the DFS order starting from startNode.
     262    // The traversal order does not matter for correctness but does matter for performance.
     263    Node* node = startNode;
     264    // To make each minor GC time bounded, we might need to give up
     265    // traversing at some point for a large DOM tree. That being said,
     266    // I could not observe the need even in pathological test cases.
     267    do {
     268        ASSERT(node);
     269        if (!node->wrapper().IsEmpty()) {
     270            // FIXME: Remove the special handling for image elements.
     271            // The same special handling is in V8GCController::opaqueRootForGC().
     272            // Maybe should image elements be active DOM nodes?
     273            // See https://code.google.com/p/chromium/issues/detail?id=164882
     274            if (!node->isV8CollectableDuringMinorGC() || (node->hasTagName(HTMLNames::imgTag) && static_cast<HTMLImageElement*>(node)->hasPendingActivity())) {
     275                // The fact that we encounter a node that is not in the Eden space
     276                // implies that its wrapper might be in the old space of V8.
     277                // This indicates that the minor GC cannot anyway judge reachability
     278                // of this DOM tree. Thus we give up traversing the DOM tree.
     279                return;
     280            }
     281            // A once traversed node is removed from the Eden space.
     282            node->setV8CollectableDuringMinorGC(false);
     283            newSpaceWrappers.append(node->wrapper());
     284        }
     285        if (node->firstChild()) {
     286            node = node->firstChild();
     287            continue;
     288        }
     289        while (!node->nextSibling()) {
     290            if (!node->parentNode())
     291                break;
     292            node = node->parentNode();
     293        }
     294        if (node->parentNode())
     295            node = node->nextSibling();
     296    } while (node != startNode);
     297
     298    // We completed the DOM tree traversal. All wrappers in the DOM tree are
     299    // stored in newSpaceWrappers and are expected to exist in the new space of V8.
     300    // We report those wrappers to V8 as an object group.
     301    for (size_t i = 0; i < newSpaceWrappers.size(); i++)
     302        newSpaceWrappers[i].MarkPartiallyDependent();
     303    if (newSpaceWrappers.size() > 0)
     304        v8::V8::AddObjectGroup(&newSpaceWrappers[0], newSpaceWrappers.size());
     305}
     306
     307void V8GCController::didCreateWrapperForNode(Node* node)
     308{
     309    // To make minor GC cycle time bounded, we limit the number of wrappers handled
     310    // by each minor GC cycle to 10000. This value was selected so that the minor
     311    // GC cycle time is bounded to 20 ms in a case where the new space size
     312    // is 16 MB and it is full of wrappers (which is almost the worst case).
     313    // Practically speaking, as far as I crawled real web applications,
     314    // the number of wrappers handled by each minor GC cycle is at most 3000.
     315    // So this limit is mainly for pathological micro benchmarks.
     316    const unsigned wrappersHandledByEachMinorGC = 10000;
     317    ASSERT(!node->wrapper().IsEmpty());
     318    if (!m_edenNodes)
     319        m_edenNodes = adoptPtr(new Vector<Node*>).leakPtr();
     320    if (m_edenNodes->size() <= wrappersHandledByEachMinorGC) {
     321        // A node of a newly created wrapper is put into the Eden space.
     322        m_edenNodes->append(node);
     323        node->setV8CollectableDuringMinorGC(true);
     324    }
     325}
     326
    349327void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags)
    350328{
     
    353331    else if (type == v8::kGCTypeMarkSweepCompact)
    354332        majorGCPrologue();
     333
     334    if (isMainThreadOrGCThread() && m_edenNodes) {
     335        // The Eden space is cleared at every minor/major GC.
     336        m_edenNodes->clear();
     337    }
    355338}
    356339
    357340void V8GCController::minorGCPrologue()
     341{
     342    TRACE_EVENT_BEGIN0("v8", "GC");
     343
     344    if (isMainThreadOrGCThread() && m_edenNodes) {
     345        for (size_t i = 0; i < m_edenNodes->size(); i++) {
     346            ASSERT(!m_edenNodes->at(i)->wrapper().IsEmpty());
     347            if (m_edenNodes->at(i)->isV8CollectableDuringMinorGC()) // This branch is just for performance.
     348                gcTree(m_edenNodes->at(i));
     349        }
     350    }
     351}
     352
     353// Create object groups for DOM tree nodes.
     354void V8GCController::majorGCPrologue()
    358355{
    359356    TRACE_EVENT_BEGIN0("v8", "GC");
     
    362359    v8::HandleScope scope;
    363360
    364     // A minor GC can handle the main world only.
    365     DOMWrapperWorld* world = worldForEnteredContextWithoutContextCheck();
    366     if (world && world->isMainWorld()) {
    367         MinorGCWrapperVisitor visitor(isolate);
    368         v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
    369         visitor.notifyFinished();
    370     }
    371 }
    372 
    373 // Create object groups for DOM tree nodes.
    374 void V8GCController::majorGCPrologue()
    375 {
    376     TRACE_EVENT_BEGIN0("v8", "GC");
    377 
    378     v8::Isolate* isolate = v8::Isolate::GetCurrent();
    379     v8::HandleScope scope;
    380 
    381     MajorGCWrapperVisitor visitor(isolate);
     361    WrapperVisitor visitor(isolate);
    382362    v8::V8::VisitHandlesWithClassIds(&visitor);
    383363    visitor.notifyFinished();
  • trunk/Source/WebCore/bindings/v8/V8GCController.h

    r142077 r142103  
    5353
    5454    static Node* opaqueRootForGC(Node*, v8::Isolate*);
     55    static void didCreateWrapperForNode(Node*);
    5556
    5657private:
Note: See TracChangeset for help on using the changeset viewer.