]> git.kaiwu.me - njs.git/commitdiff
Improved memory footprint of RegExp.prototype.replace().
authorDmitry Volyntsev <xeioex@nginx.com>
Wed, 4 Oct 2023 01:09:06 +0000 (18:09 -0700)
committerDmitry Volyntsev <xeioex@nginx.com>
Wed, 4 Oct 2023 01:09:06 +0000 (18:09 -0700)
src/njs_flathsh.c
src/njs_flathsh.h
src/njs_regexp.c

index 224dd39d9af88af0b278fd8e1349f3e4fd77b491..c823c4660e013fd36703c38c1d358e368916b2fe 100644 (file)
@@ -162,6 +162,15 @@ njs_flathsh_new(njs_flathsh_query_t *fhq)
 }
 
 
+void
+njs_flathsh_destroy(njs_flathsh_t *fh, njs_flathsh_query_t *fhq)
+{
+    njs_flathsh_free(fhq, njs_flathsh_chunk(fh->slot));
+
+    fh->slot = NULL;
+}
+
+
 static njs_flathsh_descr_t *
 njs_flathsh_alloc(njs_flathsh_query_t *fhq, size_t hash_size, size_t elts_size)
 {
index b3d39d2091dc5dae9552a25eb05b05b8e620722b..d347bb81389a0ee4d8b4408d3e394ebaca90a9c9 100644 (file)
@@ -130,6 +130,7 @@ NJS_EXPORT njs_flathsh_elt_t *njs_flathsh_add_elt(njs_flathsh_t *fh,
     njs_flathsh_query_t *fhq);
 
 NJS_EXPORT njs_flathsh_descr_t *njs_flathsh_new(njs_flathsh_query_t *fhq);
+NJS_EXPORT void njs_flathsh_destroy(njs_flathsh_t *fh, njs_flathsh_query_t *fhq);
 
 
 /* Temporary backward compatibility .*/
index 30368f57a80cb7794333264751a1bb92624f8ac3..47a32375d2ab1ff1d3b2caebbff8083543cbdf7f 100644 (file)
@@ -1182,6 +1182,50 @@ done:
 }
 
 
+static void
+njs_regexp_exec_result_free(njs_vm_t *vm, njs_array_t *result)
+{
+    njs_uint_t          n;
+    njs_value_t         *start;
+    njs_flathsh_t       *hash;
+    njs_object_prop_t   *prop;
+    njs_lvlhsh_each_t   lhe;
+    njs_lvlhsh_query_t  lhq;
+
+    if (result->object.fast_array) {
+        start = result->start;
+
+        for (n = 0; n < result->length; n++) {
+            if (start[n].short_string.size == NJS_STRING_LONG) {
+                njs_mp_free(vm->mem_pool, start[n].long_string.data);
+            }
+        }
+    }
+
+    njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
+
+    hash = &result->object.hash;
+
+    for ( ;; ) {
+        prop = njs_flathsh_each(hash, &lhe);
+
+        if (prop == NULL) {
+            break;
+        }
+
+        njs_mp_free(vm->mem_pool, prop);
+    }
+
+
+    lhq.pool = vm->mem_pool;
+    lhq.proto = &njs_object_hash_proto;
+
+    njs_flathsh_destroy(hash, &lhq);
+
+    njs_array_destroy(vm, result);
+}
+
+
 njs_int_t
 njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused, njs_value_t *retval)
@@ -1497,6 +1541,10 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
                                               arguments, ncaptures, &groups,
                                               replace, retval);
 
+            if (njs_object_slots(r)) {
+                njs_regexp_exec_result_free(vm, njs_array(r));
+            }
+
         } else {
             ret = njs_array_expand(vm, array, 0,
                                    njs_is_defined(&groups) ? 3 : 2);
@@ -1517,6 +1565,8 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
                                     arguments, n, retval);
         }
 
+        njs_array_destroy(vm, array);
+
         if (njs_slow_path(ret == NJS_ERROR)) {
             return NJS_ERROR;
         }