[njs] Splitting vmcode functionality from njs_vm.c into njs_vmcode.c

Dmitry Volyntsev xeioex at nginx.com
Tue Jul 23 17:02:48 UTC 2019


details:   https://hg.nginx.org/njs/rev/7fd8df281a37
branches:  
changeset: 1066:7fd8df281a37
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Jul 23 17:53:00 2019 +0300
description:
Splitting vmcode functionality from njs_vm.c into njs_vmcode.c

No functional changes.

diffstat:

 auto/sources     |     1 +
 njs/njs_core.h   |     1 +
 njs/njs_vm.c     |  2435 +-----------------------------------------------------
 njs/njs_vm.h     |   414 +---------
 njs/njs_vmcode.c |  2385 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 njs/njs_vmcode.h |   443 +++++++++
 6 files changed, 2832 insertions(+), 2847 deletions(-)

diffs (truncated from 5768 to 1000 lines):

diff -r 82c03a8af063 -r 7fd8df281a37 auto/sources
--- a/auto/sources	Sat Jul 20 13:31:59 2019 +0300
+++ b/auto/sources	Tue Jul 23 17:53:00 2019 +0300
@@ -32,6 +32,7 @@ NJS_LIB_SRCS=" \
    njs/njs.c \
    njs/njs_value.c \
    njs/njs_vm.c \
+   njs/njs_vmcode.c \
    njs/njs_boolean.c \
    njs/njs_number.c \
    njs/njs_string.c \
diff -r 82c03a8af063 -r 7fd8df281a37 njs/njs_core.h
--- a/njs/njs_core.h	Sat Jul 20 13:31:59 2019 +0300
+++ b/njs/njs_core.h	Tue Jul 23 17:53:00 2019 +0300
@@ -34,6 +34,7 @@
 #include <njs.h>
 #include <njs_value.h>
 #include <njs_vm.h>
+#include <njs_vmcode.h>
 #include <njs_variable.h>
 #include <njs_lexer.h>
 #include <njs_parser.h>
diff -r 82c03a8af063 -r 7fd8df281a37 njs/njs_vm.c
--- a/njs/njs_vm.c	Sat Jul 20 13:31:59 2019 +0300
+++ b/njs/njs_vm.c	Tue Jul 23 17:53:00 2019 +0300
@@ -9,33 +9,6 @@
 #include <string.h>
 
 
-struct njs_property_next_s {
-    uint32_t     index;
-    njs_array_t  *array;
-};
-
-
-/*
- * These functions are forbidden to inline to minimize JavaScript VM
- * interpreter memory footprint.  The size is less than 8K on AMD64
- * and should fit in CPU L1 instruction cache.
- */
-
-static njs_ret_t njs_string_concat(njs_vm_t *vm, njs_value_t *val1,
-    njs_value_t *val2);
-static njs_ret_t njs_values_equal(njs_vm_t *vm, njs_value_t *val1,
-    njs_value_t *val2);
-static njs_ret_t njs_primitive_values_compare(njs_vm_t *vm, njs_value_t *val1,
-    njs_value_t *val2);
-static njs_ret_t njs_function_frame_create(njs_vm_t *vm, njs_value_t *value,
-    const njs_value_t *this, uintptr_t nargs, nxt_bool_t ctor);
-static njs_object_t *njs_function_new_object(njs_vm_t *vm, njs_value_t *value);
-
-static njs_ret_t njs_vm_add_backtrace_entry(njs_vm_t *vm, njs_frame_t *frame);
-
-void njs_debug(njs_index_t index, njs_value_t *value);
-
-
 const nxt_str_t  njs_entry_main =           nxt_string("main");
 const nxt_str_t  njs_entry_module =         nxt_string("module");
 const nxt_str_t  njs_entry_native =         nxt_string("native");
@@ -43,2126 +16,6 @@ const nxt_str_t  njs_entry_unknown =    
 const nxt_str_t  njs_entry_anonymous =      nxt_string("anonymous");
 
 
