[njs] Array iterator functions optimizations.
Igor Sysoev
igor at sysoev.ru
Thu Aug 11 13:39:57 UTC 2016
details: http://hg.nginx.org/njs/rev/0c9a771b7664
branches:
changeset: 154:0c9a771b7664
user: Igor Sysoev <igor at sysoev.ru>
date: Thu Aug 11 13:57:36 2016 +0300
description:
Array iterator functions optimizations.
diffstat:
njs/njs_array.c | 126 ++++++++++++++++++++++++++++++-------------------------
1 files changed, 69 insertions(+), 57 deletions(-)
diffs (262 lines):
diff -r 87df6b787943 -r 0c9a771b7664 njs/njs_array.c
--- a/njs/njs_array.c Thu Aug 11 13:21:46 2016 +0300
+++ b/njs/njs_array.c Thu Aug 11 13:57:36 2016 +0300
@@ -43,12 +43,23 @@ typedef struct {
*/
njs_value_t retval;
+ uint32_t next_index;
+ uint32_t length;
+} njs_array_iter_t;
+
+
+typedef struct {
+ njs_array_iter_t iter;
njs_value_t value;
njs_array_t *array;
- uint32_t next_index;
- uint32_t length;
+} njs_array_filter_t;
+
+
+typedef struct {
+ njs_array_iter_t iter;
+ njs_array_t *array;
uint32_t index;
-} njs_array_iter_t;
+} njs_array_map_t;
typedef struct {
@@ -1137,20 +1148,20 @@ static njs_ret_t
njs_array_prototype_filter(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{
- nxt_int_t ret;
- njs_array_iter_t *iter;
+ nxt_int_t ret;
+ njs_array_filter_t *filter;
ret = njs_array_iterator_args(vm, args, nargs);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}
- iter = njs_continuation(vm->frame);
- iter->u.cont.function = njs_array_prototype_filter_cont;
- iter->retval.data.truth = 0;
+ filter = njs_continuation(vm->frame);
+ filter->iter.u.cont.function = njs_array_prototype_filter_cont;
+ filter->iter.retval.data.truth = 0;
- iter->array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
- if (nxt_slow_path(iter->array == NULL)) {
+ filter->array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
+ if (nxt_slow_path(filter->array == NULL)) {
return NXT_ERROR;
}
@@ -1162,27 +1173,33 @@ static njs_ret_t
njs_array_prototype_filter_cont(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused)
{
- nxt_int_t ret;
- njs_array_iter_t *iter;
+ nxt_int_t ret;
+ njs_array_t *array;
+ njs_array_filter_t *filter;
- iter = njs_continuation(vm->frame);
+ filter = njs_continuation(vm->frame);
- if (njs_is_true(&iter->retval)) {
- ret = njs_array_add(vm, iter->array, &iter->value);
+ if (njs_is_true(&filter->iter.retval)) {
+ ret = njs_array_add(vm, filter->array, &filter->value);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}
}
- if (iter->next_index >= args[0].data.u.array->length) {
- vm->retval.data.u.array = iter->array;
+ array = args[0].data.u.array;
+
+ if (filter->iter.next_index >= array->length) {
+ vm->retval.data.u.array = filter->array;
vm->retval.type = NJS_ARRAY;
vm->retval.data.truth = 1;
return NXT_OK;
}
- return njs_array_iterator_apply(vm, iter, args, nargs);
+ /* GC: filter->value */
+ filter->value = array->start[filter->iter.next_index];
+
+ return njs_array_iterator_apply(vm, &filter->iter, args, nargs);
}
@@ -1190,29 +1207,29 @@ static njs_ret_t
njs_array_prototype_map(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{
- size_t size;
- nxt_int_t ret;
- njs_value_t *value;
- njs_array_t *array;
- njs_array_iter_t *iter;
+ size_t size;
+ nxt_int_t ret;
+ njs_value_t *value;
+ njs_array_t *array;
+ njs_array_map_t *map;
ret = njs_array_iterator_args(vm, args, nargs);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}
- iter = njs_continuation(vm->frame);
- iter->u.cont.function = njs_array_prototype_map_cont;
- njs_set_invalid(&iter->retval);
+ map = njs_continuation(vm->frame);
+ map->iter.u.cont.function = njs_array_prototype_map_cont;
+ njs_set_invalid(&map->iter.retval);
array = args[0].data.u.array;
- iter->array = njs_array_alloc(vm, array->length, 0);
- if (nxt_slow_path(iter->array == NULL)) {
+ map->array = njs_array_alloc(vm, array->length, 0);
+ if (nxt_slow_path(map->array == NULL)) {
return NXT_ERROR;
}
- value = iter->array->start;
+ value = map->array->start;
size = array->length;
while (size != 0) {
@@ -1229,23 +1246,25 @@ static njs_ret_t
njs_array_prototype_map_cont(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused)
{
- njs_array_iter_t *iter;
+ njs_array_map_t *map;
- iter = njs_continuation(vm->frame);
+ map = njs_continuation(vm->frame);
- if (njs_is_valid(&iter->retval)) {
- iter->array->start[iter->index] = iter->retval;
+ if (njs_is_valid(&map->iter.retval)) {
+ map->array->start[map->index] = map->iter.retval;
}
- if (iter->next_index >= args[0].data.u.array->length) {
- vm->retval.data.u.array = iter->array;
+ if (map->iter.next_index >= args[0].data.u.array->length) {
+ vm->retval.data.u.array = map->array;
vm->retval.type = NJS_ARRAY;
vm->retval.data.truth = 1;
return NXT_OK;
}
- return njs_array_iterator_apply(vm, iter, args, nargs);
+ map->index = map->iter.next_index;
+
+ return njs_array_iterator_apply(vm, &map->iter, args, nargs);
}
@@ -1308,12 +1327,6 @@ njs_array_prototype_reduce_cont(njs_vm_t
/* GC: array elt, array */
arguments[1] = iter->retval;
- /*
- * 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 = iter->next_index;
@@ -1392,8 +1405,6 @@ njs_array_iterator_apply(njs_vm_t *vm, n
*/
array = args[0].data.u.array;
n = iter->next_index;
- iter->index = n;
- iter->value = array->start[n];
arguments[1] = array->start[n];
njs_number_set(&arguments[2], n);
@@ -1415,29 +1426,24 @@ njs_array_prototype_reduce_right(njs_vm_
njs_array_t *array;
njs_array_iter_t *iter;
- if (nargs > 1 && njs_is_array(&args[0]) && njs_is_function(&args[1])) {
- array = args[0].data.u.array;
- iter = njs_continuation(vm->frame);
- iter->next_index = njs_array_reduce_right_next(array, array->length);
-
- } else {
- vm->exception = &njs_exception_type_error;
- return NXT_ERROR;
+ if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) {
+ goto type_error;
}
iter = njs_continuation(vm->frame);
iter->u.cont.function = njs_array_prototype_reduce_right_cont;
+ array = args[0].data.u.array;
+ iter->next_index = njs_array_reduce_right_next(array, array->length);
+
if (nargs > 2) {
iter->retval = args[2];
} else {
- array = args[0].data.u.array;
n = iter->next_index;
if (n < 0) {
- vm->exception = &njs_exception_type_error;
- return NXT_ERROR;
+ goto type_error;
}
iter->retval = array->start[n];
@@ -1446,6 +1452,12 @@ njs_array_prototype_reduce_right(njs_vm_
}
return njs_array_prototype_reduce_right_cont(vm, args, nargs, unused);
+
+type_error:
+
+ vm->exception = &njs_exception_type_error;
+
+ return NXT_ERROR;
}
@@ -1748,14 +1760,14 @@ static const njs_object_prop_t njs_arra
.type = NJS_METHOD,
.name = njs_string("filter"),
.value = njs_native_function(njs_array_prototype_filter,
- njs_continuation_size(njs_array_iter_t), 0),
+ njs_continuation_size(njs_array_filter_t), 0),
},
{
.type = NJS_METHOD,
.name = njs_string("map"),
.value = njs_native_function(njs_array_prototype_map,
- njs_continuation_size(njs_array_iter_t), 0),
+ njs_continuation_size(njs_array_map_t), 0),
},
{
More information about the nginx-devel
mailing list