Welcome! Log In Create A New Profile

Advanced

[njs] Added fast path in [[Get]] and [[Set]] for arrays and typed-arrays.

Dmitry Volyntsev
February 04, 2020 12:36PM
details: https://hg.nginx.org/njs/rev/f5afb325896f
branches:
changeset: 1315:f5afb325896f
user: Dmitry Volyntsev <xeioex@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);
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[njs] Added fast path in [[Get]] and [[Set]] for arrays and typed-arrays.

Dmitry Volyntsev 85 February 04, 2020 12:36PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 91
Record Number of Users: 6 on February 13, 2018
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready