2008-01-13 Michael Goddard <michael.goddard@trolltech.com>
authormrowe@apple.com <mrowe@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Jan 2008 11:08:39 +0000 (11:08 +0000)
committermrowe@apple.com <mrowe@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Jan 2008 11:08:39 +0000 (11:08 +0000)
        Reviewed by Anders Carlsson.

        Add binding language type to Instance.
        Allows runtime determination of the type of an
        Instance, to allow safe casting.  Doesn't actually
        add any safe casting yet, though.

        Add a helper function to get an Instance from a JSObject*.
        Given an object and the expected binding language, see if
        the JSObject actually wraps an Instance of the given type
        and return it.  Otherwise return 0.

        Move RuntimeObjectImp creations into Instance.
        Make the ctor protected, and Instance a friend class, so
        that all creation of RuntimeObjectImps goes through
        one place.

        Remove copy ctor/assignment operator for QtInstance.
        Instance itself is Noncopyable, so QtInstance doesn't
        need to have these.

        Add caching for QtInstance and associated RuntimeObjectImps.
        Push any dealings with QtLanguage bindings into QtInstance,
        and cache them there, rather than in the Instance layer.  Add
        a QtRuntimeObjectImp to help with caching.

        * JavaScriptCore.exp:
        * bindings/c/c_instance.h:
        * bindings/jni/jni_instance.h:
        * bindings/objc/objc_instance.h:
        * bindings/qt/qt_instance.cpp:
        (KJS::Bindings::QtRuntimeObjectImp::QtRuntimeObjectImp):
        (KJS::Bindings::QtRuntimeObjectImp::~QtRuntimeObjectImp):
        (KJS::Bindings::QtRuntimeObjectImp::invalidate):
        (KJS::Bindings::QtRuntimeObjectImp::removeFromCache):
        (KJS::Bindings::QtInstance::QtInstance):
        (KJS::Bindings::QtInstance::~QtInstance):
        (KJS::Bindings::QtInstance::getQtInstance):
        (KJS::Bindings::QtInstance::getRuntimeObject):
        * bindings/qt/qt_instance.h:
        (KJS::Bindings::QtInstance::getBindingLanguage):
        * bindings/runtime.cpp:
        (KJS::Bindings::Instance::createBindingForLanguageInstance):
        (KJS::Bindings::Instance::createRuntimeObject):
        (KJS::Bindings::Instance::getInstance):
        * bindings/runtime.h:
        * bindings/runtime_object.h:
        (KJS::RuntimeObjectImp::getInternalInstance):

2008-01-13  Michael Goddard  <michael.goddard@trolltech.com>

        Reviewed by Anders Carlsson.

        Move RuntimeObjectImp creations into Instance.
        Make the ctor protected, and Instance a friend class, so
        that all creation of RuntimeObjectImps goes through
        one place.

        * bindings/js/kjs_dom.cpp:
        (WebCore::getRuntimeObject):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@29447 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/bindings/c/c_instance.h
JavaScriptCore/bindings/jni/jni_instance.h
JavaScriptCore/bindings/jni/jni_jsobject.cpp
JavaScriptCore/bindings/objc/objc_instance.h
JavaScriptCore/bindings/qt/qt_instance.cpp
JavaScriptCore/bindings/qt/qt_instance.h
JavaScriptCore/bindings/runtime.cpp
JavaScriptCore/bindings/runtime.h
JavaScriptCore/bindings/runtime_object.h
WebCore/ChangeLog
WebCore/bindings/js/kjs_dom.cpp

