Title: [125873] trunk/Source
Revision
125873
Author
[email protected]
Date
2012-08-17 02:42:31 -0700 (Fri, 17 Aug 2012)

Log Message

[Qt] Replace use of internal Weak smart pointer with JSWeakObjectMap
https://bugs.webkit.org/show_bug.cgi?id=93872

Reviewed by Kenneth Rohde Christiansen.

Source/_javascript_Core:

* Target.pri: Add missing JSWeakObjectMap file to build.

Source/WebCore:

The intention of this patch series is to replace use of internal JSC
API with use of the stable and public C API.

The JSC::Weak template is internal API and the only part of the C API
that exposes similar functionality is the JSWeakObjectMap. It is
special in the sense that its life-time is tied to the life-time of the
JS global object, which in turn is subject to garbage collection. In
order to maximize re-use of the same map across different JSContextRef
instances, we use one JSWeakObjectMap per context group and store the
map in a separate context.

* bridge/qt/qt_instance.cpp:
(JSC::Bindings::unusedWeakObjectMapCallback):
(Bindings):
(JSC::Bindings::WeakMapImpl::WeakMapImpl):
(JSC::Bindings::WeakMapImpl::~WeakMapImpl):
(JSC::Bindings::WeakMap::~WeakMap):
(JSC::Bindings::WeakMap::set):
(JSC::Bindings::WeakMap::get):
(JSC::Bindings::WeakMap::remove):
* bridge/qt/qt_instance.h:
(WeakMapImpl):
(Bindings):
(WeakMap):
(QtInstance):
* bridge/qt/qt_runtime.cpp:
(JSC::Bindings::QtRuntimeMethod::~QtRuntimeMethod):
(JSC::Bindings::QtRuntimeMethod::jsObjectRef):
* bridge/qt/qt_runtime.h:
(QtRuntimeMethod):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (125872 => 125873)


--- trunk/Source/_javascript_Core/ChangeLog	2012-08-17 09:25:13 UTC (rev 125872)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-08-17 09:42:31 UTC (rev 125873)
@@ -1,3 +1,12 @@
+2012-08-16  Simon Hausmann  <[email protected]>
+
+        [Qt] Replace use of internal Weak smart pointer with JSWeakObjectMap
+        https://bugs.webkit.org/show_bug.cgi?id=93872
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        * Target.pri: Add missing JSWeakObjectMap file to build.
+
 2012-08-16  Filip Pizlo  <[email protected]>
 
         Structure check hoisting should be less expensive

Modified: trunk/Source/_javascript_Core/Target.pri (125872 => 125873)


--- trunk/Source/_javascript_Core/Target.pri	2012-08-17 09:25:13 UTC (rev 125872)
+++ trunk/Source/_javascript_Core/Target.pri	2012-08-17 09:42:31 UTC (rev 125873)
@@ -40,6 +40,7 @@
     API/JSObjectRef.cpp \
     API/JSStringRef.cpp \
     API/JSValueRef.cpp \
+    API/JSWeakObjectMapRefPrivate.cpp \
     API/OpaqueJSString.cpp \
     assembler/ARMAssembler.cpp \
     assembler/ARMv7Assembler.cpp \

Modified: trunk/Source/WebCore/ChangeLog (125872 => 125873)


