]> git.kaiwu.me - njs.git/commitdiff
nJSVM disassembler changes.
authorIgor Sysoev <igor@sysoev.ru>
Wed, 25 Nov 2015 14:22:41 +0000 (17:22 +0300)
committerIgor Sysoev <igor@sysoev.ru>
Wed, 25 Nov 2015 14:22:41 +0000 (17:22 +0300)
Makefile
njs/njs_array.c
njs/njs_disassembler.c
njs/njs_function.c
njs/njs_generator.c
njs/njs_number.c
njs/njs_object.c
njs/njs_vm.h
njs/njscript.h
njs/test/njs_unit_test.c

index b6c7a20ee8956d2184dddbc0667f63c35d5e3cb2..baad353dfb6e08dcd1c2a5936778ef3e6386f366 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -69,7 +69,7 @@ all:  test lib_test
 test:  \
        $(NXT_BUILDDIR)/njs_unit_test \
 
-       $(NXT_BUILDDIR)/njs_unit_test
+       $(NXT_BUILDDIR)/njs_unit_test d
 
 clean:
        rm -rf $(NXT_BUILDDIR)
index d336d522da820ee6fba4f68f533b8609a98928fa..a01f9b23dbf38d9d7df099ec967827bf01155b0d 100644 (file)
@@ -9,6 +9,7 @@
 #include <nxt_alignment.h>
 #include <nxt_stub.h>
 #include <nxt_djb_hash.h>
+#include <nxt_array.h>
 #include <nxt_lvlhsh.h>
 #include <nxt_mem_cache_pool.h>
 #include <njscript.h>
index e234a6fd89a2e71d87db9ca2cb513d1422e7289c..b7d9db5a033ae95e7b5b99aaf8e5966ab1685252 100644 (file)
 #include <njs_regexp.h>
 #include <njs_variable.h>
 #include <njs_parser.h>
