[njs] Array iterator functions update.

Igor Sysoev igor at sysoev.ru
Tue Aug 9 12:49:55 UTC 2016


details:   http://hg.nginx.org/njs/rev/2f40b153a7c1
branches:  
changeset: 144:2f40b153a7c1
user:      Igor Sysoev <igor at sysoev.ru>
date:      Tue Aug 09 14:10:21 2016 +0300
description:
Array iterator functions update.

diffstat:

 njs/njs_array.c          |  108 ++++++++++++++++++++++++++--------------------
 njs/test/njs_unit_test.c |    8 +++
 2 files changed, 70 insertions(+), 46 deletions(-)

diffs (290 lines):

diff -r 73b0fd4c2ea6 -r 2f40b153a7c1 njs/njs_array.c
--- a/njs/njs_array.c	Thu Aug 04 16:59:15 2016 +0300
+++ b/njs/njs_array.c	Tue Aug 09 14:10:21 2016 +0300
@@ -37,10 +37,15 @@ typedef struct {
         njs_continuation_t  cont;
         u_char              padding[NJS_CONTINUATION_SIZE];
     } u;
+    /*
+     * This retval value must be aligned so the continuation is padded
+     * to aligned size.
+     */
     njs_value_t             retval;
-    int32_t                 index;
+
+    uint32_t                next_index;
     uint32_t                length;
-} njs_array_next_t;
+} njs_array_iter_t;
 
 
 static njs_ret_t
@@ -57,11 +62,11 @@ static nxt_noinline njs_ret_t njs_array_
 static nxt_noinline njs_ret_t njs_array_prototype_every_cont(njs_vm_t *vm,
     njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
 static nxt_noinline njs_ret_t njs_array_iterator_args(njs_vm_t *vm,
-    njs_value_t * args, nxt_uint_t nargs);
-static nxt_noinline nxt_int_t njs_array_iterator_next(njs_value_t *value,
-    nxt_uint_t n, nxt_uint_t length);
+    njs_value_t *args, nxt_uint_t nargs);
+static nxt_noinline uint32_t njs_array_iterator_next(njs_array_t *array,
+    uint32_t n, uint32_t length);
 static nxt_noinline njs_ret_t njs_array_iterator_apply(njs_vm_t *vm,
-    njs_array_next_t *next, njs_value_t *args, nxt_uint_t nargs);
+    njs_array_iter_t *iter, njs_value_t *args, nxt_uint_t nargs);
 
 
 nxt_noinline njs_array_t *
@@ -778,15 +783,15 @@ njs_array_prototype_for_each(njs_vm_t *v
     njs_index_t unused)
 {
     nxt_int_t         ret;
-    njs_array_next_t  *next;
+    njs_array_iter_t  *iter;
 
     ret = njs_array_iterator_args(vm, args, nargs);
     if (nxt_slow_path(ret != NXT_OK)) {
         return ret;
     }
 
-    next = njs_continuation(vm->frame);
-    next->u.cont.function = njs_array_prototype_for_each_cont;
+    iter = njs_continuation(vm->frame);
+    iter->u.cont.function = njs_array_prototype_for_each_cont;
 
     return njs_array_prototype_for_each_cont(vm, args, nargs, unused);
 }
