Welcome! Log In Create A New Profile

Advanced

[njs] Refactored working with non-primitive types.

Dmitry Volyntsev
July 19, 2019 04:30PM
details: https://hg.nginx.org/njs/rev/201af81dfa9b
branches:
changeset: 1060:201af81dfa9b
user: Dmitry Volyntsev <xeioex@nginx.com>
date: Fri Jul 05 21:45:28 2019 +0300
description:
Refactored working with non-primitive types.

Traps mechanism is remove.

diffstat:

njs/njs.c | 2 -
njs/njs_array.c | 47 +-
njs/njs_date.c | 31 +-
njs/njs_function.c | 108 ++-
njs/njs_function.h | 50 +-
njs/njs_math.c | 24 +-
njs/njs_object.c | 2 -
njs/njs_object_property.c | 14 +-
njs/njs_regexp.c | 14 +-
njs/njs_string.c | 74 +-
njs/njs_string.h | 3 -
njs/njs_value.c | 120 +-
njs/njs_value.h | 137 ++-
njs/njs_vm.c | 1451 ++++++++++++++++----------------------
njs/njs_vm.h | 32 +-
njs/test/njs_interactive_test.c | 3 +-
njs/test/njs_unit_test.c | 74 +
17 files changed, 1033 insertions(+), 1153 deletions(-)

diffs (truncated from 3221 to 1000 lines):

diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs.c
--- a/njs/njs.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs.c Fri Jul 05 21:45:28 2019 +0300
@@ -984,8 +984,6 @@ again:

/* value evaluation threw an exception. */

- vm->top_frame->trap_tries = 0;
-
src = &vm->retval;
goto again;
}
diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_array.c
--- a/njs/njs_array.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_array.c Fri Jul 05 21:45:28 2019 +0300
@@ -528,10 +528,7 @@ njs_array_prototype_slice(njs_vm_t *vm,
ret = njs_value_property(vm, &args[0], &njs_string_length, &slice->length,
0);

- if (nxt_slow_path(ret == NXT_ERROR
- || ret == NJS_TRAP
- || ret == NJS_APPLIED))
- {
+ if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) {
return ret;
}

@@ -544,13 +541,16 @@ njs_array_prototype_slice_continuation(n
nxt_uint_t nargs, njs_index_t unused)
{
int64_t start, end, length;
+ njs_ret_t ret;
njs_array_slice_t *slice;

slice = njs_vm_continuation(vm);

if (nxt_slow_path(!njs_is_primitive(&slice->length))) {
- njs_vm_trap_value(vm, &slice->length);
- return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
+ ret = njs_value_to_numeric(vm, &slice->length, &slice->length);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

start = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
@@ -958,7 +958,7 @@ njs_array_prototype_reverse(njs_vm_t *vm

static njs_ret_t
njs_array_prototype_to_string(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
- njs_index_t retval)
+ njs_index_t unused)
{
njs_object_prop_t *prop;
nxt_lvlhsh_query_t lhq;
@@ -970,12 +970,12 @@ njs_array_prototype_to_string(njs_vm_t *
prop = njs_object_property(vm, njs_object(&args[0]), &lhq);

if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) {
- return njs_function_replace(vm, njs_function(&prop->value),
- args, nargs, retval);
+ return njs_function_call(vm, njs_function(&prop->value), args,
+ nargs, (njs_index_t) &vm->retval);
}
}

- return njs_object_prototype_to_string(vm, args, nargs, retval);
+ return njs_object_prototype_to_string(vm, args, nargs, unused);
}


@@ -1063,6 +1063,7 @@ njs_array_prototype_join_continuation(nj
u_char *p;
size_t size, length, mask;
uint32_t max;
+ njs_ret_t ret;
nxt_uint_t i, n;
njs_array_t *array;
njs_value_t *value, *values;
@@ -1089,9 +1090,10 @@ njs_array_prototype_join_continuation(nj
value = &values[n++];

if (!njs_is_string(value)) {
- njs_vm_trap_value(vm, value);
-
- return njs_trap(vm, NJS_TRAP_STRING_ARG);
+ ret = njs_value_to_string(vm, value, value);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}
}

@@ -1442,10 +1444,7 @@ njs_array_prototype_fill(njs_vm_t *vm, n
ret = njs_value_property(vm, this, &njs_string_length, &fill->length,
0);

- if (nxt_slow_path(ret == NXT_ERROR
- || ret == NJS_TRAP
- || ret == NJS_APPLIED))
- {
+ if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) {
return ret;
}
}
@@ -1459,6 +1458,7 @@ njs_array_prototype_fill_continuation(nj
nxt_uint_t nargs, njs_index_t unused)
{
nxt_int_t i, start, end, length;
+ njs_ret_t ret;
njs_array_t *array;
njs_object_t *object;
njs_array_fill_t *fill;
@@ -1488,8 +1488,10 @@ njs_array_prototype_fill_continuation(nj
} else {

if (nxt_slow_path(!njs_is_primitive(&fill->length))) {
- njs_vm_trap_value(vm, &fill->length);
- return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
+ ret = njs_value_to_numeric(vm, &fill->length, &fill->length);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

length = njs_primitive_value_to_length(&fill->length);
@@ -2202,9 +2204,10 @@ njs_array_string_sort(njs_vm_t *vm, njs_

for (i = 1; i < nargs; i++) {
if (!njs_is_string(&args[i])) {
- njs_vm_trap_value(vm, &args[i]);
-
- return njs_trap(vm, NJS_TRAP_STRING_ARG);
+ ret = njs_value_to_string(vm, &args[i], &args[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}
}

diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_date.c
--- a/njs/njs_date.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_date.c Fri Jul 05 21:45:28 2019 +0300
@@ -73,6 +73,7 @@ njs_date_constructor(njs_vm_t *vm, njs_v
{
double num, time;
int64_t values[8];
+ njs_ret_t ret;
nxt_uint_t i, n;
njs_date_t *date;
struct tm tm;
@@ -85,11 +86,14 @@ njs_date_constructor(njs_vm_t *vm, njs_v
} else if (nargs == 2) {
if (njs_is_object(&args[1])) {
if (!njs_is_date(&args[1])) {
- njs_vm_trap_value(vm, &args[1]);
-
- return njs_trap(vm, NJS_TRAP_PRIMITIVE_ARG);
+ ret = njs_value_to_primitive(vm, &args[1], &args[1], 0);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}
-
+ }
+
+ if (njs_is_date(&args[1])) {
time = njs_date(&args[1])->time;

} else if (njs_is_string(&args[1])) {
@@ -108,9 +112,10 @@ njs_date_constructor(njs_vm_t *vm, njs_v

for (i = 1; i < n; i++) {
if (!njs_is_numeric(&args[i])) {
- njs_vm_trap_value(vm, &args[i]);
-
- return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
+ ret = njs_value_to_numeric(vm, &args[i], &args[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

num = njs_number(&args[i]);
@@ -171,6 +176,7 @@ njs_date_utc(njs_vm_t *vm, njs_value_t *
{
double num, time;
struct tm tm;
+ njs_ret_t ret;
nxt_uint_t i, n;
int32_t values[8];

@@ -183,9 +189,10 @@ njs_date_utc(njs_vm_t *vm, njs_value_t *

for (i = 1; i < n; i++) {
if (!njs_is_numeric(&args[i])) {
- njs_vm_trap_value(vm, &args[i]);
-
- return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
+ ret = njs_value_to_numeric(vm, &args[i], &args[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

num = njs_number(&args[i]);
@@ -1902,8 +1909,8 @@ njs_date_prototype_to_json(njs_vm_t *vm,
prop = njs_object_property(vm, njs_object(&args[0]), &lhq);

if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) {
- return njs_function_replace(vm, njs_function(&prop->value),
- args, nargs, retval);
+ return njs_function_call(vm, njs_function(&prop->value), args,
+ nargs, (njs_index_t) &vm->retval);
}
}

diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_function.c
--- a/njs/njs_function.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_function.c Fri Jul 05 21:45:28 2019 +0300
@@ -473,6 +473,48 @@ njs_function_frame_alloc(njs_vm_t *vm, s


njs_ret_t
+njs_function_call(njs_vm_t *vm, njs_function_t *function, njs_value_t *args,
+ nxt_uint_t nargs, njs_index_t retval)
+{
+ u_char *return_address;
+ njs_ret_t ret;
+ njs_native_frame_t *frame;
+ njs_continuation_t *cont;
+
+ ret = njs_function_frame(vm, function, &args[0], &args[1], nargs - 1, 0, 0);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+
+ frame = vm->top_frame;
+ frame->call = 1;
+
+ return_address = vm->current;
+
+ if (function->native) {
+
+ if (function->continuation_size != 0) {
+ cont = njs_vm_continuation(vm);
+ cont->return_address = return_address;
+ }
+
+ ret = njs_function_native_call(vm, function->u.native, frame->arguments,
+ function->args_types, frame->nargs,
+ (njs_index_t) retval, return_address);
+
+ } else {
+ ret = njs_function_lambda_call(vm, retval, return_address);
+
+ if (nxt_fast_path(ret == NJS_APPLIED)) {
+ ret = njs_vmcode_run(vm);
+ }
+ }
+
+ return ret;
+}
+
+
+njs_ret_t
njs_function_lambda_call(njs_vm_t *vm, njs_index_t retval,
u_char *return_address)
{
@@ -594,9 +636,9 @@ njs_function_native_call(njs_vm_t *vm, n
* The callee arguments must be preserved
* for NJS_APPLIED and NXT_AGAIN cases.
*/
- if (ret == NXT_OK) {
- frame = vm->top_frame;
+ frame = vm->top_frame;

+ if (ret == NXT_OK || (frame->call && ret == NXT_ERROR)) {
vm->top_frame = njs_function_previous_frame(frame);

/*
@@ -625,7 +667,7 @@ njs_function_native_call(njs_vm_t *vm, n

njs_function_frame_free(vm, frame);

- return NXT_OK;
+ return ret;
}

return ret;
@@ -636,8 +678,8 @@ static njs_ret_t
njs_normalize_args(njs_vm_t *vm, njs_value_t *args, uint8_t *args_types,
nxt_uint_t nargs)
{
+ njs_ret_t ret;
nxt_uint_t n;
- njs_trap_t trap;

n = nxt_min(nargs, NJS_ARGS_TYPES_MAX);

@@ -655,43 +697,47 @@ njs_normalize_args(njs_vm_t *vm, njs_val

case NJS_STRING_ARG:

- if (njs_is_string(args)) {
- break;
+ if (!njs_is_string(args)) {
+ ret = njs_value_to_string(vm, args, args);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

- trap = NJS_TRAP_STRING_ARG;
- goto trap;
+ break;

case NJS_NUMBER_ARG:

- if (njs_is_numeric(args)) {
- break;
+ if (!njs_is_numeric(args)) {
+ ret = njs_value_to_numeric(vm, args, args);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

- trap = NJS_TRAP_NUMBER_ARG;
- goto trap;
+ break;

case NJS_INTEGER_ARG:

- if (njs_is_numeric(args)) {
-
- /* Numbers are truncated to fit in 32-bit integers. */
+ if (!njs_is_numeric(args)) {
+ ret = njs_value_to_numeric(vm, args, args);
+ if (ret != NXT_OK) {
+ return ret;
+ }
+ }

- if (isnan(njs_number(args))) {
- njs_number(args) = 0;
+ /* Numbers are truncated to fit in 32-bit integers. */

- } else if (njs_number(args) > 2147483647.0) {
+ if (!isnan(njs_number(args))) {
+ if (njs_number(args) > 2147483647.0) {
njs_number(args) = 2147483647.0;

} else if (njs_number(args) < -2147483648.0) {
njs_number(args) = -2147483648.0;
}
-
- break;
}

- trap = NJS_TRAP_NUMBER_ARG;
- goto trap;
+ break;

case NJS_FUNCTION_ARG:

@@ -701,8 +747,10 @@ njs_normalize_args(njs_vm_t *vm, njs_val
break;

default:
- trap = NJS_TRAP_STRING_ARG;
- goto trap;
+ ret = njs_value_to_string(vm, args, args);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

break;
@@ -716,8 +764,10 @@ njs_normalize_args(njs_vm_t *vm, njs_val
break;

default:
- trap = NJS_TRAP_STRING_ARG;
- goto trap;
+ ret = njs_value_to_string(vm, args, args);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

break;
@@ -751,12 +801,6 @@ njs_normalize_args(njs_vm_t *vm, njs_val

return NJS_OK;

-trap:
-
- njs_vm_trap_value(vm, args);
-
- return njs_trap(vm, trap);
-
type_error:

njs_type_error(vm, "cannot convert %s to %s", njs_type_string(args->type),
diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_function.h
--- a/njs/njs_function.h Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_function.h Fri Jul 05 21:45:28 2019 +0300
@@ -74,11 +74,6 @@ typedef struct {
#define NJS_CONTINUATION_SIZE njs_continuation_size(njs_continuation_t)


-#define njs_vm_trap_value(vm, val) \
- (vm)->top_frame->trap_scratch.data.u.value = val
-
-
-
typedef struct njs_exception_s njs_exception_t;

struct njs_exception_s {
@@ -92,10 +87,6 @@ struct njs_exception_s {


struct njs_native_frame_s {
- njs_value_t trap_scratch;
- njs_value_t trap_values[2];
- u_char *trap_restart;
-
u_char *free;

njs_function_t *function;
@@ -118,14 +109,7 @@ struct njs_native_frame_s {
/* Skip the Function.call() and Function.apply() methods frames. */
uint8_t skip; /* 1 bit */

- /* A number of trap tries, it can be no more than three. */
- uint8_t trap_tries; /* 2 bits */
-
- /*
- * The first operand in trap is reference to original value,
- * it is used to increment or decrement this value.
- */
- uint8_t trap_reference; /* 1 bit */
+ uint8_t call; /* 1 bit */
};


@@ -168,6 +152,8 @@ njs_ret_t njs_function_lambda_frame(njs_
njs_ret_t njs_function_activate(njs_vm_t *vm, njs_function_t *function,
const njs_value_t *this, const njs_value_t *args, nxt_uint_t nargs,
njs_index_t retval, size_t advance);
+njs_ret_t njs_function_call(njs_vm_t *vm, njs_function_t *function,
+ njs_value_t *args, nxt_uint_t nargs, njs_index_t retval);
njs_ret_t njs_function_lambda_call(njs_vm_t *vm, njs_index_t retval,
u_char *return_address);
njs_ret_t njs_function_native_call(njs_vm_t *vm, njs_function_native_t native,
@@ -215,36 +201,6 @@ njs_function_apply(njs_vm_t *vm, njs_fun
}


-/*
- * Replaces the current function with a new one.
- * Can only be used for continuation functions
- * (data.u.function.continuation_size > 0).
- */
-nxt_inline njs_ret_t
-njs_function_replace(njs_vm_t *vm, njs_function_t *function,
- const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval)
-{
- nxt_int_t ret;
-
- ret = njs_function_apply(vm, function, args, nargs, retval);
- if (nxt_slow_path(ret == NXT_ERROR)) {
- return ret;
- }
-
- /*
- * 1) njs_function_apply() allocs a new function frame,
- * in order to preserve the retval of a new function and ignore
- * retval of the current function during stack unwinding
- * skip flag is needed.
- * 2) it is also needed for correct callee arguments update in
- * njs_function_native_call() see "Object((new Date(0)).toJSON())".
- */
- vm->top_frame->previous->skip = 1;
-
- return NJS_APPLIED;
-}
-
-
nxt_inline njs_native_frame_t *
njs_function_previous_frame(njs_native_frame_t *frame)
{
diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_math.c
--- a/njs/njs_math.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_math.c Fri Jul 05 21:45:28 2019 +0300
@@ -359,13 +359,15 @@ njs_object_math_hypot(njs_vm_t *vm, njs_
njs_index_t unused)
{
double num;
+ njs_ret_t ret;
nxt_uint_t i;

for (i = 1; i < nargs; i++) {
if (!njs_is_numeric(&args[i])) {
- njs_vm_trap_value(vm, &args[i]);
-
- return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
+ ret = njs_value_to_numeric(vm, &args[i], &args[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}
}

@@ -498,6 +500,7 @@ njs_object_math_max(njs_vm_t *vm, njs_va
njs_index_t unused)
{
double num;
+ njs_ret_t ret;
nxt_uint_t i;

if (nargs > 1) {
@@ -507,9 +510,10 @@ njs_object_math_max(njs_vm_t *vm, njs_va
goto done;

} else if (!njs_is_numeric(&args[i])) {
- njs_vm_trap_value(vm, &args[i]);
-
- return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
+ ret = njs_value_to_numeric(vm, &args[i], &args[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}
}

@@ -536,14 +540,16 @@ njs_object_math_min(njs_vm_t *vm, njs_va
njs_index_t unused)
{
double num;
+ njs_ret_t ret;
nxt_uint_t i;

if (nargs > 1) {
for (i = 1; i < nargs; i++) {
if (!njs_is_numeric(&args[i])) {
- njs_vm_trap_value(vm, &args[i]);
-
- return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
+ ret = njs_value_to_numeric(vm, &args[i], &args[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}
}

diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_object.c
--- a/njs/njs_object.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_object.c Fri Jul 05 21:45:28 2019 +0300
@@ -2140,7 +2140,6 @@ njs_object_prototype_has_own_property(nj
vm->retval = njs_value_false;
return NXT_OK;

- case NJS_TRAP:
case NXT_ERROR:
default:
return ret;
@@ -2181,7 +2180,6 @@ njs_object_prototype_prop_is_enumerable(
retval = &njs_value_false;
break;

- case NJS_TRAP:
case NXT_ERROR:
default:
return ret;
diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_object_property.c
--- a/njs/njs_object_property.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_object_property.c Fri Jul 05 21:45:28 2019 +0300
@@ -38,7 +38,6 @@ static njs_object_prop_t *njs_descriptor
* NXT_DECLINED property was not found in object,
* if pq->lhq.value != NULL it contains retval of type
* njs_object_prop_t * where prop->type is NJS_WHITEOUT
- * NJS_TRAP the property trap must be called,
* NXT_ERROR exception has been thrown.
*
* TODO:
@@ -53,10 +52,16 @@ njs_property_query(njs_vm_t *vm, njs_pro
uint32_t (*hash)(const void *, size_t);
njs_ret_t ret;
njs_object_t *obj;
+ njs_value_t prop;
njs_function_t *function;

if (nxt_slow_path(!njs_is_primitive(property))) {
- return njs_trap(vm, NJS_TRAP_PROPERTY);
+ ret = njs_value_to_string(vm, &prop, (njs_value_t *) property);
+ if (ret != NXT_OK) {
+ return ret;
+ }
+
+ property = &prop;
}

hash = nxt_djb_hash;
@@ -473,7 +478,6 @@ njs_external_property_delete(njs_vm_t *v
* retval will contain the property's value
*
* NXT_DECLINED property was not found in object
- * NJS_TRAP the property trap must be called
* NJS_APPLIED the property getter was applied
* NXT_ERROR exception has been thrown.
* retval will contain undefined
@@ -553,7 +557,6 @@ njs_value_property(njs_vm_t *vm, const n

return NXT_DECLINED;

- case NJS_TRAP:
case NXT_ERROR:
default:

@@ -566,7 +569,6 @@ njs_value_property(njs_vm_t *vm, const n

/*
* NXT_OK property has been set successfully
- * NJS_TRAP the property trap must be called
* NJS_APPLIED the property setter was applied
* NXT_ERROR exception has been thrown.
*/
@@ -669,7 +671,6 @@ njs_value_property_set(njs_vm_t *vm, njs

break;

- case NJS_TRAP:
case NXT_ERROR:
default:

@@ -1152,7 +1153,6 @@ njs_object_prop_descriptor(njs_vm_t *vm,
*dest = njs_value_undefined;
return NXT_OK;

- case NJS_TRAP:
case NXT_ERROR:
default:
return ret;
diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_regexp.c
--- a/njs/njs_regexp.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_regexp.c Fri Jul 05 21:45:28 2019 +0300
@@ -112,17 +112,19 @@ njs_regexp_constructor(njs_vm_t *vm, njs
pattern = njs_arg(args, nargs, 1);

if (!njs_is_regexp(pattern) && !njs_is_primitive(pattern)) {
- njs_vm_trap_value(vm, &args[1]);
-
- return njs_trap(vm, NJS_TRAP_STRING_ARG);
+ ret = njs_value_to_string(vm, &args[1], &args[1]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

flags = njs_arg(args, nargs, 2);

if (!njs_is_primitive(flags)) {
- njs_vm_trap_value(vm, &args[2]);
-
- return njs_trap(vm, NJS_TRAP_STRING_ARG);
+ ret = njs_value_to_string(vm, &args[2], &args[2]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

re_flags = 0;
diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_string.c
--- a/njs/njs_string.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_string.c Fri Jul 05 21:45:28 2019 +0300
@@ -875,6 +875,7 @@ njs_string_prototype_concat(njs_vm_t *vm
{
u_char *p, *start;
uint64_t size, length, mask;
+ njs_ret_t ret;
nxt_uint_t i;
njs_string_prop_t string;

@@ -885,9 +886,10 @@ njs_string_prototype_concat(njs_vm_t *vm

for (i = 0; i < nargs; i++) {
if (!njs_is_string(&args[i])) {
- njs_vm_trap_value(vm, &args[i]);
-
- return njs_trap(vm, NJS_TRAP_STRING_ARG);
+ ret = njs_value_to_string(vm, &args[i], &args[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}
}

@@ -1244,16 +1246,12 @@ njs_string_prototype_char_at(njs_vm_t *v

slice.string_length = njs_string_prop(&string, &args[0]);

- start = 0;
+ start = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
length = 1;

- if (nargs > 1) {
- start = njs_number(&args[1]);
-
- if (start < 0 || start >= (ssize_t) slice.string_length) {
- start = 0;
- length = 0;
- }
+ if (start < 0 || start >= (ssize_t) slice.string_length) {
+ start = 0;
+ length = 0;
}

slice.start = start;
@@ -1409,15 +1407,11 @@ njs_string_prototype_char_code_at(njs_vm

length = njs_string_prop(&string, &args[0]);

- index = 0;
-
- if (nargs > 1) {
- index = njs_number(&args[1]);
-
- if (nxt_slow_path(index < 0 || index >= length)) {
- num = NAN;
- goto done;
- }
+ index = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
+
+ if (nxt_slow_path(index < 0 || index >= length)) {
+ num = NAN;
+ goto done;
}

if ((uint32_t) length == string.size) {
@@ -1477,6 +1471,7 @@ njs_string_bytes_from_array(njs_vm_t *vm
{
u_char *p;
uint32_t i, length;
+ njs_ret_t ret;
njs_array_t *array;
njs_value_t *octet;

@@ -1485,9 +1480,10 @@ njs_string_bytes_from_array(njs_vm_t *vm

for (i = 0; i < length; i++) {
if (!njs_is_numeric(&array->start[i])) {
- njs_vm_trap_value(vm, &array->start[i]);
-
- return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
+ ret = njs_value_to_numeric(vm, &array->start[i], &array->start[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}
}

@@ -1713,13 +1709,15 @@ njs_string_from_char_code(njs_vm_t *vm,
double num;
size_t size;
int32_t code;
+ njs_ret_t ret;
nxt_uint_t i;

for (i = 1; i < nargs; i++) {
if (!njs_is_numeric(&args[i])) {
- njs_vm_trap_value(vm, &args[i]);
-
- return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
+ ret = njs_value_to_numeric(vm, &args[i], &args[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}
}

@@ -2426,20 +2424,16 @@ njs_string_prototype_repeat(njs_vm_t *vm
uint32_t size, length;
njs_string_prop_t string;

- n = 0;
+ n = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));

(void) njs_string_prop(&string, &args[0]);

- if (nargs > 1) {
- max = (string.size > 1) ? NJS_STRING_MAX_LENGTH / string.size
- : NJS_STRING_MAX_LENGTH;
-
- n = njs_number(&args[1]);
-
- if (nxt_slow_path(n < 0 || n >= max)) {
- njs_range_error(vm, NULL);
- return NXT_ERROR;
- }
+ max = (string.size > 1) ? NJS_STRING_MAX_LENGTH / string.size
+ : NJS_STRING_MAX_LENGTH;
+
+ if (nxt_slow_path(n < 0 || n >= max)) {
+ njs_range_error(vm, NULL);
+ return NXT_ERROR;
}

if (string.size == 0) {
@@ -3427,8 +3421,10 @@ njs_string_replace_search_continuation(n
r = njs_vm_continuation(vm);

if (!njs_is_primitive(&r->retval)) {
- njs_vm_trap_value(vm, &r->retval);
- return njs_trap(vm, NJS_TRAP_STRING_ARG);
+ ret = njs_value_to_string(vm, &r->retval, &r->retval);
+ if (ret != NXT_OK) {
+ return ret;
+ }
}

ret = njs_primitive_value_to_string(vm, &string, &r->retval);
diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_string.h
--- a/njs/njs_string.h Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_string.h Fri Jul 05 21:45:28 2019 +0300
@@ -177,10 +177,7 @@ const u_char *njs_string_offset(const u_
size_t index);
uint32_t njs_string_index(njs_string_prop_t *string, uint32_t offset);
void njs_string_offset_map_init(const u_char *start, size_t size);
-njs_ret_t njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst,
- const njs_value_t *src);
double njs_string_to_index(const njs_value_t *value);
-double njs_string_to_number(const njs_value_t *value, nxt_bool_t parse_float);
const u_char *njs_string_to_c_string(njs_vm_t *vm, njs_value_t *value);
njs_ret_t njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_value.c
--- a/njs/njs_value.c Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_value.c Fri Jul 05 21:45:28 2019 +0300
@@ -101,14 +101,16 @@ njs_value_release(njs_vm_t *vm, njs_valu
*/

njs_ret_t
-njs_value_to_primitive(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint)
+njs_value_to_primitive(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value,
+ nxt_uint_t hint)
{
njs_ret_t ret;
- njs_value_t *retval;
- njs_function_t *function;
+ nxt_uint_t tries;
njs_object_prop_t *prop;
nxt_lvlhsh_query_t lhq;

+ njs_value_t retval nxt_aligned(16);
+
static const uint32_t hashes[] = {
NJS_VALUE_OF_HASH,
NJS_TO_STRING_HASH,
@@ -119,76 +121,56 @@ njs_value_to_primitive(njs_vm_t *vm, njs
nxt_string("toString"),
};

- if (!njs_is_primitive(value)) {
- retval = &vm->top_frame->trap_scratch;

- if (!njs_is_primitive(retval)) {
-
- for ( ;; ) {
- ret = NXT_ERROR;
-
- if (njs_is_object(value) && vm->top_frame->trap_tries < 2) {
- hint ^= vm->top_frame->trap_tries++;
-
- lhq.key_hash = hashes[hint];
- lhq.key = names[hint];
-
- prop = njs_object_property(vm, njs_object(value), &lhq);
-
- if (nxt_fast_path(prop != NULL)) {
-
- if (!njs_is_function(&prop->value)) {
- /* Try the second method. */
- continue;
- }
-
- function = njs_function(&prop->value);
-
- ret = njs_function_apply(vm, function, value, 1,
- (njs_index_t) retval);
- /*
- * njs_function_apply() can return
- * NXT_OK, NJS_APPLIED, NXT_ERROR, NXT_AGAIN.
- */
- if (nxt_fast_path(ret == NXT_OK)) {
-
- if (njs_is_primitive(&vm->retval)) {
- retval = &vm->retval;
- break;
- }
-
- /* Try the second method. */
- continue;
- }
-
- if (ret == NJS_APPLIED) {
- /*
- * A user-defined method or continuation have
- * been prepared to run. The method will return
- * to the current instruction and will restart it.
- */
- ret = 0;
- }
- }
- }
-
- if (ret == NXT_ERROR) {
- njs_type_error(vm,
- "Cannot convert object to primitive value");
- }
-
- return ret;
- }
- }
-
- *value = *retval;
-
- njs_set_invalid(retval);
+ if (njs_is_primitive(value)) {
+ /* GC */
+ *dst = *value;
+ return NXT_OK;
}

- vm->top_frame->trap_tries = 0;
+ tries = 0;
+
+ for ( ;; ) {
+ ret = NXT_ERROR;
+
+ if (njs_is_object(value) && tries < 2) {
+ hint ^= tries++;
+
+ lhq.key_hash = hashes[hint];
+ lhq.key = names[hint];
+
+ prop = njs_object_property(vm, njs_object(value), &lhq);
+
+ if (prop == NULL || !njs_is_function(&prop->value)) {
+ /* Try the second method. */
+ continue;
+ }
+
+ ret = njs_function_call(vm, njs_function(&prop->value), value, 1,
+ (njs_index_t) &retval);

- return 1;
+ if (nxt_fast_path(ret == NXT_OK)) {
+ if (njs_is_primitive(&retval)) {
+ break;
+ }
+
+ /* Try the second method. */
+ continue;
+ }
+
+ /* NXT_ERROR */
+
+ return ret;
+ }
+
+ njs_type_error(vm, "Cannot convert object to primitive value");
+
+ return ret;
+ }
+
+ *dst = retval;
+
+ return NXT_OK;
}


diff -r 2fdad3cbbd74 -r 201af81dfa9b njs/njs_value.h
--- a/njs/njs_value.h Thu Jul 18 21:12:25 2019 +0300
+++ b/njs/njs_value.h Fri Jul 05 21:45:28 2019 +0300
@@ -114,6 +114,9 @@ typedef struct njs_date_s nj
typedef struct njs_property_next_s njs_property_next_t;
typedef struct njs_object_init_s njs_object_init_t;

+#if (!NXT_HAVE_GCC_ATTRIBUTE_ALIGNED)
+#error "aligned attribute is required"
+#endif

union njs_value_s {
/*
@@ -560,10 +563,6 @@ typedef enum {
*(value) = njs_value_undefined


_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[njs] Refactored working with non-primitive types.

Dmitry Volyntsev 234 July 19, 2019 04:30PM



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

Online Users

Guests: 270
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready