Title: [93555] trunk/Source/WebKit2
Revision
93555
Author
[email protected]
Date
2011-08-22 16:08:37 -0700 (Mon, 22 Aug 2011)

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

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (93554 => 93555)


--- trunk/Source/WebKit2/ChangeLog	2011-08-22 23:08:36 UTC (rev 93554)
+++ trunk/Source/WebKit2/ChangeLog	2011-08-22 23:08:37 UTC (rev 93555)
@@ -1,3 +1,29 @@
+2011-08-22  Oliver Hunt  <[email protected]>
+
+        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:
+
 2011-08-22  Anders Carlsson  <[email protected]>
 
         Move code from PageClientImpl::doneWithKeyEvent to WKView

Modified: trunk/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp (93554 => 93555)


--- trunk/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp	2011-08-22 23:08:36 UTC (rev 93554)
+++ trunk/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp	2011-08-22 23:08:37 UTC (rev 93555)
@@ -77,6 +77,16 @@
     m_npObject = 0;
 }
 
+NPObject* JSNPObject::leakNPObject()
+{
+    ASSERT(m_npObject);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+
+    NPObject* object = m_npObject;
+    m_npObject = 0;
+    return object;
+}
+
 JSValue JSNPObject::callMethod(ExecState* exec, NPIdentifier methodName)
 {
     ASSERT_GC_OBJECT_INHERITS(this, &s_info);

Modified: trunk/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.h (93554 => 93555)


--- trunk/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.h	2011-08-22 23:08:36 UTC (rev 93554)
+++ trunk/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.h	2011-08-22 23:08:37 UTC (rev 93555)
@@ -50,6 +50,9 @@
 
     void invalidate();
 
+    // Used to invalidate an NPObject asynchronously.
+    NPObject* leakNPObject();
+
     JSC::JSValue callMethod(JSC::ExecState*, NPIdentifier methodName);
     JSC::JSValue callObject(JSC::ExecState*);
     JSC::JSValue callConstructor(JSC::ExecState*);

Modified: trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp (93554 => 93555)


--- trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp	2011-08-22 23:08:36 UTC (rev 93554)
+++ trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp	2011-08-22 23:08:37 UTC (rev 93555)
@@ -30,6 +30,7 @@
 #include "NPJSObject.h"
 #include "NPRuntimeUtilities.h"
 #include "PluginView.h"
+#include "WebProcess.h"
 #include <_javascript_Core/Error.h>
 #include <_javascript_Core/JSLock.h>
 #include <_javascript_Core/SourceCode.h>
@@ -45,6 +46,7 @@
 
 NPRuntimeObjectMap::NPRuntimeObjectMap(PluginView* pluginView)
     : m_pluginView(pluginView)
+    , m_finalizationTimer(WebProcess::shared().runLoop(), this, &NPRuntimeObjectMap::invalidateQueuedObjects)
 {
 }
 
@@ -218,9 +220,19 @@
     ASSERT(m_npJSObjects.isEmpty());
 
     HashMap<NPObject*, JSC::Weak<JSNPObject> >::iterator end = m_jsNPObjects.end();
+    Vector<Strong<JSNPObject> > objects;
     for (HashMap<NPObject*, JSC::Weak<JSNPObject> >::iterator ptr = m_jsNPObjects.begin(); ptr != end; ++ptr)
-        ptr->second.get()->invalidate();
+        objects.append(Strong<JSNPObject>(globalObject()->globalData(), ptr->second));
     m_jsNPObjects.clear();
+    for (size_t i = 0; i < objects.size(); ++i)
+        objects[i]->invalidate();
+    
+    // Deal with any objects that were scheduled for delayed destruction
+    if (m_npObjectsToFinalize.isEmpty())
+        return;
+    ASSERT(m_finalizationTimer.isActive());
+    m_finalizationTimer.stop();
+    invalidateQueuedObjects();
 }
 
 JSGlobalObject* NPRuntimeObjectMap::globalObject() const
@@ -265,14 +277,34 @@
     globalExceptionString() = String();
 }
 
