Changeset 93555 in webkit


Ignore:
Timestamp:
Aug 22, 2011 4:08:37 PM (13 years ago)
Author:
oliver@apple.com
Message:

Delay GC triggered NP object destruction to the next runloop cycle
https://bugs.webkit.org/show_bug.cgi?id=66717

Reviewed by Anders Carlsson.

Delay destruction of plugin objects caused by GC until the next
runloop cycle so that they can execute JS in their finalizers.
We do this using a zero delay timer coupled with a queue of
objects to be finalised.

  • WebProcess/Plugins/Netscape/JSNPObject.cpp:

(WebKit::JSNPObject::releaseObject):

  • WebProcess/Plugins/Netscape/JSNPObject.h:
  • WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp:

(WebKit::NPRuntimeObjectMap::NPRuntimeObjectMap):
(WebKit::NPRuntimeObjectMap::invalidate):
(WebKit::NPRuntimeObjectMap::invalidateQueuedObjects):
(WebKit::NPRuntimeObjectMap::addToInvalidationQueue):
(WebKit::NPRuntimeObjectMap::finalize):

  • WebProcess/Plugins/Netscape/NPRuntimeObjectMap.h:
  • WebProcess/Plugins/Netscape/NPRuntimeUtilities.cpp:

(WebKit::trySafeReleaseNPObject):

  • WebProcess/Plugins/Netscape/NPRuntimeUtilities.h:
