2006-08-22 Anders Carlsson <acarlsson@apple.com>
authorandersca <andersca@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 Aug 2006 21:05:47 +0000 (21:05 +0000)
committerandersca <andersca@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 Aug 2006 21:05:47 +0000 (21:05 +0000)
        Reviewed by Darin.

        Move the npruntime code over to using HashMap and the runtime_root code over to using
        HashMap and HashCountedSet.

        * bindings/NP_jsobject.cpp:
        * bindings/c/c_utility.cpp:
        (KJS::Bindings::identifierFromNPIdentifier):
        * bindings/c/c_utility.h:
        * bindings/jni/jni_jsobject.cpp:
        (JavaJSObject::invoke):
        * bindings/npruntime.cpp:
        (getStringIdentifierMap):
        (getIntIdentifierMap):
        (_NPN_GetStringIdentifier):
        (_NPN_GetIntIdentifier):
        * bindings/runtime_root.cpp:
        (getReferencesByRootMap):
        (getReferencesSet):
        (KJS::Bindings::findReferenceSet):
        (KJS::Bindings::rootForImp):
        (KJS::Bindings::rootForInterpreter):
        (KJS::Bindings::addNativeReference):
        (KJS::Bindings::removeNativeReference):
        (RootObject::removeAllNativeReferences):
        * bindings/runtime_root.h:

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

JavaScriptCore/ChangeLog
JavaScriptCore/bindings/NP_jsobject.cpp
JavaScriptCore/bindings/c/c_utility.cpp
JavaScriptCore/bindings/c/c_utility.h
JavaScriptCore/bindings/jni/jni_jsobject.cpp
JavaScriptCore/bindings/npruntime.cpp
JavaScriptCore/bindings/runtime_root.cpp
JavaScriptCore/bindings/runtime_root.h

index d55a35aa00806773045942775d6384d7ed14bac8..4b109f811ba565f189ad5312c11f11b726542abb 100644 (file)
@@ -1,3 +1,32 @@
+2006-08-22  Anders Carlsson  <acarlsson@apple.com>
+
+        Reviewed by Darin.
+
+        Move the npruntime code over to using HashMap and the runtime_root code over to using 
+        HashMap and HashCountedSet.
+        
+        * bindings/NP_jsobject.cpp:
+        * bindings/c/c_utility.cpp:
+        (KJS::Bindings::identifierFromNPIdentifier):
+        * bindings/c/c_utility.h:
+        * bindings/jni/jni_jsobject.cpp:
+        (JavaJSObject::invoke):
+        * bindings/npruntime.cpp:
+        (getStringIdentifierMap):
+        (getIntIdentifierMap):
+        (_NPN_GetStringIdentifier):
+        (_NPN_GetIntIdentifier):
+        * bindings/runtime_root.cpp:
+        (getReferencesByRootMap):
+        (getReferencesSet):
+        (KJS::Bindings::findReferenceSet):
+        (KJS::Bindings::rootForImp):
+        (KJS::Bindings::rootForInterpreter):
+        (KJS::Bindings::addNativeReference):
+        (KJS::Bindings::removeNativeReference):
+        (RootObject::removeAllNativeReferences):
+        * bindings/runtime_root.h:
+
 2006-08-22  Anders Carlsson  <acarlsson@apple.com>
 
         Reviewed by Geoff.
index a64bc038ed74ad00069dd46b35deba1e26c35b9e..647dabc5fcb08c986592377b8e6764c1fb722307 100644 (file)
@@ -59,16 +59,6 @@ static NPClass noScriptClass = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 NPClass* NPScriptObjectClass = &javascriptClass;
 static NPClass* NPNoScriptObjectClass = &noScriptClass;
 
-static Identifier identifierFromNPIdentifier(const NPUTF8* name)
-{
-    NPUTF16 *methodName;
-    unsigned UTF16Length;
-    convertUTF8ToUTF16(name, -1, &methodName, &UTF16Length); // requires free() of returned memory.
-    Identifier identifier((const KJS::UChar*)methodName, UTF16Length);
-    free(methodName);
-    return identifier;
-}
-
 static bool _isSafeScript(JavaScriptObject* obj)
 {
     if (obj->originExecutionContext) {
index fe019a49762d43d4966c0c33ce75e37e3ebdd19e..929cfb930e35022c5ed217901c2b767ad708f000 100644 (file)
@@ -180,4 +180,14 @@ JSValue *convertNPVariantToValue(ExecState*, const NPVariant* variant)
     return jsUndefined();
 }
 
+Identifier identifierFromNPIdentifier(const NPUTF8* name)
+{
+    NPUTF16 *methodName;
+    unsigned UTF16Length;
+    convertUTF8ToUTF16(name, -1, &methodName, &UTF16Length); // requires free() of returned memory.
+    Identifier identifier((const KJS::UChar*)methodName, UTF16Length);
+    free(methodName);
+    return identifier;
+}
+
 } }
