[gjs/wip/gcampax/70-arg-cache: 1147/1149] FIXME: function: don't root the out argument locations



commit 30cbf56dab882068b005511c089e91ed53a73906
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sun Apr 21 20:21:40 2013 +0200

    FIXME: function: don't root the out argument locations
    
    Instead, build the array object eagerly if it's know that it will
    be needed, and rely on the stack scanner to find the array itself.
    
    FIXME: No such thing as a stack scanner anymore.

 gi/function.cpp | 58 +++++++++++++++++++++++++++------------------------------
 1 file changed, 27 insertions(+), 31 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index 9263cc34..1b823f6b 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -776,7 +776,6 @@ gjs_invoke_c_function(JSContext                             *context,
     bool is_method;
     bool is_object_method = false;
     GITypeTag return_tag;
-    JS::RootedValueVector return_values(context);
 
     /* Because we can't free a closure while we're in it, we defer
      * freeing until the next time a C function is invoked.  What
@@ -936,10 +935,13 @@ gjs_invoke_c_function(JSContext                             *context,
             &state.out_cvalues[-1]);
     }
 
-    if (function->js_out_argc > 0) {
-        for (size_t i = 0; i < function->js_out_argc; i++)
-            if (!return_values.append(JS::UndefinedValue()))
-                g_error("Unable to append to vector");
+    /* Prepare a JS array that we will fill below in case there is more than
+     * one return value */
+    if (js_rval && function->js_out_argc > 1) {
+        JSObject* out_array = JS_NewArrayObject(context, 0);
+        if (!out_array)
+            return false;
+        js_rval->setObject(*out_array);
     }
 
     // Process out arguments and return values. This loop is skipped if we fail
@@ -950,14 +952,28 @@ gjs_invoke_c_function(JSContext                             *context,
         GjsArgumentCache* cache = &function->arguments[gi_arg_pos];
         GIArgument* out_value = &state.out_cvalues[gi_arg_pos];
 
-        if (!cache->marshal_out(context, cache, &state, out_value,
-                                return_values[js_arg_pos])) {
+        JS::RootedValue value(context);
+        if (!cache->marshal_out(context, cache, &state, out_value, &value)) {
             failed = true;
             break;
         }
 
-        if (!gjs_arg_cache_is_skip_out(cache))
+        if (!gjs_arg_cache_is_skip_out(cache)) {
+            if (js_rval) {
+                /* if we have 1 return value or out arg, return that item on
+                 * its own, otherwise return a JS array with [return value, out
+                 * arg 1, out arg 2, ...] */
+                if (function->js_out_argc == 1) {
+                    js_rval->set(value);
+                } else {
+                    JS::RootedObject js_rval_array(context,
+                                                   &js_rval->toObject());
+                    JS_SetElement(context, js_rval_array, js_arg_pos, value);
+                }
+            }
+
             js_arg_pos++;
+        }
     }
 
     g_assert(failed || did_throw_gerror ||
@@ -992,29 +1008,9 @@ release:
 
     g_assert_cmpuint(ffi_arg_pos, ==, processed_c_args + 1);
 
-    if (function->js_out_argc > 0 && (!failed && !did_throw_gerror)) {
-        /* if we have 1 return value or out arg, return that item
-         * on its own, otherwise return a JavaScript array with
-         * [return value, out arg 1, out arg 2, ...]
-         */
-        if (js_rval) {
-            if (function->js_out_argc == 1) {
-                js_rval.ref().set(return_values[0]);
-            } else {
-                JSObject *array;
-                array = JS_NewArrayObject(context, return_values);
-                if (array == NULL) {
-                    failed = true;
-                } else {
-                    js_rval.ref().setObject(*array);
-                }
-            }
-        }
-
-        if (r_value) {
-            *r_value = state.out_cvalues[-1];
-        }
-    }
+    /* Return a GIArgument for the first return value, if requested */
+    if (r_value && function->js_out_argc > 0 && (!failed && !did_throw_gerror))
+        *r_value = state.out_cvalues[-1];
 
     if (!failed && did_throw_gerror) {
         return gjs_throw_gerror(context, local_error);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]