+void NPRuntimeObjectMap::invalidateQueuedObjects()
+{
+    ASSERT(m_npObjectsToFinalize.size());
+    // We deliberately re-request m_npObjectsToFinalize.size() as custom dealloc
+    // functions may execute JS and so get more objects added to the dealloc queue
+    for (size_t i = 0; i < m_npObjectsToFinalize.size(); ++i)
+        deallocateNPObject(m_npObjectsToFinalize[i]);
+    m_npObjectsToFinalize.clear();
+}
+
+void NPRuntimeObjectMap::addToInvalidationQueue(NPObject* npObject)
+{
+    if (trySafeReleaseNPObject(npObject))
+        return;
+    if (m_npObjectsToFinalize.isEmpty())
+        m_finalizationTimer.startOneShot(0);
+    ASSERT(m_finalizationTimer.isActive());
+    m_npObjectsToFinalize.append(npObject);
+}
+
 void NPRuntimeObjectMap::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
 {
     HashMap<NPObject*, JSC::Weak<JSNPObject> >::iterator found = m_jsNPObjects.find(static_cast<NPObject*>(context));
     ASSERT(found != m_jsNPObjects.end());
     ASSERT_UNUSED(handle, asObject(handle.get()) == found->second);
-
-    found->second.get()->invalidate();
+    JSNPObject* object = found->second.get();
     m_jsNPObjects.remove(found);
+    addToInvalidationQueue(object->leakNPObject());
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.h (93554 => 93555)


--- trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.h	2011-08-22 23:08:36 UTC (rev 93554)
+++ trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.h	2011-08-22 23:08:37 UTC (rev 93555)
@@ -26,6 +26,9 @@
 #ifndef NPJSObjectWrapperMap_h
 #define NPJSObjectWrapperMap_h
 
+
+#include "RunLoop.h"
+
 #include <heap/Weak.h>
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
@@ -87,11 +90,15 @@
 private:
     // WeakHandleOwner
     virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+    void addToInvalidationQueue(NPObject*);
+    void invalidateQueuedObjects();
 
     PluginView* m_pluginView;
 
     HashMap<JSC::JSObject*, NPJSObject*> m_npJSObjects;
     HashMap<NPObject*, JSC::Weak<JSNPObject> > m_jsNPObjects;
+    Vector<NPObject*> m_npObjectsToFinalize;
+    RunLoop::Timer<NPRuntimeObjectMap> m_finalizationTimer;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeUtilities.cpp (93554 => 93555)


--- trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeUtilities.cpp	2011-08-22 23:08:36 UTC (rev 93554)
+++ trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeUtilities.cpp	2011-08-22 23:08:37 UTC (rev 93555)
@@ -93,6 +93,23 @@
     npObject->referenceCount++;
 }
 
+bool trySafeReleaseNPObject(NPObject* npObject)
+{
+    ASSERT(npObject);
+    if (!npObject)
+        return true;
+    
+    ASSERT(npObject->referenceCount >= 1);
+
+    npObject->referenceCount--;
+    if (npObject->referenceCount)
+        return true;
+    if (npObject->_class->deallocate)
+        return false;
+    deallocateNPObject(npObject);
+    return true;
+}
+
 void releaseNPObject(NPObject* npObject)
 {
     ASSERT(npObject);

Modified: trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeUtilities.h (93554 => 93555)


--- trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeUtilities.h	2011-08-22 23:08:36 UTC (rev 93554)
+++ trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeUtilities.h	2011-08-22 23:08:37 UTC (rev 93555)
@@ -54,6 +54,14 @@
 
 void retainNPObject(NPObject*);
 void releaseNPObject(NPObject*);
+    
+// This function decrements the refcount of the specified object. If the
+// refcount reaches 0 it will attempt to destroy the object. If the object has
+// a custom deallocate function it will fail and return false, so it will be
+// up to the caller to call deallocateNPObject.
+// This function is used to implement the delayed finalization of NPObjects
+// released during GC.
+bool trySafeReleaseNPObject(NPObject*);
 
 void releaseNPVariantValue(NPVariant*);
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to