[gjs/april-maintenance: 6/11] js: Avoid appending to vectors in a loop



commit 18fb56029b504997a00d07ed3e01a0d742d9e43a
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Apr 28 17:59:35 2020 -0700

    js: Avoid appending to vectors in a loop
    
    Where possible, use Mozilla's vector methods to append and initialize a
    bunch of elements at once, or reserve capacity and then append
    infallibly. This avoids reallocating memory for the vectors inside a
    loop.

 gi/function.cpp  |  5 ++---
 gi/object.cpp    | 40 ++++++++++++++++++++--------------------
 gi/value.cpp     |  3 +--
 gjs/importer.cpp | 10 ++++------
 4 files changed, 27 insertions(+), 31 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index fd71934a..e82b8f93 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -1147,9 +1147,8 @@ gjs_invoke_c_function(JSContext                             *context,
 
     /* Only process return values if the function didn't throw */
     if (function->js_out_argc > 0 && !did_throw_gerror) {
-        for (size_t i = 0; i < function->js_out_argc; i++)
-            if (!return_values.append(JS::UndefinedValue()))
-                g_error("Unable to append to vector");
+        if (!return_values.growBy(function->js_out_argc))
+            g_error("Unable to reserve space for vector");
 
         if (return_tag != GI_TYPE_TAG_VOID) {
             GITransfer transfer = g_callable_info_get_caller_owns((GICallableInfo*) function->info);
diff --git a/gi/object.cpp b/gi/object.cpp
index e0480602..6c861846 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -934,8 +934,15 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject,
             continue;
         }
 
-        // Methods
         int n_methods = g_interface_info_get_n_methods(iface_info);
+        int n_properties = g_interface_info_get_n_properties(iface_info);
+        if (!properties.reserve(properties.length() + n_methods +
+                                n_properties)) {
+            JS_ReportOutOfMemory(cx);
+            return false;
+        }
+
+        // Methods
         for (int i = 0; i < n_methods; i++) {
             GjsAutoFunctionInfo meth_info =
                 g_interface_info_get_method(iface_info, i);
@@ -946,15 +953,11 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject,
                 jsid id = gjs_intern_string_to_id(cx, name);
                 if (id == JSID_VOID)
                     return false;
-                if (!properties.append(id)) {
-                    JS_ReportOutOfMemory(cx);
-                    return false;
-                }
+                properties.infallibleAppend(id);
             }
         }
 
         // Properties
-        int n_properties = g_interface_info_get_n_properties(iface_info);
         for (int i = 0; i < n_properties; i++) {
             GjsAutoPropertyInfo prop_info =
                 g_interface_info_get_property(iface_info, i);
@@ -964,18 +967,22 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject,
             jsid id = gjs_intern_string_to_id(cx, js_name);
             if (id == JSID_VOID)
                 return false;
-            if (!properties.append(id)) {
-                JS_ReportOutOfMemory(cx);
-                return false;
-            }
+            properties.infallibleAppend(id);
         }
     }
 
     g_free(interfaces);
 
     if (info()) {
-        // Methods
         int n_methods = g_object_info_get_n_methods(info());
+        int n_properties = g_object_info_get_n_properties(info());
+        if (!properties.reserve(properties.length() + n_methods +
+                                n_properties)) {
+            JS_ReportOutOfMemory(cx);
+            return false;
+        }
+
+        // Methods
         for (int i = 0; i < n_methods; i++) {
             GjsAutoFunctionInfo meth_info = g_object_info_get_method(info(), i);
             GIFunctionInfoFlags flags = g_function_info_get_flags(meth_info);
@@ -985,15 +992,11 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject,
                 jsid id = gjs_intern_string_to_id(cx, name);
                 if (id == JSID_VOID)
                     return false;
-                if (!properties.append(id)) {
-                    JS_ReportOutOfMemory(cx);
-                    return false;
-                }
+                properties.infallibleAppend(id);
             }
         }
 
         // Properties
-        int n_properties = g_object_info_get_n_properties(info());
         for (int i = 0; i < n_properties; i++) {
             GjsAutoPropertyInfo prop_info =
                 g_object_info_get_property(info(), i);
@@ -1002,10 +1005,7 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject,
             jsid id = gjs_intern_string_to_id(cx, js_name);
             if (id == JSID_VOID)
                 return false;
-            if (!properties.append(id)) {
-                JS_ReportOutOfMemory(cx);
-                return false;
-            }
+            properties.infallibleAppend(id);
         }
     }
 
diff --git a/gi/value.cpp b/gi/value.cpp
index 1b7cbbdb..580797da 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -280,8 +280,7 @@ closure_marshal(GClosure        *closure,
             return;
         }
 
-        if (!argv.append(argv_to_append))
-            g_error("Unable to append to vector");
+        argv.infallibleAppend(argv_to_append);
     }
 
     for (i = 1; i < n_param_values; i++)
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index ba07beb4..6a43b76c 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -399,7 +399,6 @@ GJS_JSAPI_RETURN_CONVENTION
 static bool load_module_elements(JSContext* cx, JS::HandleObject in_object,
                                  JS::MutableHandleIdVector prop_ids,
                                  const char* init_path) {
-    size_t ix, length;
     JS::RootedObject module_obj(cx, load_module_init(cx, in_object, init_path));
     if (!module_obj)
         return false;
@@ -408,11 +407,10 @@ static bool load_module_elements(JSContext* cx, JS::HandleObject in_object,
     if (!JS_Enumerate(cx, module_obj, &ids))
         return false;
 
-    for (ix = 0, length = ids.length(); ix < length; ix++)
-        if (!prop_ids.append(ids[ix])) {
-            JS_ReportOutOfMemory(cx);
-            return false;
-        }
+    if (!prop_ids.appendAll(ids)) {
+        JS_ReportOutOfMemory(cx);
+        return false;
+    }
 
     return true;
 }


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