[xpcom] Try to avoid unnecessary conversions to nsIVariant
authorKalle Vahlman <kalle.vahlman@movial.com>
Thu, 23 Apr 2009 08:19:57 +0000 (11:19 +0300)
committerKalle Vahlman <kalle.vahlman@movial.com>
Thu, 23 Apr 2009 09:13:32 +0000 (12:13 +0300)
xpcom-dbusservice/DBusMarshaling.cpp

index d5a5e718ef3710e451ca73d6ad3d9c39218bd405..69c1f0d11e7f7472704be862fb16033227f29531 100644 (file)
@@ -807,32 +807,27 @@ void addArrayDataToIter(JSContext* cx, void *data_ptr, PRUint32 start, PRUint32
             nsISupports **data = (nsISupports **)data_ptr;
             for (PRUint32 i = 0; i < count; i++)
             {
-                // We might have a variant
-                nsCOMPtr<nsIVariant> variant = do_QueryInterface(data[i]);
 
-                if (variant) {
-                    addVariantToIter(cx, variant, aIter, &childSigIter);
-
-                    /* Advance the signature iter or reset */
-                    if (!dbus_signature_iter_next(&childSigIter))
-                        dbus_signature_iter_recurse(containerSigIter, &childSigIter);
-
-                }
-
-                // We might have a wrapped JS object in the variant
+                // We might have a wrapped JS object in the nsISupports
                 // eg. dicts
                 nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(data[i]);
 
-                if (!wrapped)
-                    continue;
+                if (wrapped) {
+                    JSObject *js_obj = nsnull;
+                    if (!NS_SUCCEEDED(wrapped->GetJSObject(&js_obj)))
+                        continue;
 
-                JSObject *js_obj = nsnull;
-                if (!NS_SUCCEEDED(wrapped->GetJSObject(&js_obj)))
-                    continue;
+                    jsval js_obj_as_value = OBJECT_TO_JSVAL(js_obj);
+                    addJSValueToIter(cx, &js_obj_as_value,
+                                        aIter, &childSigIter);
+                } else {
 
-                jsval js_obj_as_value = OBJECT_TO_JSVAL(js_obj);
-                addJSValueToIter(cx, &js_obj_as_value,
-                                    aIter, &childSigIter);
+                    // We might have a variant
+                    nsCOMPtr<nsIVariant> variant = do_QueryInterface(data[i]);
+
+                    if (variant)
+                        addVariantToIter(cx, variant, aIter, &childSigIter);
+                }
 
                 /* Advance the signature iter or reset */
                 if (!dbus_signature_iter_next(&childSigIter))
@@ -914,8 +909,45 @@ addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSigna
         }
         case DBUS_TYPE_ARRAY:
         {
-            if (JSVAL_IS_OBJECT(*aValue)) {
-                // Arrays and dicts are simply converted to variants and pushed
+            if (!JSVAL_IS_OBJECT(*aValue))
+                break;
+
+            if (JS_IsArrayObject(cx, JSVAL_TO_OBJECT(*aValue))) {
+                // We iterate the JS arrays here to (potentially) avoid
+                // extra conversions to variants
+
+                JSObject *array = JSVAL_TO_OBJECT(*aValue);
+                jsuint length = 0;
+                if (!JS_GetArrayLength(cx, array, &length))
+                    break;
+
+                DBusSignatureIter aChildSigIter;
+                dbus_signature_iter_recurse(aSigIter, &aChildSigIter);
+
+                char *array_signature = dbus_signature_iter_get_signature(&aChildSigIter);
+
+                BDBLOG(("  %s: got array signature %s\n", __FUNCTION__, array_signature));
+
+                DBusMessageIter arrayIter;
+                if (!dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
+                                                        array_signature, &arrayIter))
+                {
+                    dbus_free(array_signature);
+                    break;
+                }
+                dbus_free(array_signature);
+
+                for (int e = 0; e < length; e++)
+                {
+                    jsval ev;
+                    if (JS_GetElement(cx, array, e, &ev))
+                        addJSValueToIter(cx, &ev, &arrayIter, &aChildSigIter);
+                }
+
+                dbus_message_iter_close_container(aIter, &arrayIter);
+
+            } else {
+                // non-array JS objects are converted to variants and pushed
                 // to the variant code path
                 nsresult rv;
                 nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));