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



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

    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.

 gi/function.cpp | 57 ++++++++++++++++++++++++++-------------------------------
 1 file changed, 26 insertions(+), 31 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index da26a33d..931c1192 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -723,7 +723,6 @@ gjs_invoke_c_function(JSContext                             *context,
     bool is_method;
     bool is_object_method = false;
     GITypeTag return_tag;
-    JS::AutoValueVector return_values(context);
     GSList *iter;
 
     /* Because we can't free a closure while we're in it, we defer
@@ -887,10 +886,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
@@ -901,14 +903,27 @@ 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 || js_arg_pos == uint8_t(function->js_out_argc));
@@ -940,29 +955,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) {
         gjs_throw_g_error(context, local_error);


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