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 d18d4d4..44bf6ba 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 856d7fc..2abb63d 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 c011911..9991a18 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 e6e6120..eb89e3f 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 f694f68..347f24f 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 1eeffd7..2233791 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 22c6e9d..294d282 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 f5be9de..5449d58 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 2a2fa48..26d9e76 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 6e52c9e..dbb324c 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 d0e06be..0ce7d74 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 5135c3c..07bc807 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 4c747aa..fad4406 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