index 49b8d60907cffb250bb6617c7803edbc203b31f9..2f704a8fe9145c11ea50e5071b8f9e5187f5490e 100644 (file)
@@ -31,6 +31,7 @@
 namespace KJS {
 
 class ExecState;
+class Identifier;
 class JSValue;
 
 namespace Bindings {
@@ -52,6 +53,7 @@ void convertUTF8ToUTF16(const NPUTF8* UTF8Chars, int UTF8Length, NPUTF16** UTF16
 void coerceValueToNPVariantStringType(ExecState*, JSValue*, NPVariant* result);
 void convertValueToNPVariant(ExecState*, JSValue*, NPVariant* result);
 JSValue* convertNPVariantToValue(ExecState*, const NPVariant*);
+Identifier identifierFromNPIdentifier(const NPUTF8* name);
 
 struct PrivateIdentifier {
     union {
index e9231c4df2fbe54f8d0ce1327d22b2462ef3a1e0..87b92bacec1cbf190faad4d616803e360be626f7 100644 (file)
@@ -127,7 +127,7 @@ jvalue JavaJSObject::invoke (JSObjectCallContext *context)
     
                 case Finalize: {
                     JSObject *imp = jlong_to_impptr(nativeHandle);
-                    if (findReferenceDictionary(imp) == 0) {
+                    if (findReferenceSet(imp) == 0) {
                         // We may have received a finalize method call from the VM 
                         // AFTER removing our last reference to the Java instance.
                         JS_LOG ("finalize called on instance we have already removed.\n");
index 7cbc2a7ab6c336af716b71b8339a216b83924fcb..c5619830a88cafed6f31d7d1564925a2a87515be 100644 (file)
 #include "npruntime_priv.h"
 
 #include "c_utility.h"
-#include <CoreFoundation/CoreFoundation.h>
-
-// FIXME: Use HashMap instead of CFDictionary for better performance and portability.
+#include <wtf/HashMap.h>
+#include "identifier.h"
 
 using namespace KJS::Bindings;
 
-static Boolean stringIdentifierEqual(const void* value1, const void* value2)
-{
-    return strcmp((const char*)value1, (const char*)value2) == 0;
-}
+typedef HashMap<RefPtr<KJS::UString::Rep>, PrivateIdentifier*> StringIdentifierMap;
 
-static CFHashCode stringIdentifierHash(const void* value)
+static StringIdentifierMap* getStringIdentifierMap()
 {
-    const unsigned char* key = (const unsigned char*)value;
-    unsigned len = strlen((const char*)key);
-    unsigned result = len;
-
-    if (len <= 16) {
-        unsigned cnt = len;
-        while (cnt--)
-            result = result * 257 + *key++;
-    } else {
-        unsigned cnt;
-        for (cnt = 8; cnt > 0; cnt--)
-            result = result * 257 + *key++;
-        key += (len - 16);
-        for (cnt = 8; cnt > 0; cnt--)
-            result = result * 257 + *key++;
-    }
-    result += (result << (len & 31));
-
-    return result;
+    static StringIdentifierMap* stringIdentifierMap = 0;
+    if (!stringIdentifierMap)
+        stringIdentifierMap = new StringIdentifierMap;
+    return stringIdentifierMap;
 }
 
-static CFMutableDictionaryRef getStringIdentifierDictionary()
-{
-    static CFMutableDictionaryRef stringIdentifierDictionary = 0;
-    if (!stringIdentifierDictionary) {
-        CFDictionaryKeyCallBacks stringIdentifierCallbacks = { 0, NULL, NULL, NULL, stringIdentifierEqual, stringIdentifierHash };
-        stringIdentifierDictionary = CFDictionaryCreateMutable(NULL, 0, &stringIdentifierCallbacks, NULL);
-    }
-    return stringIdentifierDictionary;
-}
+typedef HashMap<int, PrivateIdentifier*> IntIdentifierMap;
 
-static CFMutableDictionaryRef getIntIdentifierDictionary()
+static IntIdentifierMap* getIntIdentifierMap()
 {
-    static CFMutableDictionaryRef intIdentifierDictionary = 0;
-    if (!intIdentifierDictionary)
-        intIdentifierDictionary = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
-    return intIdentifierDictionary;
+    static IntIdentifierMap* intIdentifierMap = 0;
+    if (!intIdentifierMap)
+        intIdentifierMap = new IntIdentifierMap;
+    return intIdentifierMap;
 }
 
 NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name)
@@ -88,16 +61,15 @@ NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name)
     if (name) {
         PrivateIdentifier* identifier = 0;
         
-        identifier = (PrivateIdentifier*)CFDictionaryGetValue(getStringIdentifierDictionary(), name);
+        identifier = getStringIdentifierMap()->get(identifierFromNPIdentifier(name).ustring().rep());
         if (identifier == 0) {
             identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
             // We never release identifier names, so this dictionary will grow, as will
             // the memory for the identifier name strings.
             identifier->isString = true;
-            const char* identifierName = strdup(name);
-            identifier->value.string = identifierName;
+            identifier->value.string = strdup(name);
 
-            CFDictionaryAddValue(getStringIdentifierDictionary(), identifierName, identifier);
+            getStringIdentifierMap()->set(identifierFromNPIdentifier(name).ustring().rep(), identifier);
         }
         return (NPIdentifier)identifier;
     }
@@ -119,14 +91,14 @@ NPIdentifier _NPN_GetIntIdentifier(int32_t intid)
 {
     PrivateIdentifier* identifier = 0;
     
-    identifier = (PrivateIdentifier*)CFDictionaryGetValue(getIntIdentifierDictionary(), (const void*)intid);
+    identifier = getIntIdentifierMap()->get(intid);
     if (identifier == 0) {
         identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
         // We never release identifier names, so this dictionary will grow.
         identifier->isString = false;
         identifier->value.number = intid;
 
-        CFDictionaryAddValue(getIntIdentifierDictionary(), (const void*)intid, identifier);
+        getIntIdentifierMap()->set(intid, identifier);
     }
     return (NPIdentifier)identifier;
 }
index 2ef795c3ff832f87c178b3b1cc5acde6794887ec..73516318557c7fba98acfc8b6daa0d0f2748e4da 100644 (file)
@@ -26,6 +26,7 @@
 #include "jni_jsobject.h"
 #include "object.h"
 #include "runtime_root.h"
+#include <wtf/HashCountedSet.h>
 
 using namespace KJS;
 using namespace KJS::Bindings;
@@ -38,33 +39,35 @@ using namespace KJS::Bindings;
 // the last JavaJSObject that refers to it is finalized, or when the applet is
 // shutdown.
 //
-// To do this we keep a dictionary that maps each applet instance
+// To do this we keep a map that maps each applet instance
 // to the JavaScript objects it is referencing.  For each JavaScript instance
 // we also maintain a secondary reference count.  When that reference count reaches
 // 1 OR the applet is shutdown we deref the JavaScript instance.  Applet instances
 // are represented by a jlong.
 
-static CFMutableDictionaryRef referencesByRootDictionary = 0;
+typedef HashMap<const Bindings::RootObject*, ReferencesSet*> ReferencesByRootMap; 
 
-static CFMutableDictionaryRef getReferencesByRootDictionary()
+static ReferencesByRootMap* getReferencesByRootMap()
 {
-    if (!referencesByRootDictionary)
-        referencesByRootDictionary = CFDictionaryCreateMutable(NULL, 0, NULL, &kCFTypeDictionaryValueCallBacks);
-    return referencesByRootDictionary;
+    static ReferencesByRootMap* referencesByRootMap = 0;
+    
+    if (!referencesByRootMap)
+        referencesByRootMap = new ReferencesByRootMap;
+    
+    return referencesByRootMap;
 }
 
-static CFMutableDictionaryRef getReferencesDictionary(const Bindings::RootObject *root)
+static ReferencesSet* getReferencesSet(const Bindings::RootObject *root)
 {
-    CFMutableDictionaryRef refsByRoot = getReferencesByRootDictionary();
-    CFMutableDictionaryRef referencesDictionary = 0;
+    ReferencesByRootMap* refsByRoot = getReferencesByRootMap();
+    ReferencesSet* referencesSet = 0;
     
-    referencesDictionary = (CFMutableDictionaryRef)CFDictionaryGetValue (refsByRoot, (const void *)root);
-    if (!referencesDictionary) {
-        referencesDictionary = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
-        CFDictionaryAddValue (refsByRoot, root, referencesDictionary);
-        CFRelease (referencesDictionary);
+    referencesSet = refsByRoot->get(root);
+    if (!referencesSet) {
+        referencesSet  = new ReferencesSet;
+        refsByRoot->add(root, referencesSet);
     }
-    return referencesDictionary;
+    return referencesSet;
 }
 
 // Scan all the dictionary for all the roots to see if any have a 
@@ -72,103 +75,71 @@ static CFMutableDictionaryRef getReferencesDictionary(const Bindings::RootObject
 // dictionary.
 // FIXME:  This is a potential performance bottleneck with many applets.  We could fix be adding a
 // imp to root dictionary.
-CFMutableDictionaryRef KJS::Bindings::findReferenceDictionary(JSObject *imp)
+ReferencesSet* KJS::Bindings::findReferenceSet(JSObject *imp)
 {
-    CFMutableDictionaryRef refsByRoot = getReferencesByRootDictionary ();
-    CFMutableDictionaryRef foundDictionary = 0;
-    
+    ReferencesByRootMap* refsByRoot = getReferencesByRootMap ();
     if (refsByRoot) {
-        const void **allValues = 0;
-        CFIndex count, i;
-        
-        count = CFDictionaryGetCount(refsByRoot);
-        allValues = (const void **)malloc (sizeof(void *) * count);
-        CFDictionaryGetKeysAndValues (refsByRoot, NULL, allValues);
-        for(i = 0; i < count; i++) {
-            CFMutableDictionaryRef referencesDictionary = (CFMutableDictionaryRef)allValues[i];
-            if (CFDictionaryGetValue(referencesDictionary, imp) != 0) {
-                foundDictionary = referencesDictionary;
-                break;
-            }
+        ReferencesByRootMap::const_iterator end = refsByRoot->end();
+        for (ReferencesByRootMap::const_iterator it = refsByRoot->begin(); it != end; ++it) {
+            ReferencesSet* set = it->second;
+            
+            if (set->contains(imp))
+                return set;
         }
-        
-        free ((void *)allValues);
     }
-    return foundDictionary;
+    
+    return 0;
 }
 
 // FIXME:  This is a potential performance bottleneck with many applets.  We could fix be adding a
 // imp to root dictionary.
 const Bindings::RootObject *KJS::Bindings::rootForImp (JSObject *imp)
 {
-    CFMutableDictionaryRef refsByRoot = getReferencesByRootDictionary ();
+    ReferencesByRootMap* refsByRoot = getReferencesByRootMap ();
     const Bindings::RootObject *rootObject = 0;
     
     if (refsByRoot) {
-        const void **allValues = 0;
-        const void **allKeys = 0;
-        CFIndex count, i;
-        
-        count = CFDictionaryGetCount(refsByRoot);
-        allKeys = (const void **)malloc (sizeof(void *) * count);
-        allValues = (const void **)malloc (sizeof(void *) * count);
-        CFDictionaryGetKeysAndValues (refsByRoot, allKeys, allValues);
-        for(i = 0; i < count; i++) {
-            CFMutableDictionaryRef referencesDictionary = (CFMutableDictionaryRef)allValues[i];
-            if (CFDictionaryGetValue(referencesDictionary, imp) != 0) {
-                rootObject = (const Bindings::RootObject *)allKeys[i];
+        ReferencesByRootMap::const_iterator end = refsByRoot->end();
+        for (ReferencesByRootMap::const_iterator it = refsByRoot->begin(); it != end; ++it) {
+            ReferencesSet* set = it->second;
+            if (set->contains(imp)) {
+                rootObject = it->first;
                 break;
             }
         }
-        
-        free ((void *)allKeys);
-        free ((void *)allValues);
     }
+    
     return rootObject;
 }
 
 const Bindings::RootObject *KJS::Bindings::rootForInterpreter (KJS::Interpreter *interpreter)
 {
-    CFMutableDictionaryRef refsByRoot = getReferencesByRootDictionary ();
-    const Bindings::RootObject *aRootObject = 0, *result = 0;
+    ReferencesByRootMap* refsByRoot = getReferencesByRootMap ();
     
     if (refsByRoot) {
-        const void **allValues = 0;
-        const void **allKeys = 0;
-        CFIndex count, i;
-        
-        count = CFDictionaryGetCount(refsByRoot);
-        allKeys = (const void **)malloc (sizeof(void *) * count);
-        allValues = (const void **)malloc (sizeof(void *) * count);
-        CFDictionaryGetKeysAndValues (refsByRoot, allKeys, allValues);
-        for(i = 0; i < count; i++) {
-            aRootObject = (const Bindings::RootObject *)allKeys[i];
-            if (aRootObject->interpreter() == interpreter) {
-                result = aRootObject;
-                break;
-            }
+        ReferencesByRootMap::const_iterator end = refsByRoot->end();
+        for (ReferencesByRootMap::const_iterator it = refsByRoot->begin(); it != end; ++it) {
+            const Bindings::RootObject* aRootObject = it->first;
+            
+            if (aRootObject->interpreter() == interpreter)
+                return aRootObject;
         }
-        
-        free ((void *)allKeys);
-        free ((void *)allValues);
     }
-    return result;
+    
+    return 0;
 }
 
 void KJS::Bindings::addNativeReference (const Bindings::RootObject *root, JSObject *imp)
 {
     if (root) {
-        CFMutableDictionaryRef referencesDictionary = getReferencesDictionary (root);
+        ReferencesSet* referenceMap = getReferencesSet (root);
         
-        unsigned long numReferences = (unsigned long)CFDictionaryGetValue (referencesDictionary, imp);
+        unsigned numReferences = referenceMap->count(imp);
         if (numReferences == 0) {
             JSLock lock;
             gcProtect(imp);
-            CFDictionaryAddValue (referencesDictionary, imp,  (const void *)1);
-        }
-        else {
-            CFDictionaryReplaceValue (referencesDictionary, imp, (const void *)(numReferences+1));
         }
+        referenceMap->add(imp);
     }
 }
 
@@ -177,18 +148,15 @@ void KJS::Bindings::removeNativeReference (JSObject *imp)
     if (!imp)
         return;
 
-    CFMutableDictionaryRef referencesDictionary = findReferenceDictionary (imp);
-
-    if (referencesDictionary) {
-        unsigned long numReferences = (unsigned long)CFDictionaryGetValue (referencesDictionary, imp);
+    ReferencesSet *referencesSet = findReferenceSet(imp);
+    if (referencesSet) {
+        unsigned numReferences = referencesSet->count(imp);
+        
         if (numReferences == 1) {
             JSLock lock;
             gcUnprotect(imp);
-            CFDictionaryRemoveValue (referencesDictionary, imp);
-        }
-        else {
-            CFDictionaryReplaceValue (referencesDictionary, imp, (const void *)(numReferences-1));
         }
+        referencesSet->remove(imp);
     }
 }
 
@@ -317,25 +285,18 @@ void RootObject::setFindRootObjectForNativeHandleFunction(FindRootObjectForNativ
 // Must be called when the applet is shutdown.
 void RootObject::removeAllNativeReferences ()
 {
-    CFMutableDictionaryRef referencesDictionary = getReferencesDictionary (this);
+    ReferencesSet* referencesSet = getReferencesSet (this);
     
-    if (referencesDictionary) {
-        void **allImps = 0;
-        CFIndex count, i;
-        
-        count = CFDictionaryGetCount(referencesDictionary);
-        allImps = (void **)malloc (sizeof(void *) * count);
-        CFDictionaryGetKeysAndValues (referencesDictionary, (const void **)allImps, NULL);
-        for(i = 0; i < count; i++) {
+    if (referencesSet) {
+        ReferencesSet::iterator end = referencesSet->end();
+        for (ReferencesSet::iterator it = referencesSet->begin(); it != end; ++it) {
             JSLock lock;
-            JSObject *anImp = static_cast<JSObject*>(allImps[i]);
-            gcUnprotect(anImp);
+            gcUnprotect(it->first);            
         }
-        free ((void *)allImps);
-        CFDictionaryRemoveAllValues (referencesDictionary);
-
-        CFMutableDictionaryRef refsByRoot = getReferencesByRootDictionary();
-        CFDictionaryRemoveValue (refsByRoot, (const void *)this);
+        referencesSet->clear();
+        ReferencesByRootMap* refsByRoot = getReferencesByRootMap();
+        refsByRoot->remove(this);
+        delete referencesSet;
         delete this;
     }
 }
index 3fa1b0d2260957e5f608c67705c4a98defbdd7f1..2d3585a0cb6ef820c194bfa35a5811f1d4a55a5f 100644 (file)
@@ -37,8 +37,9 @@ namespace Bindings {
 class RootObject;
 
 typedef RootObject *(*FindRootObjectForNativeHandleFunctionPtr)(void *);
+typedef HashCountedSet<JSObject*> ReferencesSet;
 
-extern CFMutableDictionaryRef findReferenceDictionary(JSObject *imp);
+extern ReferencesSet* findReferenceSet(JSObject *imp);
 extern const RootObject *rootForImp (JSObject *imp);
 extern const RootObject *rootForInterpreter (Interpreter *interpreter);
 extern void addNativeReference (const RootObject *root, JSObject *imp);