index d18d4d414fa1f1e13d27efa42e1cf5961408c086..44bf6ba22ee71f2f068250001c1f56b4e2d19f4b 100644 (file)
@@ -1,3 +1,54 @@
+2008-01-13  Michael Goddard  <michael.goddard@trolltech.com>
+
+        Reviewed by Anders Carlsson.
+
+        Add binding language type to Instance.
+        Allows runtime determination of the type of an
+        Instance, to allow safe casting.  Doesn't actually
+        add any safe casting yet, though.
+
+        Add a helper function to get an Instance from a JSObject*.
+        Given an object and the expected binding language, see if
+        the JSObject actually wraps an Instance of the given type
+        and return it.  Otherwise return 0.
+
+        Move RuntimeObjectImp creations into Instance.
+        Make the ctor protected, and Instance a friend class, so
+        that all creation of RuntimeObjectImps goes through
+        one place.
+
+        Remove copy ctor/assignment operator for QtInstance.
+        Instance itself is Noncopyable, so QtInstance doesn't
+        need to have these.
+
+        Add caching for QtInstance and associated RuntimeObjectImps.
+        Push any dealings with QtLanguage bindings into QtInstance,
+        and cache them there, rather than in the Instance layer.  Add
+        a QtRuntimeObjectImp to help with caching.
+
+        * JavaScriptCore.exp:
+        * bindings/c/c_instance.h:
+        * bindings/jni/jni_instance.h:
+        * bindings/objc/objc_instance.h:
+        * bindings/qt/qt_instance.cpp:
+        (KJS::Bindings::QtRuntimeObjectImp::QtRuntimeObjectImp):
+        (KJS::Bindings::QtRuntimeObjectImp::~QtRuntimeObjectImp):
+        (KJS::Bindings::QtRuntimeObjectImp::invalidate):
+        (KJS::Bindings::QtRuntimeObjectImp::removeFromCache):
+        (KJS::Bindings::QtInstance::QtInstance):
+        (KJS::Bindings::QtInstance::~QtInstance):
+        (KJS::Bindings::QtInstance::getQtInstance):
+        (KJS::Bindings::QtInstance::getRuntimeObject):
+        * bindings/qt/qt_instance.h:
+        (KJS::Bindings::QtInstance::getBindingLanguage):
+        * bindings/runtime.cpp:
+        (KJS::Bindings::Instance::createBindingForLanguageInstance):
+        (KJS::Bindings::Instance::createRuntimeObject):
+        (KJS::Bindings::Instance::getInstance):
+        * bindings/runtime.h:
+        * bindings/runtime_object.h:
+        (KJS::RuntimeObjectImp::getInternalInstance):
+
 2008-01-12  Alp Toker  <alp@atoker.com>
 
         Reviewed by Mark Rowe.
index 856d7fc58095cd07495a11cdc925ec98b719e7cd..2abb63d448931078000ad9bb629c2fe44fdcd6aa 100644 (file)
@@ -158,7 +158,6 @@ __ZN3KJS16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameAr
 __ZN3KJS16ParserRefCounted3refEv
 __ZN3KJS16ParserRefCounted5derefEv
 __ZN3KJS16RuntimeObjectImp4infoE
-__ZN3KJS16RuntimeObjectImpC1EPNS_8Bindings8InstanceE
 __ZN3KJS17PropertyNameArray3addERKNS_10IdentifierE
 __ZN3KJS19InternalFunctionImp4infoE
 __ZN3KJS19InternalFunctionImpC2EPNS_17FunctionPrototypeERKNS_10IdentifierE
@@ -195,6 +194,7 @@ __ZN3KJS8Bindings23convertObjcValueToValueEPNS_9ExecStateEPvNS0_13ObjcValueTypeE
 __ZN3KJS8Bindings23convertValueToObjcValueEPNS_9ExecStateEPNS_7JSValueENS0_13ObjcValueTypeE
 __ZN3KJS8Bindings24findProtectingRootObjectEPNS_8JSObjectE
 __ZN3KJS8Bindings8Instance18didExecuteFunctionEv
+__ZN3KJS8Bindings8Instance19createRuntimeObjectEPS1_
 __ZN3KJS8Bindings8Instance21setDidExecuteFunctionEPFvPNS_9ExecStateEPNS_8JSObjectEE
 __ZN3KJS8Bindings8Instance32createBindingForLanguageInstanceENS1_15BindingLanguageEPvN3WTF10PassRefPtrINS0_10RootObjectEEE
 __ZN3KJS8Debugger12sourceUnusedEPNS_9ExecStateEi