+#include <stdio.h>
+
+
+static void njs_disassemble(u_char *start, u_char *end);
 
 
 typedef struct {
@@ -29,8 +33,6 @@ static njs_code_name_t  code_names[] = {
 
     { njs_vmcode_object_create, sizeof(njs_vmcode_object_t),
           nxt_string("OBJECT CREATE   ") },
-    { njs_vmcode_array_create, sizeof(njs_vmcode_array_t),
-          nxt_string("ARRAY CREATE    ") },
     { njs_vmcode_function_create, sizeof(njs_vmcode_function_create_t),
           nxt_string("FUNCTION CREATE ") },
     { njs_vmcode_regexp_create, sizeof(njs_vmcode_regexp_t),
@@ -44,21 +46,17 @@ static njs_code_name_t  code_names[] = {
           nxt_string("PROPERTY IN     ") },
     { njs_vmcode_property_delete, sizeof(njs_vmcode_3addr_t),
           nxt_string("PROPERTY DELETE ") },
-    { njs_vmcode_property_each_start, sizeof(njs_vmcode_prop_start_t),
-          nxt_string("PROPERTY START  ") },
-    { njs_vmcode_property_each, sizeof(njs_vmcode_prop_each_t),
-          nxt_string("PROPERTY EACH   ") },
     { njs_vmcode_instance_of, sizeof(njs_vmcode_instance_of_t),
           nxt_string("INSTANCE OF     ") },
 
     { njs_vmcode_function, sizeof(njs_vmcode_function_t),
           nxt_string("FUNCTION        ") },
-    { njs_vmcode_method, sizeof(njs_vmcode_method_t),
-          nxt_string("METHOD          ") },
     { njs_vmcode_call, sizeof(njs_vmcode_call_t),
           nxt_string("CALL            ") },
     { njs_vmcode_return, sizeof(njs_vmcode_stop_t),
           nxt_string("RETURN          ") },
+    { njs_vmcode_stop, sizeof(njs_vmcode_stop_t),
+          nxt_string("STOP            ") },
 
     { njs_vmcode_increment, sizeof(njs_vmcode_3addr_t),
           nxt_string("INC             ") },
@@ -138,23 +136,8 @@ static njs_code_name_t  code_names[] = {
     { njs_vmcode_validate, sizeof(njs_vmcode_validate_t),
           nxt_string("VALIDATE        ") },
 
-    { njs_vmcode_if_true_jump, sizeof(njs_vmcode_cond_jump_t),
-          nxt_string("JUMP IF TRUE    ") },
-    { njs_vmcode_if_false_jump, sizeof(njs_vmcode_cond_jump_t),
-          nxt_string("JUMP IF FALSE   ") },
-    { njs_vmcode_jump, sizeof(njs_vmcode_jump_t),
-          nxt_string("JUMP            ") },
-    { njs_vmcode_stop, sizeof(njs_vmcode_stop_t),
-          nxt_string("STOP            ") },
-
-    { njs_vmcode_try_start, sizeof(njs_vmcode_try_start_t),
-          nxt_string("TRY START       ") },
-    { njs_vmcode_try_end, sizeof(njs_vmcode_try_end_t),
-          nxt_string("TRY END         ") },
     { njs_vmcode_throw, sizeof(njs_vmcode_throw_t),
           nxt_string("THROW           ") },
-    { njs_vmcode_catch, sizeof(njs_vmcode_catch_t),
-          nxt_string("CATCH           ") },
     { njs_vmcode_finally, sizeof(njs_vmcode_finally_t),
           nxt_string("FINALLY         ") },
 
@@ -162,30 +145,150 @@ static njs_code_name_t  code_names[] = {
 
 
 void
-njs_disassembler(u_char *start, u_char *end, nxt_str_t *text)
+njs_disassembler(njs_vm_t *vm)
 {
-    u_char                  *p;
-    nxt_uint_t              n;
-    nxt_str_t               *name;
-    njs_vmcode_1addr_t      *code1;
-    njs_vmcode_2addr_t      *code2;
-    njs_vmcode_3addr_t      *code3;
-    njs_vmcode_method_t     *method;
-    njs_code_name_t         *code_name;
-    njs_vmcode_operation_t  operation;
-
-    static nxt_str_t        unknown = nxt_string("UNKOWN");
-
-    (void) name;
-    (void) code1;
-    (void) code2;
-    (void) code3;
-    (void) method;
+    nxt_uint_t     n;
+    njs_vm_code_t  *code;
+
+    code = vm->code->start;
+    n = vm->code->items;
+
+    while(n != 0) {
+        njs_disassemble(code->start, code->end);
+        code++;
+        n--;
+    }
+}
+
+
+static void
+njs_disassemble(u_char *start, u_char *end)
+{
+    u_char                   *p;
+    nxt_str_t                *name;
+    nxt_uint_t               n;
+    const char               *sign;
+    njs_code_name_t          *code_name;
+    njs_vmcode_jump_t        *jump;
+    njs_vmcode_1addr_t       *code1;
+    njs_vmcode_2addr_t       *code2;
+    njs_vmcode_3addr_t       *code3;
+    njs_vmcode_array_t       *array;
+    njs_vmcode_catch_t       *catch;
+    njs_vmcode_method_t      *method;
+    njs_vmcode_try_end_t     *try_end;
+    njs_vmcode_try_start_t   *try_start;
+    njs_vmcode_operation_t   operation;
+    njs_vmcode_cond_jump_t   *cond_jump;
+    njs_vmcode_prop_each_t   *each;
+    njs_vmcode_prop_start_t  *prop_start;
 
     p = start;
 
     while (p < end) {
         operation = *(njs_vmcode_operation_t *) p;
+
+        if (operation == njs_vmcode_array_create) {
+            array = (njs_vmcode_array_t *) p;
+            p += sizeof(njs_vmcode_array_t);
+
+            printf("ARRAY CREATE      %04lX %ld\n",
+                   array->retval, array->length);
+
+            continue;
+        }
+
+        if (operation == njs_vmcode_if_true_jump) {
+            cond_jump = (njs_vmcode_cond_jump_t *) p;
+            p += sizeof(njs_vmcode_cond_jump_t);
+            sign = (cond_jump->offset >= 0) ? "+" : "";
+
+            printf("JUMP IF TRUE      %04lX %s%ld\n",
+                   cond_jump->cond, sign, cond_jump->offset);
+
+            continue;
+        }
+
+        if (operation == njs_vmcode_if_false_jump) {
+            cond_jump = (njs_vmcode_cond_jump_t *) p;
+            p += sizeof(njs_vmcode_cond_jump_t);
+            sign = (cond_jump->offset >= 0) ? "+" : "";
+
+            printf("JUMP IF FALSE     %04lX %s%ld\n",
+                   cond_jump->cond, sign, cond_jump->offset);
+
+            continue;
+        }
+
+        if (operation == njs_vmcode_jump) {
+            jump = (njs_vmcode_jump_t *) p;
+            p += sizeof(njs_vmcode_jump_t);
+            sign = (jump->offset >= 0) ? "+" : "";
+
+            printf("JUMP              %s%ld\n", sign, jump->offset);
+
+            continue;
+        }
+
+        if (operation == njs_vmcode_method) {
+            method = (njs_vmcode_method_t *) p;
+            p += sizeof(njs_vmcode_method_t);
+
+            printf("METHOD            %04lX %04lX %04lX %d\n", method->function,
+                   method->object, method->method, method->code.nargs);
+
+            continue;
+        }
+
+        if (operation == njs_vmcode_property_each_start) {
+            prop_start = (njs_vmcode_prop_start_t *) p;
+            p += sizeof(njs_vmcode_prop_start_t);
+
+            printf("PROPERTY START    %04lX %04lX +%ld\n",
+                   prop_start->each, prop_start->object, prop_start->offset);
+
+            continue;
+        }
+
+        if (operation == njs_vmcode_property_each) {
+            each = (njs_vmcode_prop_each_t *) p;
+            p += sizeof(njs_vmcode_prop_each_t);
+
+            printf("PROPERTY EACH     %04lX %04lX %04lX %ld\n",
+                   each->retval, each->object, each->each, each->offset);
+
+            continue;
+        }
+
+        if (operation == njs_vmcode_try_start) {
+            try_start = (njs_vmcode_try_start_t *) p;
+            p += sizeof(njs_vmcode_try_start_t);
+
+            printf("TRY START         %04lX +%ld\n",
+                   try_start->value, try_start->offset);
+
+            continue;
+        }
+
+        if (operation == njs_vmcode_catch) {
+            catch = (njs_vmcode_catch_t *) p;
+            p += sizeof(njs_vmcode_catch_t);
+
+            printf("CATCH             %04lX +%ld\n",
+                   catch->exception, catch->offset);
+
+            continue;
+        }
+
+        if (operation == njs_vmcode_try_end) {
+            try_end = (njs_vmcode_try_end_t *) p;
+            p += sizeof(njs_vmcode_try_end_t);
+
+            printf("TRY END           +%ld\n", try_end->offset);
+
+            continue;
+        }
+
         code_name = code_names;
         n = nxt_nitems(code_names);
 
@@ -193,26 +296,26 @@ njs_disassembler(u_char *start, u_char *end, nxt_str_t *text)
              if (operation == code_name->operation) {
                  name = &code_name->name;
 
-                 if (code_name->size == sizeof(njs_vmcode_method_t)) {
-                     method = (njs_vmcode_method_t *) p;
-                     nxt_log_error(NXT_LOG_INFO, log, "%V  %p %p %p %p",
-                                   name, method->function, method->object,
-                                   method->method, method->code.nargs);
-
-                 } else if (code_name->size == sizeof(njs_vmcode_3addr_t)) {
+                 if (code_name->size == sizeof(njs_vmcode_3addr_t)) {
                      code3 = (njs_vmcode_3addr_t *) p;
-                     nxt_log_error(NXT_LOG_INFO, log, "%V  %p %p %p",
-                                   name, code3->dst, code3->src1, code3->src2);
+
+                     printf("%*s  %04lX %04lX %04lX\n",
+                            (int) name->len, name->data,
+                            code3->dst, code3->src1, code3->src2);
 
                  } else if (code_name->size == sizeof(njs_vmcode_2addr_t)) {
                      code2 = (njs_vmcode_2addr_t *) p;
-                     nxt_log_error(NXT_LOG_INFO, log, "%V  %p %p",
-                                   name, code2->dst, code2->src);
+
+                     printf("%*s  %04lX %04lX\n",
+                            (int) name->len, name->data,
+                            code2->dst, code2->src);
 
                  } else if (code_name->size == sizeof(njs_vmcode_1addr_t)) {
                      code1 = (njs_vmcode_1addr_t *) p;
-                     nxt_log_error(NXT_LOG_INFO, log, "%V  %p",
-                                   name, code1->index);
+
+                     printf("%*s  %04lX\n",
+                            (int) name->len, name->data,
+                            code1->index);
                  }
 
                  p += code_name->size;
@@ -226,9 +329,8 @@ njs_disassembler(u_char *start, u_char *end, nxt_str_t *text)
         } while (n != 0);
 
         p += sizeof(njs_vmcode_operation_t);
-        name = &unknown;
 
-        nxt_log_error(NXT_LOG_INFO, log, "%V  %p", name, operation);
+        printf("UNKNOWN           %04lX\n", (uintptr_t) operation);
 
     next:
 
index ed1c3279fdf83f614fa88324dd00a6e9228111c9..c983e12f06fc9c30cb4349193b9c806173cd3d6c 100644 (file)
@@ -8,6 +8,7 @@
 #include <nxt_clang.h>
 #include <nxt_alignment.h>
 #include <nxt_stub.h>
+#include <nxt_array.h>
 #include <nxt_lvlhsh.h>
 #include <nxt_mem_cache_pool.h>
 #include <njscript.h>
index 73b02e9558d464e5204426631ade37c9d4599682..b38f8260e871f143cb1414acb554695fc687d318 100644 (file)
@@ -1481,6 +1481,7 @@ njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node,
     nxt_uint_t         n;
     njs_index_t        index;
     njs_value_t        *value;
+    njs_vm_code_t      *code;
     njs_vmcode_stop_t  *stop;
 
     p = nxt_mem_cache_alloc(vm->mem_cache_pool, parser->code_size);
@@ -1542,9 +1543,21 @@ njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node,
         *value++ = njs_value_void;
     }
 
-    nxt_thread_log_debug("SCOPE CODE:");
+    if (vm->code == NULL) {
+        vm->code = nxt_array_create(4, sizeof(njs_vm_code_t),
+                                    &njs_array_mem_proto, vm->mem_cache_pool);
+        if (nxt_slow_path(vm->code == NULL)) {
+            return NXT_ERROR;
+        }
+    }
+
+    code = nxt_array_add(vm->code, &njs_array_mem_proto, vm->mem_cache_pool);
+    if (nxt_slow_path(code == NULL)) {
+        return NXT_ERROR;
+    }
 
-    njs_disassembler(parser->code_start, parser->code_last, NULL);
+    code->start = parser->code_start;
+    code->end = parser->code_last;
 
     return NXT_OK;
 }
index 2a97fd4a6200c8f4eef391261e6cd4d56269fe2f..15d8bdb9e77783f5da53750a3aa5a1d73bf7da53 100644 (file)
@@ -7,6 +7,7 @@
 #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>
index 5f36fdd4a7b648fbeb576e8847f3ad493733ac59..ffb0946d393e56bde60c18aa92ee1d6751ca96fa 100644 (file)
@@ -8,6 +8,7 @@
 #include <nxt_clang.h>
 #include <nxt_stub.h>
 #include <nxt_djb_hash.h>
+#include <nxt_array.h>
 #include <nxt_lvlhsh.h>
 #include <nxt_mem_cache_pool.h>
 #include <njscript.h>
index 5bbe0acc73f68a9786a53bd96683a59aa9bb9dc3..c638d33b7e07748f90e5f4f7a105731f65f8efbc 100644 (file)
@@ -692,9 +692,17 @@ struct njs_vm_s {
     njs_vm_shared_t          *shared;
     njs_parser_t             *parser;
     njs_regexp_pattern_t     *pattern;
+
+    nxt_array_t              *code;  /* of njs_vm_code_t */
 };
 
 
+typedef struct {
+    u_char                   *start;
+    u_char                   *end;
+} njs_vm_code_t;
+
+
 struct njs_vm_shared_s {
     nxt_lvlhsh_t             keywords_hash;
     nxt_lvlhsh_t             values_hash;
@@ -706,8 +714,6 @@ struct njs_vm_shared_s {
 
 nxt_int_t njs_vmcode_interpreter(njs_vm_t *vm);
 
-void njs_disassembler(u_char *start, u_char *end, nxt_str_t *text);
-
 void njs_value_retain(njs_value_t *value);
 void njs_value_release(njs_vm_t *vm, njs_value_t *value);
 
index df75e40fafd3f3308750887c1c62e466fd3e1587..9a27af66a5ee5687bbc09be6285cb2bb65b2d0dc 100644 (file)
@@ -93,6 +93,8 @@ NXT_EXPORT void njs_vm_return(njs_vm_t *vm, njs_value_t *retval);
 NXT_EXPORT nxt_int_t njs_vm_retval(njs_vm_t *vm, nxt_str_t *retval);
 NXT_EXPORT nxt_int_t njs_vm_exception(njs_vm_t *vm, nxt_str_t *retval);
 
+NXT_EXPORT void njs_disassembler(njs_vm_t *vm);
+
 NXT_EXPORT njs_ret_t njs_string_create(njs_vm_t *vm, njs_value_t *value,
     u_char *start, size_t size, size_t length);
 NXT_EXPORT njs_ret_t njs_void_set(njs_value_t *value);
index 17621802dfd5520c6a222a632206d85a21df4247..2267a4435b1e7b67a5ab68ddc8947596b006efdc 100644 (file)
@@ -3231,7 +3231,7 @@ static const nxt_mem_proto_t  njs_mem_cache_pool_proto = {
 
 
 static nxt_int_t
-njs_unit_test(void)
+njs_unit_test(nxt_bool_t disassemble)
 {
     void                  *ext_object;
     u_char                *start;
@@ -3278,6 +3278,10 @@ njs_unit_test(void)
         ret = njs_vm_compile(vm, &start, start + njs_test[i].script.len);
 
         if (ret == NXT_OK) {
+            if (disassemble) {
+                njs_disassembler(vm);
+            }
+
             nvm = njs_vm_clone(vm, NULL, &ext_object);
             if (nvm == NULL) {
                 return NXT_ERROR;
@@ -3421,10 +3425,12 @@ njs_unit_test_benchmark(nxt_str_t *script, nxt_str_t *result, const char *msg,
 int nxt_cdecl
 main(int argc, char **argv)
 {
-    nxt_str_t  script = nxt_string("1");
-    nxt_str_t  result = nxt_string("1");
+    nxt_bool_t  disassemble;
+
+    static nxt_str_t  script = nxt_string("1");
+    static nxt_str_t  result = nxt_string("1");
 
-    nxt_str_t  fibo_number = nxt_string(
+    static nxt_str_t  fibo_number = nxt_string(
         "function fibo(n) {"
         "    if (n > 1)"
         "        return fibo(n - 1) + fibo(n - 2)"
@@ -3432,7 +3438,7 @@ main(int argc, char **argv)
         "}"
         "fibo(32)");
 
-    nxt_str_t  fibo_ascii = nxt_string(
+    static nxt_str_t  fibo_ascii = nxt_string(
         "function fibo(n) {"
         "    if (n > 1)"
         "        return fibo(n - 1) + fibo(n - 2)"
@@ -3440,7 +3446,7 @@ main(int argc, char **argv)
         "}"
         "fibo(32).length");
 
-    nxt_str_t  fibo_bytes = nxt_string(
+    static nxt_str_t  fibo_bytes = nxt_string(
         "function fibo(n) {"
         "    if (n > 1)"
         "        return fibo(n - 1) + fibo(n - 2)"
@@ -3448,7 +3454,7 @@ main(int argc, char **argv)
         "}"
         "fibo(32).length");
 
-    nxt_str_t  fibo_utf8 = nxt_string(
+    static nxt_str_t  fibo_utf8 = nxt_string(
         "function fibo(n) {"
         "    if (n > 1)"
         "        return fibo(n - 1) + fibo(n - 2)"
@@ -3456,9 +3462,11 @@ main(int argc, char **argv)
         "}"
         "fibo(32).length");
 
-    nxt_str_t  fibo_result = nxt_string("3524578");
+    static nxt_str_t  fibo_result = nxt_string("3524578");
 
 
+    disassemble = 0;
+
     if (argc > 1) {
         switch (argv[1][0]) {
 
@@ -3482,10 +3490,14 @@ main(int argc, char **argv)
             return njs_unit_test_benchmark(&fibo_utf8, &fibo_result,
                                            "fibobench utf8 strings", 1);
 
+        case 'd':
+            disassemble = 1;
+            break;
+
         default:
             break;
         }
     }
 
-    return njs_unit_test();
+    return njs_unit_test(disassemble);
 }