Location:
trunk/Source/WebKit2
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r93550 r93555  
     12011-08-22  Oliver Hunt  <oliver@apple.com>
     2
     3        Delay GC triggered NP object destruction to the next runloop cycle
     4        https://bugs.webkit.org/show_bug.cgi?id=66717
     5
     6        Reviewed by Anders Carlsson.
     7
     8        Delay destruction of plugin objects caused by GC until the next
     9        runloop cycle so that they can execute JS in their finalizers.
     10        We do this using a zero delay timer coupled with a queue of
     11        objects to be finalised.
     12
     13        * WebProcess/Plugins/Netscape/JSNPObject.cpp:
     14        (WebKit::JSNPObject::releaseObject):
     15        * WebProcess/Plugins/Netscape/JSNPObject.h:
     16        * WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp:
     17        (WebKit::NPRuntimeObjectMap::NPRuntimeObjectMap):
     18        (WebKit::NPRuntimeObjectMap::invalidate):
     19        (WebKit::NPRuntimeObjectMap::invalidateQueuedObjects):
     20        (WebKit::NPRuntimeObjectMap::addToInvalidationQueue):
     21        (WebKit::NPRuntimeObjectMap::finalize):
     22        * WebProcess/Plugins/Netscape/NPRuntimeObjectMap.h:
     23        * WebProcess/Plugins/Netscape/NPRuntimeUtilities.cpp:
     24        (WebKit::trySafeReleaseNPObject):
     25        * WebProcess/Plugins/Netscape/NPRuntimeUtilities.h:
     26
    1272011-08-22  Anders Carlsson  <andersca@apple.com>
    228
  • trunk/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp

    r91903 r93555  
    7878}
    7979
     80NPObject* JSNPObject::leakNPObject()
     81{
     82    ASSERT(m_npObject);
     83    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     84
     85    NPObject* object = m_npObject;
     86    m_npObject = 0;
     87    return object;
     88}
     89
    8090JSValue JSNPObject::callMethod(ExecState* exec, NPIdentifier methodName)
    8191{
  • trunk/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.h

    r92706 r93555  
    5151    void invalidate();
    5252
     53    // Used to invalidate an NPObject asynchronously.
     54    NPObject* leakNPObject();
     55
    5356    JSC::JSValue callMethod(JSC::ExecState*, NPIdentifier methodName);
    5457    JSC::JSValue callObject(JSC::ExecState*);
  • trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp

    r91903 r93555  
    3131#include "NPRuntimeUtilities.h"
    3232#include "PluginView.h"
     33#include "WebProcess.h"
    3334#include <JavaScriptCore/Error.h>
    3435#include <JavaScriptCore/JSLock.h>
     
    4647NPRuntimeObjectMap::NPRuntimeObjectMap(PluginView* pluginView)
    4748    : m_pluginView(pluginView)
     49    , m_finalizationTimer(WebProcess::shared().runLoop(), this, &NPRuntimeObjectMap::invalidateQueuedObjects)
    4850{
    4951}
     
    219221
    220222    HashMap<NPObject*, JSC::Weak<JSNPObject> >::iterator end = m_jsNPObjects.end();
     223    Vector<Strong<JSNPObject> > objects;
    221224    for (HashMap<NPObject*, JSC::Weak<JSNPObject> >::iterator ptr = m_jsNPObjects.begin(); ptr != end; ++ptr)
    222         ptr->second.get()->invalidate();
     225        objects.append(Strong<JSNPObject>(globalObject()->globalData(), ptr->second));
    223226    m_jsNPObjects.clear();
     227    for (size_t i = 0; i < objects.size(); ++i)
     228        objects[i]->invalidate();
     229   
     230    // Deal with any objects that were scheduled for delayed destruction
     231    if (m_npObjectsToFinalize.isEmpty())
     232        return;
     233    ASSERT(m_finalizationTimer.isActive());
     234    m_finalizationTimer.stop();
     235    invalidateQueuedObjects();
    224236}
    225237
     
    266278}
    267279
     280void NPRuntimeObjectMap::invalidateQueuedObjects()
     281{
     282    ASSERT(m_npObjectsToFinalize.size());
     283    // We deliberately re-request m_npObjectsToFinalize.size() as custom dealloc
     284    // functions may execute JS and so get more objects added to the dealloc queue
     285    for (size_t i = 0; i < m_npObjectsToFinalize.size(); ++i)
     286        deallocateNPObject(m_npObjectsToFinalize[i]);
     287    m_npObjectsToFinalize.clear();
     288}
     289
     290void NPRuntimeObjectMap::addToInvalidationQueue(NPObject* npObject)
     291{
     292    if (trySafeReleaseNPObject(npObject))
     293        return;
     294    if (m_npObjectsToFinalize.isEmpty())
     295        m_finalizationTimer.startOneShot(0);
     296    ASSERT(m_finalizationTimer.isActive());
     297    m_npObjectsToFinalize.append(npObject);
     298}
     299
    268300void NPRuntimeObjectMap::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
    269301{
     
    271303    ASSERT(found != m_jsNPObjects.end());
    272304    ASSERT_UNUSED(handle, asObject(handle.get()) == found->second);
    273 
    274     found->second.get()->invalidate();
     305    JSNPObject* object = found->second.get();
    275306    m_jsNPObjects.remove(found);
     307    addToInvalidationQueue(object->leakNPObject());
    276308}
    277309
  • trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.h

    r87195 r93555  
    2626#ifndef NPJSObjectWrapperMap_h
    2727#define NPJSObjectWrapperMap_h
     28
     29
     30#include "RunLoop.h"
    2831
    2932#include <heap/Weak.h>
     
    8891    // WeakHandleOwner
    8992    virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
     93    void addToInvalidationQueue(NPObject*);
     94    void invalidateQueuedObjects();
    9095
    9196    PluginView* m_pluginView;
     
    9398    HashMap<JSC::JSObject*, NPJSObject*> m_npJSObjects;
    9499    HashMap<NPObject*, JSC::Weak<JSNPObject> > m_jsNPObjects;
     100    Vector<NPObject*> m_npObjectsToFinalize;
     101    RunLoop::Timer<NPRuntimeObjectMap> m_finalizationTimer;
    95102};
    96103
  • trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeUtilities.cpp

    r76916 r93555  
    9494}
    9595
     96bool trySafeReleaseNPObject(NPObject* npObject)
     97{
     98    ASSERT(npObject);
     99    if (!npObject)
     100        return true;
     101   
     102    ASSERT(npObject->referenceCount >= 1);
     103
     104    npObject->referenceCount--;
     105    if (npObject->referenceCount)
     106        return true;
     107    if (npObject->_class->deallocate)
     108        return false;
     109    deallocateNPObject(npObject);
     110    return true;
     111}
     112
    96113void releaseNPObject(NPObject* npObject)
    97114{
  • trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeUtilities.h

    r71169 r93555  
    5555void retainNPObject(NPObject*);
    5656void releaseNPObject(NPObject*);
     57   
     58// This function decrements the refcount of the specified object. If the
     59// refcount reaches 0 it will attempt to destroy the object. If the object has
     60// a custom deallocate function it will fail and return false, so it will be
     61// up to the caller to call deallocateNPObject.
     62// This function is used to implement the delayed finalization of NPObjects
     63// released during GC.
     64bool trySafeReleaseNPObject(NPObject*);
    5765
    5866void releaseNPVariantValue(NPVariant*);
Note: See TracChangeset for help on using the changeset viewer.