details: http://hg.nginx.org/njs/rev/2f40b153a7c1 branches: changeset: 144:2f40b153a7c1 user: Igor Sysoev <i...@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") }, _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel