[njs] Math object.

Igor Sysoev igor at sysoev.ru
Thu Mar 24 15:16:58 UTC 2016


details:   http://hg.nginx.org/njs/rev/e3bc4f6f3480
branches:  
changeset: 86:e3bc4f6f3480
user:      Igor Sysoev <igor at sysoev.ru>
date:      Wed Mar 23 15:27:14 2016 +0300
description:
Math object.

diffstat:

 Makefile                 |   14 +
 njs/njs_array.c          |    1 +
 njs/njs_builtin.c        |   22 +-
 njs/njs_disassembler.c   |    4 +-
 njs/njs_function.c       |   15 +-
 njs/njs_generator.c      |   42 +++-
 njs/njs_lexer_keyword.c  |    1 +
 njs/njs_math.c           |  554 +++++++++++++++++++++++++++++++++++++++++++++++
 njs/njs_math.h           |   17 +
 njs/njs_object.c         |   28 ++-
 njs/njs_object.h         |    2 +
 njs/njs_parser.c         |   37 +++-
 njs/njs_parser.h         |    4 +
 njs/njs_regexp.c         |    1 +
 njs/njs_vm.c             |   64 +++--
 njs/njs_vm.h             |   26 +-
 njs/test/njs_unit_test.c |   62 +++++
 17 files changed, 841 insertions(+), 53 deletions(-)

diffs (truncated from 1256 to 1000 lines):

diff -r 5995bd7637ff -r e3bc4f6f3480 Makefile
--- a/Makefile	Wed Mar 23 15:27:10 2016 +0300
+++ b/Makefile	Wed Mar 23 15:27:14 2016 +0300
@@ -18,6 +18,7 @@ NXT_BUILDDIR =	build
 	$(NXT_BUILDDIR)/njs_array.o \
 	$(NXT_BUILDDIR)/njs_function.o \
 	$(NXT_BUILDDIR)/njs_regexp.o \
+	$(NXT_BUILDDIR)/njs_math.o \
 	$(NXT_BUILDDIR)/njs_extern.o \
 	$(NXT_BUILDDIR)/njs_variable.o \
 	$(NXT_BUILDDIR)/njs_builtin.o \
@@ -46,6 +47,7 @@ NXT_BUILDDIR =	build
 		$(NXT_BUILDDIR)/njs_array.o \
 		$(NXT_BUILDDIR)/njs_function.o \
 		$(NXT_BUILDDIR)/njs_regexp.o \
+		$(NXT_BUILDDIR)/njs_math.o \
 		$(NXT_BUILDDIR)/njs_extern.o \
 		$(NXT_BUILDDIR)/njs_variable.o \
 		$(NXT_BUILDDIR)/njs_builtin.o \
@@ -220,6 +222,18 @@ tarball:
 		-I$(NXT_LIB) -Injs $(NXT_PCRE_CFLAGS) \
 		njs/njs_regexp.c
 