-/*
- * The nJSVM is optimized for an ABIs where the first several arguments
- * are passed in registers (AMD64, ARM32/64): two pointers to the operand
- * values is passed as arguments although they are not always used.
- */
-
-nxt_int_t
-njs_vmcode_interpreter(njs_vm_t *vm)
-{
-    u_char                *catch, call;
-    njs_ret_t             ret;
-    njs_value_t           *retval, *value1, *value2;
-    njs_frame_t           *frame;
-    njs_native_frame_t    *previous;
-    njs_vmcode_generic_t  *vmcode;
-
-start:
-
-    for ( ;; ) {
-
-        vmcode = (njs_vmcode_generic_t *) vm->current;
-
-        /*
-         * The first operand is passed as is in value2 to
-         *   njs_vmcode_jump(),
-         *   njs_vmcode_if_true_jump(),
-         *   njs_vmcode_if_false_jump(),
-         *   njs_vmcode_validate(),
-         *   njs_vmcode_function_frame(),
-         *   njs_vmcode_function_call(),
-         *   njs_vmcode_return(),
-         *   njs_vmcode_try_start(),
-         *   njs_vmcode_try_continue(),
-         *   njs_vmcode_try_break(),
-         *   njs_vmcode_try_end(),
-         *   njs_vmcode_catch().
-         *   njs_vmcode_throw().
-         *   njs_vmcode_stop().
-         */
-        value2 = (njs_value_t *) vmcode->operand1;
-        value1 = NULL;
-
-        switch (vmcode->code.operands) {
-
-        case NJS_VMCODE_3OPERANDS:
-            value2 = njs_vmcode_operand(vm, vmcode->operand3);
-
-            /* Fall through. */
-
-        case NJS_VMCODE_2OPERANDS:
-            value1 = njs_vmcode_operand(vm, vmcode->operand2);
-        }
-
-        ret = vmcode->code.operation(vm, value1, value2);
-
-        /*
-         * On success an operation returns size of the bytecode,
-         * a jump offset or zero after the call or return operations.
-         * Jumps can return a negative offset.  Compilers can generate
-         *    (ret < 0 && ret >= NJS_PREEMPT)
-         * as a single unsigned comparision.
-         */
-
-        if (nxt_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
-            break;
-        }
-
-        vm->current += ret;
-
-        if (vmcode->code.retval) {
-            retval = njs_vmcode_operand(vm, vmcode->operand1);
-            njs_release(vm, retval);
-            *retval = vm->retval;
-        }
-    }
-
-    if (ret == NXT_ERROR) {
-
-        for ( ;; ) {
-            frame = (njs_frame_t *) vm->top_frame;
-
-            call = frame->native.call;
-            catch = frame->native.exception.catch;
-
-            if (catch != NULL) {
-                vm->current = catch;
-
-                if (vm->debug != NULL) {
-                    nxt_array_reset(vm->backtrace);
-                }
-
-                goto start;
-            }
-
-            if (vm->debug != NULL
-                && njs_vm_add_backtrace_entry(vm, frame) != NXT_OK)
-            {
-                return NXT_ERROR;
-            }
-
-            previous = frame->native.previous;
-            if (previous == NULL) {
-                return NXT_ERROR;
-            }
-
-            njs_vm_scopes_restore(vm, frame, previous);
-
-            if (frame->native.size != 0) {
-                vm->stack_size -= frame->native.size;
-                nxt_mp_free(vm->mem_pool, frame);
-            }
-
-            if (call) {
-                return NXT_ERROR;
-            }
-        }
-    }
-
-    /* NXT_ERROR, NJS_STOP. */
-
-    return ret;
-}
-
-
-nxt_int_t
-njs_vmcode_run(njs_vm_t *vm)
-{
-    njs_ret_t  ret;
-
-    vm->top_frame->call = 1;
-
-    if (nxt_slow_path(vm->count > 128)) {
-        njs_range_error(vm, "Maximum call stack size exceeded");
-        return NXT_ERROR;
-    }
-
-    vm->count++;
-
-    ret = njs_vmcode_interpreter(vm);
-    if (ret == NJS_STOP) {
-        ret = NJS_OK;
-    }
-
-    vm->count--;
-
-    return ret;
-}
-
-
-njs_ret_t
-njs_vmcode_object(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
-{
-    njs_object_t  *object;
-
-    object = njs_object_alloc(vm);
-
-    if (nxt_fast_path(object != NULL)) {
-        njs_set_object(&vm->retval, object);
-
-        return sizeof(njs_vmcode_object_t);
-    }
-
-    return NXT_ERROR;
-}
-
-
-njs_ret_t
-njs_vmcode_array(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
-{
-    uint32_t            length;
-    njs_array_t         *array;
-    njs_value_t         *value;
-    njs_vmcode_array_t  *code;
-
-    code = (njs_vmcode_array_t *) vm->current;
-
-    array = njs_array_alloc(vm, code->length, NJS_ARRAY_SPARE);
-
-    if (nxt_fast_path(array != NULL)) {
-
-        if (code->code.ctor) {
-            /* Array of the form [,,,], [1,,]. */
-            value = array->start;
-            length = array->length;
-
-            do {
-                njs_set_invalid(value);
-                value++;
-                length--;
-            } while (length != 0);
-
-        } else {
-            /* Array of the form [], [,,1], [1,2,3]. */
-            array->length = 0;
-        }
-
-        njs_set_array(&vm->retval, array);
-
-        return sizeof(njs_vmcode_array_t);
-    }
-
-    return NXT_ERROR;
-}
-
-
-njs_ret_t
-njs_vmcode_function(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
-{
-    njs_function_t         *function;
-    njs_function_lambda_t  *lambda;
-    njs_vmcode_function_t  *code;
-
-    code = (njs_vmcode_function_t *) vm->current;
-    lambda = code->lambda;
-
-    function = njs_function_alloc(vm, lambda, vm->active_frame->closures, 0);
-    if (nxt_slow_path(function == NULL)) {
-        return NXT_ERROR;
-    }
-
-    njs_set_function(&vm->retval, function);
-
-    return sizeof(njs_vmcode_function_t);
-}
-
-
-njs_ret_t
-njs_vmcode_this(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
-{
-    njs_frame_t        *frame;
-    njs_value_t        *value;
-    njs_vmcode_this_t  *code;
-
-    frame = (njs_frame_t *) vm->active_frame;
-    code = (njs_vmcode_this_t *) vm->current;
-
-    value = njs_vmcode_operand(vm, code->dst);
-    *value = frame->native.arguments[0];
-
-    return sizeof(njs_vmcode_this_t);
-}
-
-
-njs_ret_t
-njs_vmcode_arguments(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
-{
-    nxt_int_t               ret;
-    njs_frame_t             *frame;
-    njs_value_t             *value;
-    njs_vmcode_arguments_t  *code;
-
-    frame = (njs_frame_t *) vm->active_frame;
-
-    if (frame->native.arguments_object == NULL) {
-        ret = njs_function_arguments_object_init(vm, &frame->native);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return NXT_ERROR;
-        }
-    }
-
-    code = (njs_vmcode_arguments_t *) vm->current;
-
-    value = njs_vmcode_operand(vm, code->dst);
-    njs_set_object(value, frame->native.arguments_object);
-
-    return sizeof(njs_vmcode_arguments_t);
-}
-
-
-njs_ret_t
-njs_vmcode_regexp(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
-{
-    njs_regexp_t         *regexp;
-    njs_vmcode_regexp_t  *code;
-
-    code = (njs_vmcode_regexp_t *) vm->current;
-
-    regexp = njs_regexp_alloc(vm, code->pattern);
-
-    if (nxt_fast_path(regexp != NULL)) {
-        njs_set_regexp(&vm->retval, regexp);
-
-        return sizeof(njs_vmcode_regexp_t);
-    }
-
-    return NXT_ERROR;
-}
-
-
-njs_ret_t
-njs_vmcode_template_literal(njs_vm_t *vm, njs_value_t *invld1,
-    njs_value_t *retval)
-{
-    nxt_int_t    ret;
-    njs_array_t  *array;
-    njs_value_t  *value;
-
-    static const njs_function_t  concat = {
-          .native = 1,
-          .args_offset = 1,
-          .u.native = njs_string_prototype_concat
-    };
-
-    value = njs_vmcode_operand(vm, retval);
-
-    if (!njs_is_primitive(value)) {
-        array = njs_array(value);
-
-        ret = njs_function_frame(vm, (njs_function_t *) &concat,
-                                 (njs_value_t *) &njs_string_empty,
-                                 array->start, array->length, 0);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return ret;
-        }
-
-        ret = njs_function_frame_invoke(vm, (njs_index_t) retval);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return ret;
-        }
-    }
-
-    return sizeof(njs_vmcode_template_literal_t);
-}
-
-
-njs_ret_t
-njs_vmcode_object_copy(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
-{
-    njs_object_t    *object;
-    njs_function_t  *function;
-
-    switch (value->type) {
-
-    case NJS_OBJECT:
-        object = njs_object_value_copy(vm, value);
-        if (nxt_slow_path(object == NULL)) {
-            return NXT_ERROR;
-        }
-
-        break;
-
-    case NJS_FUNCTION:
-        function = njs_function_value_copy(vm, value);
-        if (nxt_slow_path(function == NULL)) {
-            return NXT_ERROR;
-        }
-
-        break;
-
-    default:
-        break;
-    }
-
-    vm->retval = *value;
-
-    njs_retain(value);
-
-    return sizeof(njs_vmcode_object_copy_t);
-}
-
-
-njs_ret_t
-njs_vmcode_property_get(njs_vm_t *vm, njs_value_t *object,
-    njs_value_t *property)
-{
-    njs_ret_t              ret;
-    njs_value_t            *retval;
-    njs_vmcode_prop_get_t  *code;
-
-    code = (njs_vmcode_prop_get_t *) vm->current;
-    retval = njs_vmcode_operand(vm, code->value);
-
-    ret = njs_value_property(vm, object, property, retval);
-    if (nxt_slow_path(ret == NXT_ERROR)) {
-        return ret;
-    }
-
-    vm->retval = *retval;
-
-    return sizeof(njs_vmcode_prop_get_t);
-}
-
-
-njs_ret_t
-njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *object,
-    njs_value_t *property)
-{
-    uint32_t               index, size;
-    njs_ret_t              ret;
-    njs_array_t            *array;
-    njs_value_t            *init, *value, name;
-    njs_object_t           *obj;
-    njs_object_prop_t      *prop;
-    nxt_lvlhsh_query_t     lhq;
-    njs_vmcode_prop_set_t  *code;
-
-    code = (njs_vmcode_prop_set_t *) vm->current;
-    init = njs_vmcode_operand(vm, code->value);
-
-    switch (object->type) {
-    case NJS_ARRAY:
-        index = njs_value_to_index(property);
-        if (nxt_slow_path(index == NJS_ARRAY_INVALID_INDEX)) {
-            njs_internal_error(vm,
-                               "invalid index while property initialization");
-            return NXT_ERROR;
-        }
-
-        array = object->data.u.array;
-
-        if (index >= array->length) {
-            size = index - array->length;
-
-            ret = njs_array_expand(vm, array, 0, size + 1);
-            if (nxt_slow_path(ret != NXT_OK)) {
-                return ret;
-            }
-
-            value = &array->start[array->length];
-
-            while (size != 0) {
-                njs_set_invalid(value);
-                value++;
-                size--;
-            }
-
-            array->length = index + 1;
-        }
-
-        /* GC: retain. */
-        array->start[index] = *init;
-
-        break;
-
-    case NJS_OBJECT:
-        ret = njs_value_to_string(vm, &name, property);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return NXT_ERROR;
-        }
-
-        njs_string_get(&name, &lhq.key);
-        lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length);
-        lhq.proto = &njs_object_hash_proto;
-        lhq.pool = vm->mem_pool;
-
-        obj = njs_object(object);
-
-        ret = nxt_lvlhsh_find(&obj->__proto__->shared_hash, &lhq);
-        if (ret == NXT_OK) {
-            prop = lhq.value;
-
-            if (prop->type == NJS_PROPERTY_HANDLER) {
-                ret = prop->value.data.u.prop_handler(vm, object, init,
-                                                      &vm->retval);
-                if (nxt_slow_path(ret != NXT_OK)) {
-                    return ret;
-                }
-
-                break;
-            }
-        }
-
-        prop = njs_object_prop_alloc(vm, &name, init, 1);
-        if (nxt_slow_path(prop == NULL)) {
-            return NXT_ERROR;
-        }
-
-        lhq.value = prop;
-        lhq.replace = 1;
-
-        ret = nxt_lvlhsh_insert(&obj->hash, &lhq);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            njs_internal_error(vm, "lvlhsh insert/replace failed");
-            return NXT_ERROR;
-        }
-
-        break;
-
-    default:
-        njs_internal_error(vm, "unexpected object type \"%s\" "
-                           "while property initialization",
-                           njs_type_string(object->type));
-
-        return NXT_ERROR;
-    }
-
-    return sizeof(njs_vmcode_prop_set_t);
-}
-
-
-njs_ret_t
-njs_vmcode_property_set(njs_vm_t *vm, njs_value_t *object,
-    njs_value_t *property)
-{
-    njs_ret_t              ret;
-    njs_value_t            *value;
-    njs_vmcode_prop_set_t  *code;
-
-    code = (njs_vmcode_prop_set_t *) vm->current;
-    value = njs_vmcode_operand(vm, code->value);
-
-    ret = njs_value_property_set(vm, object, property, value);
-    if (nxt_slow_path(ret == NXT_ERROR)) {
-        return ret;
-    }
-
-    return sizeof(njs_vmcode_prop_set_t);
-}
-
-
-njs_ret_t
-njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *object, njs_value_t *property)
-{
-    njs_ret_t             ret;
-    njs_object_prop_t     *prop;
-    const njs_value_t     *retval;
-    njs_property_query_t  pq;
-
-    retval = &njs_value_false;
-
-    njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0);
-
-    ret = njs_property_query(vm, &pq, object, property);
-
-    switch (ret) {
-
-    case NXT_OK:
-        prop = pq.lhq.value;
-
-        if (!njs_is_valid(&prop->value)) {
-            break;
-        }
-
-        retval = &njs_value_true;
-        break;
-
-    case NXT_DECLINED:
-        if (!njs_is_object(object) && !njs_is_external(object)) {
-            njs_type_error(vm, "property in on a primitive value");
-
-            return NXT_ERROR;
-        }
-
-        break;
-
-    case NXT_ERROR:
-    default:
-
-        return ret;
-    }
-
-    vm->retval = *retval;
-
-    return sizeof(njs_vmcode_3addr_t);
-}
-
-
-njs_ret_t
-njs_vmcode_property_delete(njs_vm_t *vm, njs_value_t *object,
-    njs_value_t *property)
-{
-    njs_ret_t             ret;
-    njs_object_prop_t     *prop, *whipeout;
-    njs_property_query_t  pq;
-
-    njs_property_query_init(&pq, NJS_PROPERTY_QUERY_DELETE, 1);
-
-    ret = njs_property_query(vm, &pq, object, property);
-
-    switch (ret) {
-
-    case NXT_OK:
-        prop = pq.lhq.value;
-
-        if (nxt_slow_path(!prop->configurable)) {
-            njs_type_error(vm, "Cannot delete property \"%V\" of %s",
-                           &pq.lhq.key, njs_type_string(object->type));
-            return NXT_ERROR;
-        }
-
-        if (nxt_slow_path(pq.shared)) {
-            whipeout = nxt_mp_align(vm->mem_pool, sizeof(njs_value_t),
-                                    sizeof(njs_object_prop_t));
-            if (nxt_slow_path(whipeout == NULL)) {
-                njs_memory_error(vm);
-                return NXT_ERROR;
-            }
-
-            njs_set_invalid(&whipeout->value);
-            whipeout->name = prop->name;
-            whipeout->type = NJS_WHITEOUT;
-
-            pq.lhq.replace = 0;
-            pq.lhq.value = whipeout;
-            pq.lhq.pool = vm->mem_pool;
-
-            ret = nxt_lvlhsh_insert(&pq.prototype->hash, &pq.lhq);
-            if (nxt_slow_path(ret != NXT_OK)) {
-                njs_internal_error(vm, "lvlhsh insert failed");
-                return NXT_ERROR;
-            }
-
-            break;
-        }
-
-        switch (prop->type) {
-        case NJS_PROPERTY:
-        case NJS_METHOD:
-            break;
-
-        case NJS_PROPERTY_REF:
-            njs_set_invalid(prop->value.data.u.value);
-            goto done;
-
-        case NJS_PROPERTY_HANDLER:
-            ret = prop->value.data.u.prop_handler(vm, object, NULL, NULL);
-            if (nxt_slow_path(ret != NXT_OK)) {
-                return ret;
-            }
-
-            goto done;
-
-        default:
-            njs_internal_error(vm, "unexpected property type \"%s\" "
-                               "while deleting",
-                               njs_prop_type_string(prop->type));
-
-            return NXT_ERROR;
-        }
-
-        /* GC: release value. */
-        prop->type = NJS_WHITEOUT;
-        njs_set_invalid(&prop->value);
-
-        break;
-
-    case NXT_DECLINED:
-        break;
-
-    case NXT_ERROR:
-    default:
-
-        return ret;
-    }
-
-done:
-
-    vm->retval = njs_value_true;
-
-    return sizeof(njs_vmcode_3addr_t);
-}
-
-
-njs_ret_t
-njs_vmcode_property_foreach(njs_vm_t *vm, njs_value_t *object,
-    njs_value_t *invld)
-{
-    void                       *obj;
-    njs_ret_t                  ret;
-    njs_property_next_t        *next;
-    const njs_extern_t         *ext_proto;
-    njs_vmcode_prop_foreach_t  *code;
-
-    if (njs_is_external(object)) {
-        ext_proto = object->external.proto;
-
-        if (ext_proto->foreach != NULL) {
-            obj = njs_extern_object(vm, object);
-
-            ret = ext_proto->foreach(vm, obj, &vm->retval);
-            if (nxt_slow_path(ret != NXT_OK)) {
-                return ret;
-            }
-        }
-
-        goto done;
-    }
-
-    next = nxt_mp_alloc(vm->mem_pool, sizeof(njs_property_next_t));
-    if (nxt_slow_path(next == NULL)) {
-        njs_memory_error(vm);
-        return NXT_ERROR;
-    }
-
-    next->index = 0;
-    next->array = njs_value_enumerate(vm, object, NJS_ENUM_KEYS, 0);
-    if (nxt_slow_path(next->array == NULL)) {
-        njs_memory_error(vm);
-        return NXT_ERROR;
-    }
-
-    vm->retval.data.u.next = next;
-
-done:
-
-    code = (njs_vmcode_prop_foreach_t *) vm->current;
-
-    return code->offset;
-}
-
-
-njs_ret_t
-njs_vmcode_property_next(njs_vm_t *vm, njs_value_t *object, njs_value_t *value)
-{
-    void                    *obj;
-    njs_ret_t               ret;
-    njs_value_t             *retval;
-    njs_property_next_t     *next;
-    const njs_extern_t      *ext_proto;
-    njs_vmcode_prop_next_t  *code;
-
-    code = (njs_vmcode_prop_next_t *) vm->current;
-    retval = njs_vmcode_operand(vm, code->retval);
-
-    if (njs_is_external(object)) {
-        ext_proto = object->external.proto;
-
-        if (ext_proto->next != NULL) {
-            obj = njs_extern_object(vm, object);
-
-            ret = ext_proto->next(vm, retval, obj, value);
-
-            if (ret == NXT_OK) {
-                return code->offset;
-            }
-
-            if (nxt_slow_path(ret == NXT_ERROR)) {
-                return ret;
-            }
-
-            /* ret == NJS_DONE. */
-        }
-
-        return sizeof(njs_vmcode_prop_next_t);
-    }
-
-    next = value->data.u.next;
-
-    if (next->index < next->array->length) {
-        *retval = next->array->data[next->index++];
-
-        return code->offset;
-    }
-
-    nxt_mp_free(vm->mem_pool, next);
-
-    return sizeof(njs_vmcode_prop_next_t);
-}
-
-
-njs_ret_t
-njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object,
-    njs_value_t *constructor)
-{
-    nxt_int_t          ret;
-    njs_value_t        value;
-    njs_object_t       *prototype, *proto;
-    const njs_value_t  *retval;
-
-    static njs_value_t prototype_string = njs_string("prototype");
-
-    if (!njs_is_function(constructor)) {
-        njs_type_error(vm, "right argument is not a function");
-        return NXT_ERROR;
-    }
-
-    retval = &njs_value_false;
-
-    if (njs_is_object(object)) {
-        value = njs_value_undefined;
-        ret = njs_value_property(vm, constructor, &prototype_string, &value);
-
-        if (nxt_slow_path(ret == NXT_ERROR)) {
-            return ret;
-        }
-
-        if (nxt_fast_path(ret == NXT_OK)) {
-
-            if (nxt_slow_path(!njs_is_object(&value))) {
-                njs_internal_error(vm, "prototype is not an object");
-                return NXT_ERROR;
-            }
-
-            prototype = njs_object(&value);
-            proto = njs_object(object);
-
-            do {
-                proto = proto->__proto__;
-
-                if (proto == prototype) {
-                    retval = &njs_value_true;
-                    break;
-                }
-
-            } while (proto != NULL);
-        }
-    }
-
-    vm->retval = *retval;
-
-    return sizeof(njs_vmcode_instance_of_t);
-}
-
-
-njs_ret_t
-njs_vmcode_increment(njs_vm_t *vm, njs_value_t *reference, njs_value_t *value)
-{
-    double       num;
-    njs_ret_t    ret;
-    njs_value_t  numeric;
-
-    if (nxt_slow_path(!njs_is_numeric(value))) {
-        ret = njs_value_to_numeric(vm, &numeric, value);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return ret;
-        }
-
-        num = njs_number(&numeric);
-
-    } else {
-        num = njs_number(value);
-    }
-
-    njs_release(vm, reference);
-
-    njs_set_number(reference, num + 1.0);
-    vm->retval = *reference;
-
-    return sizeof(njs_vmcode_3addr_t);
-}
-
-
-njs_ret_t
-njs_vmcode_decrement(njs_vm_t *vm, njs_value_t *reference, njs_value_t *value)
-{
-    double       num;
-    njs_ret_t    ret;
-    njs_value_t  numeric;
-
-    if (nxt_slow_path(!njs_is_numeric(value))) {
-        ret = njs_value_to_numeric(vm, &numeric, value);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return ret;
-        }
-
-        num = njs_number(&numeric);
-
-    } else {
-        num = njs_number(value);
-    }
-
-    njs_release(vm, reference);
-
-    njs_set_number(reference, num - 1.0);
-    vm->retval = *reference;
-
-    return sizeof(njs_vmcode_3addr_t);
-}
-
-
-njs_ret_t
-njs_vmcode_post_increment(njs_vm_t *vm, njs_value_t *reference,
-    njs_value_t *value)
-{
-    double  num;
-    njs_ret_t    ret;
-    njs_value_t  numeric;
-
-    if (nxt_slow_path(!njs_is_numeric(value))) {
-        ret = njs_value_to_numeric(vm, &numeric, value);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return ret;
-        }
-
-        num = njs_number(&numeric);
-
-    } else {
-        num = njs_number(value);
-    }
-
-    njs_release(vm, reference);
-
-    njs_set_number(reference, num + 1.0);
-    njs_set_number(&vm->retval, num);
-
-    return sizeof(njs_vmcode_3addr_t);
-}
-
-
-njs_ret_t
-njs_vmcode_post_decrement(njs_vm_t *vm, njs_value_t *reference,
-    njs_value_t *value)
-{
-    double       num;
-    njs_ret_t    ret;
-    njs_value_t  numeric;
-
-    if (nxt_slow_path(!njs_is_numeric(value))) {
-        ret = njs_value_to_numeric(vm, &numeric, value);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return ret;
-        }
-
-        num = njs_number(&numeric);
-
-    } else {
-        num = njs_number(value);
-    }
-
-    njs_release(vm, reference);
-
-    njs_set_number(reference, num - 1.0);
-    njs_set_number(&vm->retval, num);
-
-    return sizeof(njs_vmcode_3addr_t);
-}
-
-
-njs_ret_t
-njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
-{
-    /* ECMAScript 5.1: null, array and regexp are objects. */
-
-    static const njs_value_t  *types[NJS_TYPE_MAX] = {
-        &njs_string_object,
-        &njs_string_undefined,
-        &njs_string_boolean,
-        &njs_string_number,
-        &njs_string_string,
-        &njs_string_data,
-        &njs_string_external,
-        &njs_string_invalid,
-        &njs_string_undefined,
-        &njs_string_undefined,
-        &njs_string_undefined,
-        &njs_string_undefined,
-        &njs_string_undefined,


More information about the nginx-devel mailing list