--- trunk/Source/WebCore/ChangeLog	2012-08-17 09:25:13 UTC (rev 125872)
+++ trunk/Source/WebCore/ChangeLog	2012-08-17 09:42:31 UTC (rev 125873)
@@ -1,3 +1,42 @@
+2012-08-16  Simon Hausmann  <[email protected]>
+
+        [Qt] Replace use of internal Weak smart pointer with JSWeakObjectMap
+        https://bugs.webkit.org/show_bug.cgi?id=93872
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        The intention of this patch series is to replace use of internal JSC
+        API with use of the stable and public C API.
+
+        The JSC::Weak template is internal API and the only part of the C API
+        that exposes similar functionality is the JSWeakObjectMap. It is
+        special in the sense that its life-time is tied to the life-time of the
+        JS global object, which in turn is subject to garbage collection. In
+        order to maximize re-use of the same map across different JSContextRef
+        instances, we use one JSWeakObjectMap per context group and store the
+        map in a separate context.
+
+        * bridge/qt/qt_instance.cpp:
+        (JSC::Bindings::unusedWeakObjectMapCallback):
+        (Bindings):
+        (JSC::Bindings::WeakMapImpl::WeakMapImpl):
+        (JSC::Bindings::WeakMapImpl::~WeakMapImpl):
+        (JSC::Bindings::WeakMap::~WeakMap):
+        (JSC::Bindings::WeakMap::set):
+        (JSC::Bindings::WeakMap::get):
+        (JSC::Bindings::WeakMap::remove):
+        * bridge/qt/qt_instance.h:
+        (WeakMapImpl):
+        (Bindings):
+        (WeakMap):
+        (QtInstance):
+        * bridge/qt/qt_runtime.cpp:
+        (JSC::Bindings::QtRuntimeMethod::~QtRuntimeMethod):
+        (JSC::Bindings::QtRuntimeMethod::jsObjectRef):
+        * bridge/qt/qt_runtime.h:
+        (QtRuntimeMethod):
+
+
 2012-08-16  Pavel Feldman  <[email protected]>
 
         Web Inspector: build Elements, Resources, Timeline, Audits and Console panels lazily.

Modified: trunk/Source/WebCore/bridge/qt/qt_instance.cpp (125872 => 125873)


