[njs] Added fast path in [[Get]] and [[Set]] for arrays and typed-arrays.
Dmitry Volyntsev
xeioex at nginx.com
Tue Feb 4 17:35:26 UTC 2020
details: https://hg.nginx.org/njs/rev/f5afb325896f
branches:
changeset: 1315:f5afb325896f
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Tue Feb 04 20:35:00 2020 +0300
description:
Added fast path in [[Get]] and [[Set]] for arrays and typed-arrays.
diffstat:
src/njs_array.c | 1 +
src/njs_number.h | 12 ++++-
src/njs_object.c | 3 +
src/njs_typed_array.c | 1 +
src/njs_value.c | 108 +++++++++++++++++++++++++++++++++++++++++++++-
src/njs_value.h | 1 +
src/njs_vmcode.c | 2 +-
src/test/njs_unit_test.c | 4 +-
8 files changed, 123 insertions(+), 9 deletions(-)
diffs (276 lines):
diff -r 2b75ee955589 -r f5afb325896f src/njs_array.c
--- a/src/njs_array.c Mon Jan 20 13:24:09 2020 +0300
+++ b/src/njs_array.c Tue Feb 04 20:35:00 2020 +0300
@@ -67,6 +67,7 @@ njs_array_alloc(njs_vm_t *vm, uint64_t l
array->object.type = NJS_ARRAY;
array->object.shared = 0;
array->object.extensible = 1;
+ array->object.fast_array = 1;
array->size = size;
array->length = length;
diff -r 2b75ee955589 -r f5afb325896f src/njs_number.h
--- a/src/njs_number.h Mon Jan 20 13:24:09 2020 +0300
+++ b/src/njs_number.h Tue Feb 04 20:35:00 2020 +0300
@@ -30,16 +30,24 @@ njs_int_t njs_number_parse_float(njs_vm_
njs_inline njs_bool_t
-njs_number_is_integer_index(double num, const njs_value_t *value)
+njs_number_is_integer_index(double num)
{
uint32_t u32;
u32 = num;
- return (u32 == num && u32 != 0xffffffff)
+ return (u32 == num && u32 != 0xffffffff);
+}
+
+
+njs_inline njs_bool_t
+njs_key_is_integer_index(double num, const njs_value_t *value)
+{
+ return (njs_number_is_integer_index(num))
&& !(njs_is_string(value) && num == 0 && signbit(num));
}
+
njs_inline int64_t
njs_number_to_int64(double num)
{
diff -r 2b75ee955589 -r f5afb325896f src/njs_object.c
--- a/src/njs_object.c Mon Jan 20 13:24:09 2020 +0300
+++ b/src/njs_object.c Tue Feb 04 20:35:00 2020 +0300
@@ -51,6 +51,8 @@ njs_object_alloc(njs_vm_t *vm)
object->shared = 0;
object->extensible = 1;
object->error_data = 0;
+ object->fast_array = 0;
+
return object;
}
@@ -108,6 +110,7 @@ njs_object_value_alloc(njs_vm_t *vm, con
ov->object.type = njs_object_value_type(type);
ov->object.shared = 0;
ov->object.extensible = 1;
+ ov->object.fast_array = 0;
index = njs_primitive_prototype_index(type);
ov->object.__proto__ = &vm->prototypes[index].object;
diff -r 2b75ee955589 -r f5afb325896f src/njs_typed_array.c
--- a/src/njs_typed_array.c Mon Jan 20 13:24:09 2020 +0300
+++ b/src/njs_typed_array.c Tue Feb 04 20:35:00 2020 +0300
@@ -179,6 +179,7 @@ njs_typed_array_constructor(njs_vm_t *vm
array->object.type = NJS_TYPED_ARRAY;
array->object.shared = 0;
array->object.extensible = 1;
+ array->object.fast_array = 1;
njs_set_typed_array(&vm->retval, array);
diff -r 2b75ee955589 -r f5afb325896f src/njs_value.c
--- a/src/njs_value.c Mon Jan 20 13:24:09 2020 +0300
+++ b/src/njs_value.c Tue Feb 04 20:35:00 2020 +0300
@@ -549,7 +549,7 @@ njs_property_query(njs_vm_t *vm, njs_pro
case NJS_STRING:
if (njs_fast_path(!njs_is_null_or_undefined_or_boolean(key))) {
num = njs_key_to_index(key);
- if (njs_fast_path(njs_number_is_integer_index(num, key))) {
+ if (njs_fast_path(njs_key_is_integer_index(num, key))) {
return njs_string_property_query(vm, pq, value, num);
}
}
@@ -654,7 +654,7 @@ njs_object_property_query(njs_vm_t *vm,
switch (proto->type) {
case NJS_ARRAY:
num = njs_key_to_index(key);
- if (njs_fast_path(njs_number_is_integer_index(num, key))) {
+ if (njs_fast_path(njs_key_is_integer_index(num, key))) {
array = (njs_array_t *) proto;
return njs_array_property_query(vm, pq, array, num);
}
@@ -663,7 +663,7 @@ njs_object_property_query(njs_vm_t *vm,
case NJS_TYPED_ARRAY:
num = njs_key_to_index(key);
- if (njs_fast_path(njs_number_is_integer_index(num, key))) {
+ if (njs_fast_path(njs_key_is_integer_index(num, key))) {
tarray = (njs_typed_array_t *) proto;
return njs_typed_array_property_query(vm, pq, tarray, num);
}
@@ -676,7 +676,7 @@ njs_object_property_query(njs_vm_t *vm,
case NJS_OBJECT_STRING:
num = njs_key_to_index(key);
- if (njs_fast_path(njs_number_is_integer_index(num, key))) {
+ if (njs_fast_path(njs_key_is_integer_index(num, key))) {
ov = (njs_object_value_t *) proto;
ret = njs_string_property_query(vm, pq, &ov->value, num);
@@ -1021,10 +1021,60 @@ njs_int_t
njs_value_property(njs_vm_t *vm, njs_value_t *value, njs_value_t *key,
njs_value_t *retval)
{
+ double num;
+ uint32_t index;
njs_int_t ret;
+ njs_array_t *array;
njs_object_prop_t *prop;
+ njs_typed_array_t *tarray;
njs_property_query_t pq;
+ if (njs_fast_path(njs_is_number(key))) {
+ num = njs_number(key);
+
+ if (njs_slow_path(!njs_number_is_integer_index(num))) {
+ goto slow_path;
+ }
+
+ index = (uint32_t) num;
+
+ if (njs_is_typed_array(value)) {
+ tarray = njs_typed_array(value);
+
+ if (njs_slow_path(index >= njs_typed_array_length(tarray))) {
+ goto slow_path;
+ }
+
+ njs_set_number(retval, njs_typed_array_get(tarray, index));
+
+ return NJS_OK;
+ }
+
+ if (njs_slow_path(!(njs_is_object(value)
+ && njs_object(value)->fast_array)))
+ {
+ goto slow_path;
+ }
+
+ /* NJS_ARRAY */
+
+ array = njs_array(value);
+
+ if (njs_slow_path(index >= array->length)) {
+ goto slow_path;
+ }
+
+ *retval = array->start[index];
+
+ if (njs_slow_path(!njs_is_valid(retval))) {
+ njs_set_undefined(retval);
+ }
+
+ return NJS_OK;
+ }
+
+slow_path:
+
njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0);
ret = njs_property_query(vm, &pq, value, key);
@@ -1093,16 +1143,66 @@ njs_int_t
njs_value_property_set(njs_vm_t *vm, njs_value_t *value, njs_value_t *key,
njs_value_t *setval)
{
+ double num;
+ uint32_t index;
njs_int_t ret;
+ njs_array_t *array;
njs_object_prop_t *prop;
+ njs_typed_array_t *tarray;
njs_property_query_t pq;
+ if (njs_fast_path(njs_is_number(key))) {
+ num = njs_number(key);
+
+ if (njs_slow_path(!njs_number_is_integer_index(num))) {
+ goto slow_path;
+ }
+
+ index = (uint32_t) num;
+
+ if (njs_is_typed_array(value)) {
+ tarray = njs_typed_array(value);
+
+ if (njs_fast_path(index < njs_typed_array_length(tarray))) {
+ ret = njs_value_to_number(vm, setval, &num);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ njs_typed_array_set(tarray, index, num);
+ }
+
+ return NJS_OK;
+ }
+
+ if (njs_slow_path(!(njs_is_object(value)
+ && njs_object(value)->fast_array)))
+ {
+ goto slow_path;
+ }
+
+ /* NJS_ARRAY */
+
+ array = njs_array(value);
+
+ if (njs_slow_path(index >= array->length)) {
+ goto slow_path;
+ }
+
+ array->start[index] = *setval;
+
+ return NJS_OK;
+ }
+
+slow_path:
+
if (njs_is_primitive(value)) {
njs_type_error(vm, "property set on primitive %s type",
njs_type_string(value->type));
return NJS_ERROR;
}
+
njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 0);
ret = njs_property_query(vm, &pq, value, key);
diff -r 2b75ee955589 -r f5afb325896f src/njs_value.h
--- a/src/njs_value.h Mon Jan 20 13:24:09 2020 +0300
+++ b/src/njs_value.h Tue Feb 04 20:35:00 2020 +0300
@@ -215,6 +215,7 @@ struct njs_object_s {
uint8_t extensible:1;
uint8_t error_data:1;
+ uint8_t fast_array:1;
};
diff -r 2b75ee955589 -r f5afb325896f src/njs_vmcode.c
--- a/src/njs_vmcode.c Mon Jan 20 13:24:09 2020 +0300
+++ b/src/njs_vmcode.c Tue Feb 04 20:35:00 2020 +0300
@@ -1152,7 +1152,7 @@ njs_vmcode_property_init(njs_vm_t *vm, n
switch (value->type) {
case NJS_ARRAY:
num = njs_key_to_index(key);
- if (njs_slow_path(!njs_number_is_integer_index(num, key))) {
+ if (njs_slow_path(!njs_key_is_integer_index(num, key))) {
njs_internal_error(vm,
"invalid index while property initialization");
return NJS_ERROR;
diff -r 2b75ee955589 -r f5afb325896f src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Mon Jan 20 13:24:09 2020 +0300
+++ b/src/test/njs_unit_test.c Tue Feb 04 20:35:00 2020 +0300
@@ -17772,8 +17772,8 @@ njs_string_to_index_test(njs_vm_t *vm, n
}
}
- is_integer_index = njs_number_is_integer_index(njs_number(&vm->retval),
- &tests[i].value);
+ is_integer_index = njs_key_is_integer_index(njs_number(&vm->retval),
+ &tests[i].value);
if (tests[i].is_integer_index != is_integer_index) {
njs_string_get(&tests[i].value, &string);
More information about the nginx-devel
mailing list