index c011911140d3035d25a50210bd6e1031837ddfa4..9991a181c6aa92d95466bead5c465f0e2e86f180 100644 (file)
@@ -64,6 +64,8 @@ public:
     
     NPObject *getObject() const { return _object; }
 
+    virtual BindingLanguage getBindingLanguage() const { return CLanguage; }
+
 private:
     mutable CClass *_class;
     NPObject *_object;
index e6e6120e04c0e5f18d75268a1f722f31b7cbd8d2..eb89e3f2cbf3a1d4c4dfa59608e14a21daa88ec0 100644 (file)
@@ -83,7 +83,9 @@ public:
     JSValue *stringValue() const;
     JSValue *numberValue() const;
     JSValue *booleanValue() const;
-        
+
+    virtual BindingLanguage getBindingLanguage() const { return JavaLanguage; }
+
 private:
     RefPtr<JObjectWrapper> _instance;
     mutable JavaClass *_class;
index f694f68691ebf9be111f65ffca67e639bd932c1c..347f24f23112a1a54d1dd238e071ef3e3ac007d7 100644 (file)
@@ -469,9 +469,7 @@ JSValue *JavaJSObject::convertJObjectToValue (jobject theObject) const
 
     JSLock lock;
     JavaInstance* javaInstance = new JavaInstance(theObject, _rootObject);
-    RuntimeObjectImp* newImp = new RuntimeObjectImp(javaInstance);
-
-    return newImp;
+    return KJS::Bindings::Instance::createRuntimeObject(javaInstance);
 }
 
 void JavaJSObject::getListFromJArray(jobjectArray jArray, List& list) const
index 1eeffd79c49f5a531bc42048ba8b2c0d64e844f0..223379115cd6b54841e9a5a3c872857c6f620d12 100644 (file)
@@ -64,7 +64,9 @@ public:
     JSValue *stringValue() const;
     JSValue *numberValue() const;
     JSValue *booleanValue() const;
-    
+
+    virtual BindingLanguage getBindingLanguage() const { return ObjectiveCLanguage; }
+
 private:
     RetainPtr<ObjectStructPtr> _instance;
     mutable ObjcClass *_class;
index 22c6e9d5fdc6a8ec41bde70a33c4f3b107a85316..294d2828ebf0a0e336fbb741fb96792f72c3a66f 100644 (file)
 #include "config.h"
 #include "qt_instance.h"
 
+#include "list.h"
 #include "qt_class.h"
 #include "qt_runtime.h"
-#include "list.h"
+#include "runtime_object.h"
 
 #include <qmetaobject.h>
 #include <qdebug.h>