--- trunk/Source/WebCore/bridge/qt/qt_instance.cpp	2012-08-17 09:25:13 UTC (rev 125872)
+++ trunk/Source/WebCore/bridge/qt/qt_instance.cpp	2012-08-17 09:42:31 UTC (rev 125873)
@@ -40,6 +40,63 @@
 namespace JSC {
 namespace Bindings {
 
+static void unusedWeakObjectMapCallback(JSWeakObjectMapRef, void*)
+{
+}
+
+WeakMapImpl::WeakMapImpl(JSContextGroupRef group)
+{
+    m_context = JSGlobalContextCreateInGroup(group, 0);
+    // Deleted by GC when m_context's globalObject gets collected.
+    m_map = JSWeakObjectMapCreate(m_context, 0, unusedWeakObjectMapCallback);
+}
+
+WeakMapImpl::~WeakMapImpl()
+{
+    JSGlobalContextRelease(m_context);
+    m_context = 0;
+    m_map = 0;
+}
+
+typedef HashMap<JSContextGroupRef, RefPtr<WeakMapImpl> > WeakMapSet;
+static WeakMapSet weakMaps;
+
+WeakMap::~WeakMap()
+{
+    // If this is the last WeakMap instance left, then we should remove
+    // the cached WeakMapImpl from the global weakMaps, too.
+    if (m_impl && m_impl->refCount() == 2) {
+        weakMaps.remove(JSContextGetGroup(m_impl->m_context));
+        ASSERT(m_impl->hasOneRef());
+    }
+}
+
+void WeakMap::set(JSContextRef context, void *key, JSObjectRef object)
+{
+    if (!m_impl) {
+        JSContextGroupRef group = JSContextGetGroup(context);
+        WeakMapSet::AddResult entry = weakMaps.add(group, 0);
+        if (entry.isNewEntry)
+            entry.iterator->second = new WeakMapImpl(group);
+        m_impl = entry.iterator->second;
+    }
+    JSWeakObjectMapSet(m_impl->m_context, m_impl->m_map, key, object);
+}
+
+JSObjectRef WeakMap::get(void* key)
+{
+    if (!m_impl)
+        return 0;
+    return JSWeakObjectMapGet(m_impl->m_context, m_impl->m_map, key);
+}
+
+void WeakMap::remove(void *key)
+{
+    if (!m_impl)
+        return;
+    JSWeakObjectMapRemove(m_impl->m_context, m_impl->m_map, key);
+}
+
 // Cache QtInstances
 typedef QMultiHash<void*, QtInstance*> QObjectInstanceMap;
 static QObjectInstanceMap cachedInstances;

Modified: trunk/Source/WebCore/bridge/qt/qt_instance.h (125872 => 125873)


--- trunk/Source/WebCore/bridge/qt/qt_instance.h	2012-08-17 09:25:13 UTC (rev 125872)
+++ trunk/Source/WebCore/bridge/qt/qt_instance.h	2012-08-17 09:42:31 UTC (rev 125873)
@@ -21,6 +21,7 @@
 #define qt_instance_h
 
 #include "BridgeJSC.h"
+#include "JSWeakObjectMapRefPrivate.h"
 #include <QPointer>
 #include "Weak.h"
 #include "runtime_root.h"
@@ -35,6 +36,27 @@
 class QtField;
 class QtRuntimeMethod;
 
+class WeakMapImpl : public RefCounted<WeakMapImpl> {
+public:
+    WeakMapImpl(JSContextGroupRef);
+    ~WeakMapImpl();
+
+    JSGlobalContextRef m_context;
+    JSWeakObjectMapRef m_map;
+};
+
+class WeakMap {
+public:
+    ~WeakMap();
+
+    void set(JSContextRef, void* key, JSObjectRef);
+    JSObjectRef get(void* key);
+    void remove(void* key);
+
+private:
+    RefPtr<WeakMapImpl> m_impl;
+};
+
 class QtInstance : public Instance {
 public:
     enum ValueOwnership {
@@ -81,11 +103,13 @@
 
     friend class QtClass;
     friend class QtField;
+    friend class QtRuntimeMethod;
     QtInstance(QObject*, PassRefPtr<RootObject>, ValueOwnership); // Factory produced only..
     mutable QtClass* m_class;
     QPointer<QObject> m_object;
     QObject* m_hashkey;
     mutable QHash<QByteArray, QtRuntimeMethod*> m_methods;
+    WeakMap m_cachedMethods;
     mutable QHash<QString, QtField*> m_fields;
     ValueOwnership m_ownership;
 };

Modified: trunk/Source/WebCore/bridge/qt/qt_runtime.cpp (125872 => 125873)


--- trunk/Source/WebCore/bridge/qt/qt_runtime.cpp	2012-08-17 09:25:13 UTC (rev 125872)
+++ trunk/Source/WebCore/bridge/qt/qt_runtime.cpp	2012-08-17 09:42:31 UTC (rev 125873)
@@ -1301,8 +1301,9 @@
 
 QtRuntimeMethod::~QtRuntimeMethod()
 {
-    if (m_jsObject)
-        JSObjectSetPrivate(toRef(m_jsObject.get()), 0);
+    if (JSObjectRef cachedWrapper = m_instance->m_cachedMethods.get(this))
+        JSObjectSetPrivate(cachedWrapper, 0);
+    m_instance->m_cachedMethods.remove(this);
 }
 
 JSValueRef QtRuntimeMethod::call(JSContextRef context, JSObjectRef function, JSObjectRef /*thisObject*/, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -1350,8 +1351,8 @@
 
 JSObjectRef QtRuntimeMethod::jsObjectRef(JSContextRef context, JSValueRef* exception)
 {
-    if (m_jsObject)
-        return toRef(m_jsObject.get());
+    if (JSObjectRef cachedWrapper = m_instance->m_cachedMethods.get(this))
+        return cachedWrapper;
 
     static const JSClassDefinition classDefForConnect = {
         0, 0, "connect", 0, 0, 0,
@@ -1387,7 +1388,8 @@
     JSObjectSetProperty(context, object, lengthStr, JSValueMakeNumber(context, 0), attributes, exception);
     JSObjectSetProperty(context, object, nameStr, JSValueMakeString(context, actualNameStr.get()), attributes, exception);
 
-    m_jsObject = PassWeak<JSObject>(toJS(object));
+    m_instance->m_cachedMethods.set(context, this, object);
+
     return object;
 }
 

Modified: trunk/Source/WebCore/bridge/qt/qt_runtime.h (125872 => 125873)


--- trunk/Source/WebCore/bridge/qt/qt_runtime.h	2012-08-17 09:25:13 UTC (rev 125872)
+++ trunk/Source/WebCore/bridge/qt/qt_runtime.h	2012-08-17 09:42:31 UTC (rev 125873)
@@ -122,7 +122,6 @@
     QByteArray m_identifier;
     int m_index;
     int m_flags;
-    Weak<JSObject> m_jsObject;
     QtInstance* m_instance;
 };
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to