@@ -796,16 +801,16 @@ static njs_ret_t
 njs_array_prototype_for_each_cont(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused)
 {
-    njs_array_next_t  *next;
+    njs_array_iter_t  *iter;
 
-    next = njs_continuation(vm->frame);
+    iter = njs_continuation(vm->frame);
 
-    if (next->index < 0) {
+    if (iter->next_index >= args[0].data.u.array->length) {
         vm->retval = njs_value_void;
         return NXT_OK;
     }
 
-    return njs_array_iterator_apply(vm, next, args, nargs);
+    return njs_array_iterator_apply(vm, iter, args, nargs);
 }
 
 
@@ -814,16 +819,16 @@ njs_array_prototype_some(njs_vm_t *vm, n
     njs_index_t unused)
 {
     nxt_int_t         ret;
-    njs_array_next_t  *next;
+    njs_array_iter_t  *iter;
 
     ret = njs_array_iterator_args(vm, args, nargs);
     if (nxt_slow_path(ret != NXT_OK)) {
         return ret;
     }
 
-    next = njs_continuation(vm->frame);
-    next->u.cont.function = njs_array_prototype_some_cont;
-    next->retval.data.truth = 0;
+    iter = njs_continuation(vm->frame);
+    iter->u.cont.function = njs_array_prototype_some_cont;
+    iter->retval.data.truth = 0;
 
     return njs_array_prototype_some_cont(vm, args, nargs, unused);
 }
@@ -833,19 +838,19 @@ static njs_ret_t
 njs_array_prototype_some_cont(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused)
 {
-    njs_array_next_t   *next;
+    njs_array_iter_t   *iter;
     const njs_value_t  *retval;
 
-    next = njs_continuation(vm->frame);
+    iter = njs_continuation(vm->frame);
 
-    if (njs_is_true(&next->retval)) {
+    if (njs_is_true(&iter->retval)) {
         retval = &njs_value_true;
 
-    } else if (next->index < 0) {
+    } else if (iter->next_index >= args[0].data.u.array->length) {
         retval = &njs_value_false;
 
     } else {
-        return njs_array_iterator_apply(vm, next, args, nargs);
+        return njs_array_iterator_apply(vm, iter, args, nargs);
     }
 
     vm->retval = *retval;
@@ -859,16 +864,16 @@ njs_array_prototype_every(njs_vm_t *vm, 
     njs_index_t unused)
 {
     nxt_int_t         ret;
-    njs_array_next_t  *next;
+    njs_array_iter_t  *iter;
 
     ret = njs_array_iterator_args(vm, args, nargs);
     if (nxt_slow_path(ret != NXT_OK)) {
         return ret;
     }
 
-    next = njs_continuation(vm->frame);
-    next->u.cont.function = njs_array_prototype_every_cont;
-    next->retval.data.truth = 1;
+    iter = njs_continuation(vm->frame);
+    iter->u.cont.function = njs_array_prototype_every_cont;
+    iter->retval.data.truth = 1;
 
     return njs_array_prototype_every_cont(vm, args, nargs, unused);
 }
@@ -878,19 +883,19 @@ static njs_ret_t
 njs_array_prototype_every_cont(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused)
 {
-    njs_array_next_t   *next;
+    njs_array_iter_t   *iter;
     const njs_value_t  *retval;
 
-    next = njs_continuation(vm->frame);
+    iter = njs_continuation(vm->frame);
 
-    if (!njs_is_true(&next->retval)) {
+    if (!njs_is_true(&iter->retval)) {
         retval = &njs_value_false;
 
-    } else if (next->index < 0) {
+    } else if (iter->next_index >= args[0].data.u.array->length) {
         retval = &njs_value_true;
 
     } else {
-        return njs_array_iterator_apply(vm, next, args, nargs);
+        return njs_array_iterator_apply(vm, iter, args, nargs);
     }
 
     vm->retval = *retval;
@@ -900,17 +905,17 @@ njs_array_prototype_every_cont(njs_vm_t 
 
 
 static nxt_noinline njs_ret_t
-njs_array_iterator_args(njs_vm_t *vm, njs_value_t * args, nxt_uint_t nargs)
+njs_array_iterator_args(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs)
 {
     njs_array_t       *array;
-    njs_array_next_t  *next;
+    njs_array_iter_t  *iter;
 
     if (nargs > 1 && njs_is_array(&args[0]) && njs_is_function(&args[1])) {
 
         array = args[0].data.u.array;
-        next = njs_continuation(vm->frame);
-        next->length = array->length;
-        next->index = njs_array_iterator_next(array->start, 0, array->length);
+        iter = njs_continuation(vm->frame);
+        iter->length = array->length;
+        iter->next_index = njs_array_iterator_next(array, 0, array->length);
 
         return NXT_OK;
     }
@@ -921,11 +926,13 @@ njs_array_iterator_args(njs_vm_t *vm, nj
 }
 
 
-static nxt_noinline nxt_int_t
-njs_array_iterator_next(njs_value_t *value, nxt_uint_t n, nxt_uint_t length)
+static nxt_noinline uint32_t
+njs_array_iterator_next(njs_array_t *array, uint32_t n, uint32_t length)
 {
+    length = nxt_min(length, array->length);
+
     while (n < length) {
-        if (njs_is_valid(&value[n])) {
+        if (njs_is_valid(&array->start[n])) {
             return n;
         }
 
@@ -937,7 +944,7 @@ njs_array_iterator_next(njs_value_t *val
 
 
 static nxt_noinline njs_ret_t
-njs_array_iterator_apply(njs_vm_t *vm, njs_array_next_t *next,
+njs_array_iterator_apply(njs_vm_t *vm, njs_array_iter_t *iter,
     njs_value_t *args, nxt_uint_t nargs)
 {
     nxt_int_t    n;
@@ -950,16 +957,25 @@ njs_array_iterator_apply(njs_vm_t *vm, n
      */
     arguments[0] = (nargs > 2) ? args[2] : *(njs_value_t *) &njs_value_void;
     /* GC: array elt, array */
+
+    /*
+     * All array iterators functions call njs_array_iterator_args()
+     * function which set a correct iter->next_index value.  A large
+     * value of iter->next_index must be checked before calling
+     * njs_array_iterator_apply().
+     */
     array = args[0].data.u.array;
-    n = next->index;
+    n = iter->next_index;
     arguments[1] = array->start[n];
+
     njs_number_set(&arguments[2], n);
+
     arguments[3] = args[0];
 
-    next->index = njs_array_iterator_next(array->start, ++n, next->length);
+    iter->next_index = njs_array_iterator_next(array, n + 1, iter->length);
 
     return njs_function_apply(vm, args[1].data.u.function, arguments, 4,
-                              (njs_index_t) &next->retval);
+                              (njs_index_t) &iter->retval);
 }
 
 
@@ -1034,21 +1050,21 @@ static const njs_object_prop_t  njs_arra
         .type = NJS_METHOD,
         .name = njs_string("forEach"),
         .value = njs_native_function(njs_array_prototype_for_each,
-                     njs_continuation_size(njs_array_next_t), 0),
+                     njs_continuation_size(njs_array_iter_t), 0),
     },
 
     {
         .type = NJS_METHOD,
         .name = njs_string("some"),
         .value = njs_native_function(njs_array_prototype_some,
-                     njs_continuation_size(njs_array_next_t), 0),
+                     njs_continuation_size(njs_array_iter_t), 0),
     },
 
     {
         .type = NJS_METHOD,
         .name = njs_string("every"),
         .value = njs_native_function(njs_array_prototype_every,
-                     njs_continuation_size(njs_array_next_t), 0),
+                     njs_continuation_size(njs_array_iter_t), 0),
     },
 };
 
diff -r 73b0fd4c2ea6 -r 2f40b153a7c1 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Thu Aug 04 16:59:15 2016 +0300
+++ b/njs/test/njs_unit_test.c	Tue Aug 09 14:10:21 2016 +0300
@@ -2293,6 +2293,14 @@ static njs_unit_test_t  njs_test[] =
                  "s.sum"),
       nxt_string("6") },
 
+    { nxt_string("var a = []; var c = 0;"
+                 "a.forEach(function(v, i, a) { c++ }); c"),
+      nxt_string("0") },
+
+    { nxt_string("var a = [,,,,]; var c = 0;"
+                 "a.forEach(function(v, i, a) { c++ }); c"),
+      nxt_string("0") },
+
     { nxt_string("var a = [];"
                  "a.some(function(v, i, a) { return v > 1 })"),
       nxt_string("false") },



More information about the nginx-devel mailing list