+#include <qhash.h>
 
 namespace KJS {
 namespace Bindings {
 
-QtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
-    : Instance(rootObject),
-      _class(0),
-      _object(o)
+// Cache QtInstances
+typedef QMultiHash<void*, QtInstance*> QObjectInstanceMap;
+static QObjectInstanceMap cachedInstances;
+
+// Cache JSObjects
+typedef QHash<QtInstance*, JSObject*> InstanceJSObjectMap;
+static InstanceJSObjectMap cachedObjects;
+
+// Derived RuntimeObject
+class QtRuntimeObjectImp : public RuntimeObjectImp {
+    public:
+        QtRuntimeObjectImp(Instance*);
+        ~QtRuntimeObjectImp();
+        virtual void invalidate();
+    protected:
+        void removeFromCache();
+};
+
+QtRuntimeObjectImp::QtRuntimeObjectImp(Instance* instance)
+    : RuntimeObjectImp(instance)
+{
+}
+
+QtRuntimeObjectImp::~QtRuntimeObjectImp()
 {
+    removeFromCache();
 }
 
-QtInstance::~QtInstance() 
+void QtRuntimeObjectImp::invalidate()
 {
+    removeFromCache();
+    RuntimeObjectImp::invalidate();
 }
 
-QtInstance::QtInstance(const QtInstance& other)
-    : Instance(other.rootObject()), _class(0), _object(other._object)
+void QtRuntimeObjectImp::removeFromCache()
 {
+    JSLock lock;
+    QtInstance* key = cachedObjects.key(this);
+    if (key)
+        cachedObjects.remove(key);
 }
 
-QtInstance& QtInstance::operator=(const QtInstance& other)
+// QtInstance
+QtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
+    : Instance(rootObject)
+    , _class(0)
+    , _object(o)
+    , _hashkey(o)
 {
-    if (this == &other)
-        return *this;
+}
 
-    _object = other._object;
-    _class = 0;
+QtInstance::~QtInstance()
+{
+    JSLock lock;
+    cachedObjects.remove(this);
+    cachedInstances.remove(_hashkey);
+}
 
-    return *this;
+QtInstance* QtInstance::getQtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
+{
+    JSLock lock;
+
+    foreach(QtInstance* instance, cachedInstances.values(o)) {
+        if (instance->rootObject() == rootObject)
+            return instance;
+    }
+
+    QtInstance* ret = new QtInstance(o, rootObject);
+    cachedInstances.insert(o, ret);
+
+    return ret;
+}
+
+JSObject* QtInstance::getRuntimeObject(QtInstance* instance)
+{
+    JSLock lock;
+    JSObject* ret = cachedObjects.value(instance);
+    if (!ret) {
+        ret = new QtRuntimeObjectImp(instance);
+        cachedObjects.insert(instance, ret);
+    }
+    return ret;
 }
 
 Class* QtInstance::getClass() const
index f5be9de6000854ace8ab454c49fcfdb651f7c6fd..5449d583b3c5550894a218209ac5ee4569e31cdb 100644 (file)
@@ -35,16 +35,10 @@ class QtClass;
 class QtInstance : public Instance
 {
 public:
-    QtInstance(QObject* instance, PassRefPtr<RootObject>);
-        
     ~QtInstance ();
     
     virtual Class* getClass() const;
     
-    QtInstance (const QtInstance &other);
-
-    QtInstance &operator=(const QtInstance &other);
-    
     virtual void begin();
     virtual void end();
     
@@ -62,9 +56,16 @@ public:
     
     QObject* getObject() const { return _object; }
 
+    virtual BindingLanguage getBindingLanguage() const { return QtLanguage; }
+
+    static QtInstance* getQtInstance(QObject*, PassRefPtr<RootObject>);
+    static JSObject* getRuntimeObject(QtInstance*);
+
 private:
+    QtInstance(QObject*, PassRefPtr<RootObject>); // Factory produced only..
     mutable QtClass* _class;
     QPointer<QObject> _object;
+    QObject* _hashkey;
 };
 
 } // namespace Bindings
index 2a2fa48c21120de2e03b23f601d2fce217ae034c..26d9e7687c105bdf94a7c896eee8ec289285460f 100644 (file)
@@ -105,7 +105,7 @@ Instance* Instance::createBindingForLanguageInstance(BindingLanguage language, v
 #endif
 #if PLATFORM(QT)
         case Instance::QtLanguage: {
-            newInstance = new Bindings::QtInstance((QObject *)nativeInstance, rootObject);
+            newInstance = Bindings::QtInstance::getQtInstance((QObject *)nativeInstance, rootObject);
             break;
         }
 #endif
@@ -119,13 +119,36 @@ Instance* Instance::createBindingForLanguageInstance(BindingLanguage language, v
 JSObject* Instance::createRuntimeObject(BindingLanguage language, void* nativeInstance, PassRefPtr<RootObject> rootObject)
 {
     Instance* instance = Instance::createBindingForLanguageInstance(language, nativeInstance, rootObject);
-    
+
+    return createRuntimeObject(instance);
+}
+
+JSObject* Instance::createRuntimeObject(Instance* instance)
+{
+#if PLATFORM(QT)
+    if (instance->getBindingLanguage() == QtLanguage)
+        return QtInstance::getRuntimeObject(static_cast<QtInstance*>(instance));
+#endif
     JSLock lock;
     return new RuntimeObjectImp(instance);
 }
 
-RootObject* Instance::rootObject() const 
-{ 
+Instance* Instance::getInstance(JSObject* object, BindingLanguage language)
+{
+    if (!object)
+        return 0;
+    if (!object->inherits(&RuntimeObjectImp::info))
+        return 0;
+    Instance* instance = (static_cast<RuntimeObjectImp*>(object))->getInternalInstance();
+    if (!instance)
+        return 0;
+    if (instance->getBindingLanguage() != language)
+        return 0;
+    return instance;
+}
+
+RootObject* Instance::rootObject() const
+{
     return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
 }
 
index 6e52c9e71c8fd834818cb95dfcfe40236a457621..dbb324c64e44ceaca5f848fbd1cf0a95f9238021 100644 (file)
@@ -101,6 +101,9 @@ public:
     
     static Instance* createBindingForLanguageInstance(BindingLanguage, void* nativeInstance, PassRefPtr<RootObject>);
     static JSObject* createRuntimeObject(BindingLanguage, void* nativeInstance, PassRefPtr<RootObject>);
+    static JSObject* createRuntimeObject(Instance*);
+
+    static Instance* getInstance(JSObject*, BindingLanguage);
 
     void ref() { _refCount++; }
     void deref() 
@@ -138,6 +141,8 @@ public:
     
     virtual ~Instance();
 
+    virtual BindingLanguage getBindingLanguage() const = 0;
+
 protected:
     RefPtr<RootObject> _rootObject;
     unsigned _refCount;
index d0e06be095abb93d40ea13550cb8f3c3a9869084..0ce7d7494b30a691069db9c30b5d87b76110d581 100644 (file)
@@ -35,7 +35,6 @@ namespace KJS {
 
 class RuntimeObjectImp : public JSObject {
 public:
-    RuntimeObjectImp(Bindings::Instance *i);
     virtual ~RuntimeObjectImp();
     
     const ClassInfo *classInfo() const { return &info; }
@@ -49,13 +48,17 @@ public:
     virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
     virtual void getPropertyNames(ExecState*, PropertyNameArray&);
 
-    void invalidate();
+    virtual void invalidate();
     Bindings::Instance *getInternalInstance() const { return instance.get(); }
     
     static JSObject* throwInvalidAccessError(ExecState*);
     
     static const ClassInfo info;
 
+protected:
+    friend class Bindings::Instance;
+    RuntimeObjectImp(Bindings::Instance*); // Only allow Instances and derived classes to create us
+
 private:
     RuntimeObjectImp(); // prevent default construction
     
index 5135c3c7fd4d247d5560f75f96a6cb255e860b2a..07bc8075612d146140e14bfaeb6ea8dd1255e7ec 100644 (file)
@@ -1,3 +1,15 @@
+2008-01-13  Michael Goddard  <michael.goddard@trolltech.com>
+
+        Reviewed by Anders Carlsson.
+
+        Move RuntimeObjectImp creations into Instance.
+        Make the ctor protected, and Instance a friend class, so
+        that all creation of RuntimeObjectImps goes through
+        one place.
+
+        * bindings/js/kjs_dom.cpp:
+        (WebCore::getRuntimeObject):
+
 2008-01-12  Rodney Dawes  <dobey@wayofthemonkey.com>
 
         Gtk debug build fix.  Reviewed by Mark Rowe.
index 4c747aa5348547b3f3af44a43a91d3f478384cd5..fad4406500627a1aed9c8c1cdae05f1e344dabd4 100644 (file)
@@ -102,7 +102,7 @@ JSValue* getRuntimeObject(ExecState* exec, Node* n)
         HTMLPlugInElement* plugInElement = static_cast<HTMLPlugInElement*>(n);
         if (plugInElement->getInstance() && plugInElement->getInstance()->rootObject())
             // The instance is owned by the PlugIn element.
-            return new RuntimeObjectImp(plugInElement->getInstance());
+            return KJS::Bindings::Instance::createRuntimeObject(plugInElement->getInstance());
     }
 #endif