+$(NXT_BUILDDIR)/njs_math.o: \
+	$(NXT_BUILDDIR)/libnxt.a \
+	njs/njscript.h \
+	njs/njs_vm.h \
+	njs/njs_object.h \
+	njs/njs_math.h \
+	njs/njs_math.c \
+
+	$(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_math.o $(NXT_CFLAGS) \
+		-I$(NXT_LIB) -Injs \
+		njs/njs_math.c
+
 $(NXT_BUILDDIR)/njs_extern.o: \
 	$(NXT_BUILDDIR)/libnxt.a \
 	njs/njscript.h \
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_array.c
--- a/njs/njs_array.c	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_array.c	Wed Mar 23 15:27:14 2016 +0300
@@ -129,6 +129,7 @@ njs_array_alloc(njs_vm_t *vm, uint32_t l
     nxt_lvlhsh_init(&array->object.hash);
     nxt_lvlhsh_init(&array->object.shared_hash);
     array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY];
+    array->object.shared = 0;
     array->size = size;
     array->length = length;
 
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_builtin.c
--- a/njs/njs_builtin.c	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_builtin.c	Wed Mar 23 15:27:14 2016 +0300
@@ -19,6 +19,7 @@
 #include <njs_array.h>
 #include <njs_function.h>
 #include <njs_regexp.h>
+#include <njs_math.h>
 #include <string.h>
 
 
@@ -33,7 +34,7 @@ njs_builtin_objects_create(njs_vm_t *vm)
 {
     nxt_int_t                         ret;
     nxt_uint_t                        i;
-    njs_object_t                      *prototypes;
+    njs_object_t                      *objects, *prototypes;
     njs_function_t                    *functions;
 
     static const njs_object_init_t    *prototype_init[] = {
@@ -71,6 +72,10 @@ njs_builtin_objects_create(njs_vm_t *vm)
         { njs_eval_function,        { 0 } },
     };
 
+    static const njs_object_init_t    *objects_init[] = {
+        &njs_math_object_init,
+    };
+
     static const njs_object_prop_t  null_proto_property = {
         .type = NJS_WHITEOUT,
         .name = njs_string("__proto__"),
@@ -83,6 +88,19 @@ njs_builtin_objects_create(njs_vm_t *vm)
         return NXT_ERROR;
     }
 
+    objects = vm->shared->objects;
+
+    for (i = NJS_OBJECT_MATH; i < NJS_OBJECT_MAX; i++) {
+        ret = njs_object_hash_create(vm, &objects[i].shared_hash,
+                                     objects_init[i]->properties,
+                                     objects_init[i]->items);
+        if (nxt_slow_path(ret != NXT_OK)) {
+            return NXT_ERROR;
+        }
+
+        objects[i].shared = 1;
+    }
+
     prototypes = vm->shared->prototypes;
 
     for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
@@ -99,9 +117,9 @@ njs_builtin_objects_create(njs_vm_t *vm)
     functions = vm->shared->functions;
 
     for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
+        functions[i].object.shared = 0;
         functions[i].native = 1;
         functions[i].args_offset = 1;
-        functions[i].shared = 0;
         functions[i].u.native = native_functions[i].native;
         functions[i].args_types[0] = native_functions[i].args_types[0];
         functions[i].args_types[1] = native_functions[i].args_types[1];
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_disassembler.c
--- a/njs/njs_disassembler.c	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_disassembler.c	Wed Mar 23 15:27:14 2016 +0300
@@ -35,10 +35,10 @@ static njs_code_name_t  code_names[] = {
           nxt_string("OBJECT          ") },
     { njs_vmcode_function, sizeof(njs_vmcode_function_t),
           nxt_string("FUNCTION        ") },
-    { njs_vmcode_function_copy, sizeof(njs_vmcode_function_copy_t),
-          nxt_string("FUNCTION COPY   ") },
     { njs_vmcode_regexp, sizeof(njs_vmcode_regexp_t),
           nxt_string("REGEXP          ") },
+    { njs_vmcode_object_copy, sizeof(njs_vmcode_object_copy_t),
+          nxt_string("OBJECT COPY     ") },
 
     { njs_vmcode_property_get, sizeof(njs_vmcode_prop_get_t),
           nxt_string("PROPERTY GET    ") },
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_function.c
--- a/njs/njs_function.c	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_function.c	Wed Mar 23 15:27:14 2016 +0300
@@ -31,8 +31,15 @@ njs_function_alloc(njs_vm_t *vm)
     function = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_function_t));
 
     if (nxt_fast_path(function != NULL)) {
+        /*
+         * nxt_mem_cache_zalloc() does also:
+         *   nxt_lvlhsh_init(&function->object.hash);
+         *   nxt_lvlhsh_init(&function->object.shared_hash);
+         *   function->object.__proto__ = NULL;
+         */
+
+        function->object.shared = 1;
         function->args_offset = 1;
-        function->shared = 1;
 
         function->u.lambda = nxt_mem_cache_zalloc(vm->mem_cache_pool,
                                                  sizeof(njs_function_lambda_t));
@@ -52,7 +59,7 @@ njs_function_value_copy(njs_vm_t *vm, nj
 
     function = value->data.u.function;
 
-    if (!function->shared) {
+    if (!function->object.shared) {
         return function;
     }
 
@@ -61,7 +68,7 @@ njs_function_value_copy(njs_vm_t *vm, nj
     if (nxt_fast_path(function != NULL)) {
         *function = *value->data.u.function;
         function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
-        function->shared = 0;
+        function->object.shared = 0;
         value->data.u.function = function;
     }
 
@@ -458,7 +465,7 @@ njs_function_prototype_bind(njs_vm_t *vm
     *function = *args[0].data.u.function;
 
     function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
-    function->shared = 0;
+    function->object.shared = 0;
 
     if (nargs == 1) {
         args = (njs_value_t *) &njs_value_void;
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_generator.c
--- a/njs/njs_generator.c	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_generator.c	Wed Mar 23 15:27:14 2016 +0300
@@ -25,6 +25,8 @@ static nxt_int_t njs_generator(njs_vm_t 
     njs_parser_node_t *node);
 static nxt_int_t njs_generate_name(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node);
+static nxt_int_t njs_generate_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node);
 static nxt_int_t njs_generate_variable(njs_parser_t *parser,
     njs_parser_node_t *node);
 static nxt_int_t njs_generate_if_statement(njs_vm_t *vm, njs_parser_t *parser,
@@ -289,6 +291,9 @@ njs_generator(njs_vm_t *vm, njs_parser_t
     case NJS_TOKEN_NAME:
         return njs_generate_name(vm, parser, node);
 
+    case NJS_TOKEN_MATH:
+        return njs_generate_builtin_object(vm, parser, node);
+
     case NJS_TOKEN_FUNCTION:
         return njs_generate_function_declaration(vm, parser, node);
 
@@ -319,9 +324,9 @@ njs_generator(njs_vm_t *vm, njs_parser_t
 static nxt_int_t
 njs_generate_name(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
 {
-    njs_index_t                 index;
-    njs_value_t                 *value;
-    njs_vmcode_function_copy_t  *copy;
+    njs_index_t               index;
+    njs_value_t               *value;
+    njs_vmcode_object_copy_t  *copy;
 
     index = node->u.variable->index;
     value = njs_variable_value(parser, index);
@@ -333,12 +338,12 @@ njs_generate_name(njs_vm_t *vm, njs_pars
             return node->index;
         }
 
-        njs_generate_code(parser, njs_vmcode_function_copy_t, copy);
-        copy->code.operation = njs_vmcode_function_copy;
+        njs_generate_code(parser, njs_vmcode_object_copy_t, copy);
+        copy->code.operation = njs_vmcode_object_copy;
         copy->code.operands = NJS_VMCODE_2OPERANDS;
         copy->code.retval = NJS_VMCODE_RETVAL;
         copy->retval = node->index;
-        copy->function = index;
+        copy->object = index;
 
         return NXT_OK;
     }
@@ -348,6 +353,31 @@ njs_generate_name(njs_vm_t *vm, njs_pars
 
 
 static nxt_int_t
+njs_generate_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node)
+{
+    njs_index_t               index;
+    njs_vmcode_object_copy_t  *copy;
+
+    index = node->index;
+
+    node->index = njs_generator_dest_index(vm, parser, node);
+    if (nxt_slow_path(node->index == NJS_INDEX_ERROR)) {
+        return node->index;
+    }
+
+    njs_generate_code(parser, njs_vmcode_object_copy_t, copy);
+    copy->code.operation = njs_vmcode_object_copy;
+    copy->code.operands = NJS_VMCODE_2OPERANDS;
+    copy->code.retval = NJS_VMCODE_RETVAL;
+    copy->retval = node->index;
+    copy->object = index;
+
+    return NXT_OK;
+}
+
+
+static nxt_int_t
 njs_generate_variable(njs_parser_t *parser, njs_parser_node_t *node)
 {
     njs_value_t            *value;
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_lexer_keyword.c
--- a/njs/njs_lexer_keyword.c	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_lexer_keyword.c	Wed Mar 23 15:27:14 2016 +0300
@@ -73,6 +73,7 @@ static const njs_keyword_t  njs_keywords
     /* Builtin objects. */
 
     { nxt_string("this"),          NJS_TOKEN_THIS, 0 },
+    { nxt_string("Math"),          NJS_TOKEN_MATH, 0 },
 
     /* Builtin functions. */
 
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_math.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/njs/njs_math.c	Wed Mar 23 15:27:14 2016 +0300
@@ -0,0 +1,554 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_stub.h>
+#include <nxt_array.h>
+#include <nxt_lvlhsh.h>
+#include <nxt_mem_cache_pool.h>
+#include <njscript.h>
+#include <njs_vm.h>
+#include <njs_number.h>
+#include <njs_object.h>
+#include <njs_function.h>
+#include <math.h>
+
+
+static njs_ret_t
+njs_object_math_abs(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, fabs(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_acos(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, acos(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_asin(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, asin(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_atan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, atan(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_atan2(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  y, x;
+
+    y = NJS_NAN;
+    x = NJS_NAN;
+
+    if (nargs > 1) {
+        y = args[1].data.u.number;
+    }
+
+    if (nargs > 2) {
+        x = args[2].data.u.number;
+    }
+
+    njs_number_set(&vm->retval, atan2(y, x));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_ceil(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, ceil(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_cos(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, cos(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_exp(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, exp(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_floor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, floor(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_log(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, log(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_max(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double      num;
+    nxt_uint_t  i;
+
+    if (nargs > 1) {
+        for (i = 1; i < nargs; i++) {
+            if (!njs_is_numeric(&args[i])) {
+                vm->frame->trap_scratch.data.u.value = &args[i];
+                return NJS_TRAP_NUMBER_ARG;
+            }
+        }
+
+        num = args[1].data.u.number;
+
+        for (i = 2; i < nargs; i++) {
+            num = fmax(num, args[i].data.u.number);
+        }
+
+    } else {
+        num = -NJS_INFINITY;
+    }
+
+    njs_number_set(&vm->retval, num);
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_min(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double      num;
+    nxt_uint_t  i;
+
+    if (nargs > 1) {
+        for (i = 1; i < nargs; i++) {
+            if (!njs_is_numeric(&args[i])) {
+                vm->frame->trap_scratch.data.u.value = &args[i];
+                return NJS_TRAP_NUMBER_ARG;
+            }
+        }
+
+        num = args[1].data.u.number;
+
+        for (i = 2; i < nargs; i++) {
+            num = fmin(num, args[i].data.u.number);
+        }
+
+    } else {
+        num = NJS_INFINITY;
+    }
+
+    njs_number_set(&vm->retval, num);
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_pow(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  base, exponent;
+
+    base = NJS_NAN;
+    exponent = NJS_NAN;
+
+    if (nargs > 1) {
+        base = args[1].data.u.number;
+    }
+
+    if (nargs > 2) {
+        exponent = args[2].data.u.number;
+    }
+
+    njs_number_set(&vm->retval, pow(base, exponent));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_round(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, round(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_sin(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, sin(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_sqrt(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, sqrt(num));
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_tan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double  num;
+
+    if (nargs > 1) {
+        num = args[1].data.u.number;
+
+    } else {
+        num = NJS_NAN;
+    }
+
+    njs_number_set(&vm->retval, tan(num));
+
+    return NXT_OK;
+}
+
+
+static const njs_object_prop_t  njs_math_object_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("E"),
+        .value = njs_value(NJS_NUMBER, 1, 2.718281828459045),
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("LN10"),
+        .value = njs_value(NJS_NUMBER, 1, 2.302585092994046),
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("LN2"),
+        .value = njs_value(NJS_NUMBER, 1, 0.6931471805599453),
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("LOG10E"),
+        .value = njs_value(NJS_NUMBER, 1, 0.4342944819032518),
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("LOG2E"),
+        .value = njs_value(NJS_NUMBER, 1, 1.4426950408889634),
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("PI"),
+        .value = njs_value(NJS_NUMBER, 1, 3.141592653589793),
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("SQRT1_2"),
+        .value = njs_value(NJS_NUMBER, 1, 0.7071067811865476),
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("SQRT2"),
+        .value = njs_value(NJS_NUMBER, 1, 1.4142135623730951),
+    },
+
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("__proto__"),
+        .value = njs_native_getter(njs_object_prototype_get_proto),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("abs"),
+        .value = njs_native_function(njs_object_math_abs, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("acos"),
+        .value = njs_native_function(njs_object_math_acos, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("asin"),
+        .value = njs_native_function(njs_object_math_asin, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("atan"),
+        .value = njs_native_function(njs_object_math_atan, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("atan2"),
+        .value = njs_native_function(njs_object_math_atan2, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("ceil"),
+        .value = njs_native_function(njs_object_math_ceil, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("cos"),
+        .value = njs_native_function(njs_object_math_cos, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("exp"),
+        .value = njs_native_function(njs_object_math_exp, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("floor"),
+        .value = njs_native_function(njs_object_math_floor, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("log"),
+        .value = njs_native_function(njs_object_math_log, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("max"),
+        .value = njs_native_function(njs_object_math_max, 0, 0),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("min"),
+        .value = njs_native_function(njs_object_math_min, 0, 0),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("pow"),
+        .value = njs_native_function(njs_object_math_pow, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("round"),
+        .value = njs_native_function(njs_object_math_round, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("sin"),
+        .value = njs_native_function(njs_object_math_sin, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("sqrt"),
+        .value = njs_native_function(njs_object_math_sqrt, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("tan"),
+        .value = njs_native_function(njs_object_math_tan, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
+    },
+};
+
+
+const njs_object_init_t  njs_math_object_init = {
+    njs_math_object_properties,
+    nxt_nitems(njs_math_object_properties),
+};
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_math.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/njs/njs_math.h	Wed Mar 23 15:27:14 2016 +0300
@@ -0,0 +1,17 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NJS_MATH_H_INCLUDED_
+#define _NJS_MATH_H_INCLUDED_
+
+
+#include <math.h>
+
+
+extern const njs_object_init_t  njs_math_object_init;
+
+
+#endif /* _NJS_MATH_H_INCLUDED_ */
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_object.c
--- a/njs/njs_object.c	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_object.c	Wed Mar 23 15:27:14 2016 +0300
@@ -34,6 +34,31 @@ njs_object_alloc(njs_vm_t *vm)
         nxt_lvlhsh_init(&object->hash);
         nxt_lvlhsh_init(&object->shared_hash);
         object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+        object->shared = 0;
+    }
+
+    return object;
+}
+
+
+njs_object_t *
+njs_object_value_copy(njs_vm_t *vm, njs_value_t *value)
+{
+    njs_object_t  *object;
+
+    object = value->data.u.object;
+
+    if (!object->shared) {
+        return object;
+    }
+
+    object = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_object_t));
+
+    if (nxt_fast_path(object != NULL)) {
+        *object = *value->data.u.object;
+        object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+        object->shared = 0;
+        value->data.u.object = object;
     }
 
     return object;
@@ -51,6 +76,7 @@ njs_object_value_alloc(njs_vm_t *vm, con
     if (nxt_fast_path(ov != NULL)) {
         nxt_lvlhsh_init(&ov->object.hash);
         nxt_lvlhsh_init(&ov->object.shared_hash);
+        ov->object.shared = 0;
 
         index = njs_primitive_prototype_index(type);
         ov->object.__proto__ = &vm->prototypes[index];
@@ -413,7 +439,7 @@ const njs_object_init_t  njs_object_cons
 };
 
 
-static njs_ret_t
+njs_ret_t
 njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
 {
     njs_object_t  *proto;
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_object.h
--- a/njs/njs_object.h	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_object.h	Wed Mar 23 15:27:14 2016 +0300
@@ -44,6 +44,7 @@ struct njs_object_init_s {
 
 
 njs_object_t *njs_object_alloc(njs_vm_t *vm);
+njs_object_t *njs_object_value_copy(njs_vm_t *vm, njs_value_t *value);
 njs_object_t *njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value,
     nxt_uint_t type);
 njs_object_prop_t *njs_object_property(njs_vm_t *vm, njs_object_t *obj,
@@ -55,6 +56,7 @@ njs_ret_t njs_object_constructor(njs_vm_
 njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name);
 njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
 njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value);
+njs_ret_t njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
 njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
 
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_parser.c
--- a/njs/njs_parser.c	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_parser.c	Wed Mar 23 15:27:14 2016 +0300
@@ -68,6 +68,8 @@ static njs_token_t njs_parser_throw_stat
     njs_parser_t *parser);
 static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm,
     njs_parser_t *parser);
+static njs_token_t njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node);
 static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *obj);
 static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser,
@@ -1470,7 +1472,7 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
             break;
         }
 
-        parser->code_size += sizeof(njs_vmcode_function_copy_t);
+        parser->code_size += sizeof(njs_vmcode_object_copy_t);
         node->lvalue = NJS_LVALUE_ENABLED;
         node->u.variable = var;
         break;
@@ -1588,6 +1590,9 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
         node->index = NJS_INDEX_THIS;
         break;
 
+    case NJS_TOKEN_MATH:
+        return njs_parser_builtin_object(vm, parser, node);
+
     case NJS_TOKEN_OBJECT_CONSTRUCTOR:
         node->index = NJS_INDEX_OBJECT;
         break;
@@ -1632,6 +1637,36 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
 
 
 static njs_token_t
+njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node)
+{
+    nxt_uint_t      index, level;
+    njs_value_t     *value;
+    njs_variable_t  *var;
+
+    var = njs_parser_variable(vm, parser, &level);
+    if (nxt_slow_path(var == NULL)) {
+        return NJS_TOKEN_ERROR;
+    }
+
+    var->state = NJS_VARIABLE_DECLARED;
+    node->index = var->index;
+
+    value = njs_variable_value(parser, node->index);
+
+    index = node->token - NJS_TOKEN_FIRST_OBJECT;
+    value->data.u.object = &vm->shared->objects[index];
+    value->type = NJS_OBJECT;
+    value->data.truth = 1;
+
+    parser->node = node;
+    parser->code_size += sizeof(njs_vmcode_object_copy_t);
+
+    return njs_lexer_token(parser->lexer);
+}
+
+
+static njs_token_t
 njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj)
 {
     njs_token_t        token;
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_parser.h
--- a/njs/njs_parser.h	Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_parser.h	Wed Mar 23 15:27:14 2016 +0300
@@ -159,6 +159,10 @@ typedef enum {
 
     NJS_TOKEN_THIS,
 
+#define NJS_TOKEN_FIRST_OBJECT     NJS_TOKEN_MATH
+
+    NJS_TOKEN_MATH,
+
     NJS_TOKEN_OBJECT_CONSTRUCTOR,
     NJS_TOKEN_ARRAY_CONSTRUCTOR,
     NJS_TOKEN_FUNCTION_CONSTRUCTOR,



More information about the nginx-devel mailing list