[njs] Code generator refactored.

Dmitry Volyntsev xeioex at nginx.com
Fri Dec 7 14:16:22 UTC 2018


details:   https://hg.nginx.org/njs/rev/8eb112dcca79
branches:  
changeset: 686:8eb112dcca79
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Fri Dec 07 17:11:33 2018 +0300
description:
Code generator refactored.

Previously, the code size had to be calculated before code generation
phase because raw pointers to instruction were used to determine proper
jump offsets. It introduced unnecessary coupling between parser and
generator as well as complicated the parser because it had to know in
advance what instructions will be generated.

The solution is the dynamic reallocation of the code during generation
phase and the usage of relative offsets when calculating jump instructions.

diffstat:

 njs/njs_core.h              |    1 +
 njs/njs_generator.c         |  227 ++++++++++++++++++++++++++++++++-----------
 njs/njs_generator.h         |   15 ++
 njs/njs_parser.c            |   45 +--------
 njs/njs_parser.h            |   12 +-
 njs/njs_parser_expression.c |   77 +-------------
 6 files changed, 194 insertions(+), 183 deletions(-)

diffs (truncated from 1250 to 1000 lines):

diff -r 23fecf3fcc60 -r 8eb112dcca79 njs/njs_core.h
--- a/njs/njs_core.h	Wed Dec 05 15:38:33 2018 +0300
+++ b/njs/njs_core.h	Fri Dec 07 17:11:33 2018 +0300
@@ -32,6 +32,7 @@
 #include <njs_vm.h>
 #include <njs_variable.h>
 #include <njs_parser.h>
+#include <njs_generator.h>
 #include <njs_function.h>
 #include <njs_boolean.h>
 #include <njs_number.h>
diff -r 23fecf3fcc60 -r 8eb112dcca79 njs/njs_generator.c
--- a/njs/njs_generator.c	Wed Dec 05 15:38:33 2018 +0300
+++ b/njs/njs_generator.c	Fri Dec 07 17:11:33 2018 +0300
@@ -10,6 +10,8 @@
 
 static nxt_int_t njs_generator(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node);
+static u_char *njs_generate_reserve(njs_vm_t *vm, njs_parser_t *parser,
+    size_t size);
 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,
@@ -78,8 +80,8 @@ static nxt_int_t njs_generate_function_d
     njs_parser_t *parser, njs_parser_node_t *node);
 static nxt_int_t njs_generate_function_scope(njs_vm_t *vm,
     njs_function_lambda_t *lambda, njs_parser_node_t *node);
-static void njs_generate_argument_closures(njs_parser_t *parser,
-    njs_parser_node_t *node);
+static nxt_int_t njs_generate_argument_closures(njs_vm_t *vm,
+    njs_parser_t *parser, njs_parser_node_t *node);
 static nxt_int_t njs_generate_return_statement(njs_vm_t *vm,
     njs_parser_t *parser, njs_parser_node_t *node);
 static nxt_int_t njs_generate_function_call(njs_vm_t *vm, njs_parser_t *parser,
@@ -113,6 +115,46 @@ static nxt_int_t njs_generate_function_d
     njs_function_lambda_t *lambda, uint32_t line);
 
 
+#define njs_generate_code(parser, type, code)                                 \
+    do {                                                                      \
+        code = (type *) njs_generate_reserve(vm, parser, sizeof(type));       \
+        if (nxt_slow_path(code == NULL)) {                                    \
+            return NXT_ERROR;                                                 \
+        }                                                                     \
+        parser->code_end += sizeof(type);                                     \
+    } while (0)
+
+
+#define njs_code_offset(parser, code)                                         \
+    ((u_char *) code - parser->code_start)
+
+
+#define njs_code_ptr(parser, type, offset)                                    \
+    (type *) (parser->code_start + offset)
+
+
+#define njs_code_jump_ptr(parser, offset)                                     \
+    (njs_ret_t *) (parser->code_start + offset)
+
+
+#define njs_code_offset_diff(parser, offset)                                  \
+    ((parser->code_end - parser->code_start) - offset)
+
+
+#define njs_code_set_offset(parser, offset, target)                           \
+    *(njs_code_jump_ptr(parser, offset)) = njs_code_offset_diff(parser, target)
+
+
+#define njs_code_set_jump_offset(parser, type, code_offset)                   \
+    *(njs_code_jump_ptr(parser, code_offset + offsetof(type, offset)))        \
+        = njs_code_offset_diff(parser, code_offset)
+
+
+#define njs_code_update_offset(parser, patch)                                 \
+    *(njs_code_jump_ptr(parser, patch->jump_offset)) +=                       \
+        njs_code_offset_diff(parser, patch->jump_offset)
+
+
 static const nxt_str_t  no_label = { 0, NULL };
 
 
@@ -340,6 +382,43 @@ njs_generator(njs_vm_t *vm, njs_parser_t
 }
 
 
+static u_char *
+njs_generate_reserve(njs_vm_t *vm, njs_parser_t *parser, size_t size)
+{
+    u_char  *p;
+
+    if (parser->code_end + size <= parser->code_start + parser->code_size) {
+        return parser->code_end;
+    }
+
+    size = nxt_max(parser->code_end - parser->code_start + size,
+                   parser->code_size);
+
+    if (size < 1024) {
+        size *= 2;
+
+    } else {
+        size += size/ 2;
+    }
+
+    p = nxt_mem_cache_alloc(vm->mem_cache_pool, size);
+    if (nxt_slow_path(p == NULL)) {
+        njs_memory_error(vm);
+        return NULL;
+    }
+
+    parser->code_size = size;
+
+    size = parser->code_end - parser->code_start;
+    memcpy(p, parser->code_start, size);
+
+    parser->code_start = p;
+    parser->code_end = p + size;
+
+    return parser->code_end;
+}
+
+
 static nxt_int_t
 njs_generate_name(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
 {
@@ -496,9 +575,8 @@ static nxt_int_t
 njs_generate_if_statement(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
-    u_char                  *previous;
+    njs_ret_t               jump_offset, label_offset;
     nxt_int_t               ret;
-    njs_ret_t               *label;
     njs_vmcode_jump_t       *jump;
     njs_vmcode_cond_jump_t  *cond_jump;
 
@@ -520,8 +598,8 @@ njs_generate_if_statement(njs_vm_t *vm, 
         return ret;
     }
 
-    previous = (u_char *) cond_jump;
-    label = &cond_jump->offset;
+    jump_offset = njs_code_offset(parser, cond_jump);
+    label_offset = jump_offset + offsetof(njs_vmcode_cond_jump_t, offset);
 
     if (node->right != NULL && node->right->token == NJS_TOKEN_BRANCHING) {
 
@@ -544,9 +622,10 @@ njs_generate_if_statement(njs_vm_t *vm, 
         jump->code.operands = NJS_VMCODE_NO_OPERAND;
         jump->code.retval = NJS_VMCODE_NO_RETVAL;
 
-        *label = parser->code_end - previous;
-        previous = (u_char *) jump;
-        label = &jump->offset;
+        njs_code_set_offset(parser, label_offset, jump_offset);
+
+        jump_offset = njs_code_offset(parser, jump);
+        label_offset = jump_offset + offsetof(njs_vmcode_jump_t, offset);
     }
 
     /*
@@ -564,7 +643,7 @@ njs_generate_if_statement(njs_vm_t *vm, 
         return ret;
     }
 
-    *label = parser->code_end - previous;
+    njs_code_set_offset(parser, label_offset, jump_offset);
 
     return NXT_OK;
 }
@@ -574,6 +653,7 @@ static nxt_int_t
 njs_generate_cond_expression(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
+    njs_ret_t               jump_offset, cond_jump_offset;
     nxt_int_t               ret;
     njs_parser_node_t       *branch;
     njs_vmcode_move_t       *move;
@@ -588,6 +668,7 @@ njs_generate_cond_expression(njs_vm_t *v
     }
 
     njs_generate_code(parser, njs_vmcode_cond_jump_t, cond_jump);
+    cond_jump_offset = njs_code_offset(parser, cond_jump);
     cond_jump->code.operation = njs_vmcode_if_false_jump;
     cond_jump->code.operands = NJS_VMCODE_2OPERANDS;
     cond_jump->code.retval = NJS_VMCODE_NO_RETVAL;
@@ -628,11 +709,12 @@ njs_generate_cond_expression(njs_vm_t *v
     }
 
     njs_generate_code(parser, njs_vmcode_jump_t, jump);
+    jump_offset = njs_code_offset(parser, jump);
     jump->code.operation = njs_vmcode_jump;
     jump->code.operands = NJS_VMCODE_NO_OPERAND;
     jump->code.retval = NJS_VMCODE_NO_RETVAL;
 
-    cond_jump->offset = parser->code_end - (u_char *) cond_jump;
+    njs_code_set_jump_offset(parser, njs_vmcode_cond_jump_t, cond_jump_offset);
 
     /* The "false" branch. */
 
@@ -650,7 +732,7 @@ njs_generate_cond_expression(njs_vm_t *v
         move->src = branch->right->index;
     }
 
-    jump->offset = parser->code_end - (u_char *) jump;
+    njs_code_set_jump_offset(parser, njs_vmcode_cond_jump_t, jump_offset);
 
     ret = njs_generator_node_index_release(vm, parser, branch->right);
     if (nxt_slow_path(ret != NXT_OK)) {
@@ -665,6 +747,7 @@ static nxt_int_t
 njs_generate_switch_statement(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *swtch)
 {
+    njs_ret_t                jump_offset;
     nxt_int_t                ret;
     njs_index_t              index;
     njs_parser_node_t        *node, *expr, *branch;
@@ -703,6 +786,7 @@ njs_generate_switch_statement(njs_vm_t *
         return ret;
     }
 
+    patches = NULL;
     last = &patches;
 
     for (branch = swtch->right; branch != NULL; branch = branch->left) {
@@ -737,7 +821,8 @@ njs_generate_switch_statement(njs_vm_t *
                 return NXT_ERROR;
             }
 
-            patch->address = &equal->offset;
+            patch->jump_offset = njs_code_offset(parser, equal)
+                                 + offsetof(njs_vmcode_equal_jump_t, offset);
 
             *last = patch;
             last = &patch->next;
@@ -751,6 +836,7 @@ njs_generate_switch_statement(njs_vm_t *
     }
 
     njs_generate_code(parser, njs_vmcode_jump_t, jump);
+    jump_offset = njs_code_offset(parser, jump);
     jump->code.operation = njs_vmcode_jump;
     jump->code.operands = NJS_VMCODE_1OPERAND;
     jump->code.retval = NJS_VMCODE_NO_RETVAL;
@@ -761,12 +847,13 @@ njs_generate_switch_statement(njs_vm_t *
     for (branch = swtch->right; branch != NULL; branch = branch->left) {
 
         if (branch->token == NJS_TOKEN_DEFAULT) {
-            jump->offset = parser->code_end - (u_char *) jump;
+            njs_code_set_jump_offset(parser, njs_vmcode_jump_t, jump_offset);
             jump = NULL;
             node = branch;
 
         } else {
-            *patch->address += parser->code_end - (u_char *) patch->address;
+            njs_code_update_offset(parser, patch);
+
             next = patch->next;
 
             nxt_mem_cache_free(vm->mem_cache_pool, patch);
@@ -785,7 +872,7 @@ njs_generate_switch_statement(njs_vm_t *
 
     if (jump != NULL) {
         /* A "switch" without default case. */
-        jump->offset = parser->code_end - (u_char *) jump;
+        njs_code_set_jump_offset(parser, njs_vmcode_jump_t, jump_offset);
     }
 
     /* Patch "break" statements offsets. */
@@ -799,7 +886,7 @@ static nxt_int_t
 njs_generate_while_statement(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
-    u_char                  *loop;
+    njs_ret_t               jump_offset, loop_offset;
     nxt_int_t               ret;
     njs_parser_node_t       *condition;
     njs_vmcode_jump_t       *jump;
@@ -812,6 +899,7 @@ njs_generate_while_statement(njs_vm_t *v
      */
 
     njs_generate_code(parser, njs_vmcode_jump_t, jump);
+    jump_offset = njs_code_offset(parser, jump);
     jump->code.operation = njs_vmcode_jump;
     jump->code.operands = NJS_VMCODE_NO_OPERAND;
     jump->code.retval = NJS_VMCODE_NO_RETVAL;
@@ -823,7 +911,7 @@ njs_generate_while_statement(njs_vm_t *v
         return ret;
     }
 
-    loop = parser->code_end;
+    loop_offset = njs_code_offset(parser, parser->code_end);
 
     ret = njs_generator(vm, parser, node->left);
     if (nxt_slow_path(ret != NXT_OK)) {
@@ -834,7 +922,7 @@ njs_generate_while_statement(njs_vm_t *v
 
     njs_generate_patch_loop_continuation(vm, parser);
 
-    jump->offset = parser->code_end - (u_char *) jump;
+    njs_code_set_jump_offset(parser, njs_vmcode_jump_t, jump_offset);
 
     condition = node->right;
 
@@ -847,7 +935,7 @@ njs_generate_while_statement(njs_vm_t *v
     cond_jump->code.operation = njs_vmcode_if_true_jump;
     cond_jump->code.operands = NJS_VMCODE_2OPERANDS;
     cond_jump->code.retval = NJS_VMCODE_NO_RETVAL;
-    cond_jump->offset = loop - (u_char *) cond_jump;
+    cond_jump->offset = loop_offset - njs_code_offset(parser, cond_jump);
     cond_jump->cond = condition->index;
 
     njs_generate_patch_block_exit(vm, parser);
@@ -860,7 +948,7 @@ static nxt_int_t
 njs_generate_do_while_statement(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
-    u_char                  *loop;
+    njs_ret_t               loop_offset;
     nxt_int_t               ret;
     njs_parser_node_t       *condition;
     njs_vmcode_cond_jump_t  *cond_jump;
@@ -872,7 +960,7 @@ njs_generate_do_while_statement(njs_vm_t
         return ret;
     }
 
-    loop = parser->code_end;
+    loop_offset = njs_code_offset(parser, parser->code_end);
 
     ret = njs_generator(vm, parser, node->left);
     if (nxt_slow_path(ret != NXT_OK)) {
@@ -894,7 +982,7 @@ njs_generate_do_while_statement(njs_vm_t
     cond_jump->code.operation = njs_vmcode_if_true_jump;
     cond_jump->code.operands = NJS_VMCODE_2OPERANDS;
     cond_jump->code.retval = NJS_VMCODE_NO_RETVAL;
-    cond_jump->offset = loop - (u_char *) cond_jump;
+    cond_jump->offset = loop_offset - njs_code_offset(parser, cond_jump);
     cond_jump->cond = condition->index;
 
     njs_generate_patch_block_exit(vm, parser);
@@ -907,7 +995,7 @@ static nxt_int_t
 njs_generate_for_statement(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
-    u_char                  *loop;
+    njs_ret_t               jump_offset, loop_offset;
     nxt_int_t               ret;
     njs_parser_node_t       *condition, *update;
     njs_vmcode_jump_t       *jump;
@@ -935,6 +1023,9 @@ njs_generate_for_statement(njs_vm_t *vm,
     node = node->right;
     condition = node->left;
 
+    /* GCC complains about uninitialized jump_offset. */
+    jump_offset = 0;
+
     if (condition != NULL) {
         /*
          * The loop condition presents so set a jump to it.  This jump is
@@ -942,6 +1033,7 @@ njs_generate_for_statement(njs_vm_t *vm,
          * execution of one additional jump inside the loop per each iteration.
          */
         njs_generate_code(parser, njs_vmcode_jump_t, jump);
+        jump_offset = njs_code_offset(parser, jump);
         jump->code.operation = njs_vmcode_jump;
         jump->code.operands = NJS_VMCODE_NO_OPERAND;
         jump->code.retval = NJS_VMCODE_NO_RETVAL;
@@ -949,7 +1041,7 @@ njs_generate_for_statement(njs_vm_t *vm,
 
     /* The loop body. */
 
-    loop = parser->code_end;
+    loop_offset = njs_code_offset(parser, parser->code_end);
 
     node = node->right;
 
@@ -977,7 +1069,7 @@ njs_generate_for_statement(njs_vm_t *vm,
     /* The loop condition. */
 
     if (condition != NULL) {
-        jump->offset = parser->code_end - (u_char *) jump;
+        njs_code_set_jump_offset(parser, njs_vmcode_jump_t, jump_offset);
 
         ret = njs_generator(vm, parser, condition);
         if (nxt_slow_path(ret != NXT_OK)) {
@@ -988,7 +1080,7 @@ njs_generate_for_statement(njs_vm_t *vm,
         cond_jump->code.operation = njs_vmcode_if_true_jump;
         cond_jump->code.operands = NJS_VMCODE_2OPERANDS;
         cond_jump->code.retval = NJS_VMCODE_NO_RETVAL;
-        cond_jump->offset = loop - (u_char *) cond_jump;
+        cond_jump->offset = loop_offset - njs_code_offset(parser, cond_jump);
         cond_jump->cond = condition->index;
 
         njs_generate_patch_block_exit(vm, parser);
@@ -1000,7 +1092,7 @@ njs_generate_for_statement(njs_vm_t *vm,
     jump->code.operation = njs_vmcode_jump;
     jump->code.operands = NJS_VMCODE_NO_OPERAND;
     jump->code.retval = NJS_VMCODE_NO_RETVAL;
-    jump->offset = loop - (u_char *) jump;
+    jump->offset = loop_offset - njs_code_offset(parser, jump);
 
     njs_generate_patch_block_exit(vm, parser);
 
@@ -1012,7 +1104,7 @@ static nxt_int_t
 njs_generate_for_in_statement(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
-    u_char                     *loop;
+    njs_ret_t                  loop_offset, prop_offset;
     nxt_int_t                  ret;
     njs_index_t                index;
     njs_parser_node_t          *foreach;
@@ -1034,6 +1126,7 @@ njs_generate_for_in_statement(njs_vm_t *
     }
 
     njs_generate_code(parser, njs_vmcode_prop_foreach_t, prop_foreach);
+    prop_offset = njs_code_offset(parser, prop_foreach);
     prop_foreach->code.operation = njs_vmcode_property_foreach;
     prop_foreach->code.operands = NJS_VMCODE_2OPERANDS;
     prop_foreach->code.retval = NJS_VMCODE_RETVAL;
@@ -1048,7 +1141,7 @@ njs_generate_for_in_statement(njs_vm_t *
 
     /* The loop body. */
 
-    loop = parser->code_end;
+    loop_offset = njs_code_offset(parser, parser->code_end);
 
     ret = njs_generator(vm, parser, node->right);
     if (nxt_slow_path(ret != NXT_OK)) {
@@ -1059,7 +1152,7 @@ njs_generate_for_in_statement(njs_vm_t *
 
     njs_generate_patch_loop_continuation(vm, parser);
 
-    prop_foreach->offset = parser->code_end - (u_char *) prop_foreach;
+    njs_code_set_jump_offset(parser, njs_vmcode_prop_foreach_t, prop_offset);
 
     ret = njs_generator(vm, parser, node->left->left);
     if (nxt_slow_path(ret != NXT_OK)) {
@@ -1067,13 +1160,14 @@ njs_generate_for_in_statement(njs_vm_t *
     }
 
     njs_generate_code(parser, njs_vmcode_prop_next_t, prop_next);
+    prop_offset = njs_code_offset(parser, prop_next);
     prop_next->code.operation = njs_vmcode_property_next;
     prop_next->code.operands = NJS_VMCODE_3OPERANDS;
     prop_next->code.retval = NJS_VMCODE_NO_RETVAL;
     prop_next->retval = foreach->left->index;
     prop_next->object = foreach->right->index;
     prop_next->next = index;
-    prop_next->offset = loop - (u_char *) prop_next;
+    prop_next->offset = loop_offset - prop_offset;
 
     njs_generate_patch_block_exit(vm, parser);
 
@@ -1123,7 +1217,7 @@ njs_generate_patch_loop_continuation(njs
     block = parser->block;
 
     for (patch = block->continuation; patch != NULL; patch = next) {
-        *patch->address += parser->code_end - (u_char *) patch->address;
+        njs_code_update_offset(parser, patch);
         next = patch->next;
 
         nxt_mem_cache_free(vm->mem_cache_pool, patch);
@@ -1141,7 +1235,7 @@ njs_generate_patch_block_exit(njs_vm_t *
     parser->block = block->next;
 
     for (patch = block->exit; patch != NULL; patch = next) {
-        *patch->address += parser->code_end - (u_char *) patch->address;
+        njs_code_update_offset(parser, patch);
         next = patch->next;
 
         nxt_mem_cache_free(vm->mem_cache_pool, patch);
@@ -1185,7 +1279,8 @@ found:
         jump->code.retval = NJS_VMCODE_NO_RETVAL;
         jump->offset = offsetof(njs_vmcode_jump_t, offset);
 
-        patch->address = &jump->offset;
+        patch->jump_offset = njs_code_offset(parser, jump)
+                             + offsetof(njs_vmcode_jump_t, offset);
     }
 
     return NXT_OK;
@@ -1228,7 +1323,8 @@ found:
         jump->code.retval = NJS_VMCODE_NO_RETVAL;
         jump->offset = offsetof(njs_vmcode_jump_t, offset);
 
-        patch->address = &jump->offset;
+        patch->jump_offset = njs_code_offset(parser, jump)
+                             + offsetof(njs_vmcode_jump_t, offset);
     }
 
     return NXT_OK;
@@ -1685,6 +1781,7 @@ static nxt_int_t
 njs_generate_test_jump_expression(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
+    njs_ret_t               jump_offset;
     nxt_int_t               ret;
     njs_vmcode_move_t       *move;
     njs_vmcode_test_jump_t  *test_jump;
@@ -1695,6 +1792,7 @@ njs_generate_test_jump_expression(njs_vm
     }
 
     njs_generate_code(parser, njs_vmcode_test_jump_t, test_jump);
+    jump_offset = njs_code_offset(parser, test_jump);
     test_jump->code.operation = node->u.operation;
     test_jump->code.operands = NJS_VMCODE_2OPERANDS;
     test_jump->code.retval = NJS_VMCODE_RETVAL;
@@ -1727,7 +1825,7 @@ njs_generate_test_jump_expression(njs_vm
         move->src = node->right->index;
     }
 
-    test_jump->offset = parser->code_end - (u_char *) test_jump;
+    njs_code_set_jump_offset(parser, njs_vmcode_test_jump_t, jump_offset);
 
     return njs_generator_children_indexes_release(vm, parser, node);
 }
@@ -2040,9 +2138,6 @@ njs_generate_function_scope(njs_vm_t *vm
     parser = lambda->parser;
     node = node->right;
 
-    parser->code_size += node->scope->argument_closures
-                         * sizeof(njs_vmcode_move_t);
-
     parser->arguments_object = 0;
     ret = njs_generate_scope(vm, parser, node);
 
@@ -2074,8 +2169,9 @@ nxt_int_t
 njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
 {
     u_char              *p;
-    size_t              code_size, size;
+    size_t              size;
     uintptr_t           scope_size;
+    nxt_int_t           ret;
     nxt_uint_t          n;
     njs_value_t         *value;
     njs_vm_code_t       *code;
@@ -2083,6 +2179,8 @@ njs_generate_scope(njs_vm_t *vm, njs_par
 
     scope = node->scope;
 
+    parser->code_size = 128;
+
     p = nxt_mem_cache_alloc(vm->mem_cache_pool, parser->code_size);
     if (nxt_slow_path(p == NULL)) {
         return NXT_ERROR;
@@ -2091,22 +2189,16 @@ njs_generate_scope(njs_vm_t *vm, njs_par
     parser->code_start = p;
     parser->code_end = p;
 
-    njs_generate_argument_closures(parser, node);
+    ret = njs_generate_argument_closures(vm, parser, node);
+    if (nxt_slow_path(ret != NXT_OK)) {
+        return NXT_ERROR;
+    }
 
     if (nxt_slow_path(njs_generator(vm, parser, node) != NXT_OK)) {
         return NXT_ERROR;
     }
 
-    code_size = parser->code_end - parser->code_start;
-
-    nxt_thread_log_debug("SCOPE CODE SIZE: %uz %uz",
-                         parser->code_size, code_size);
-
-    if (nxt_slow_path(parser->code_size < code_size)) {
-        njs_internal_error(vm, "code size mismatch expected %uz < actual %uz",
-                           parser->code_size, code_size);
-        return NXT_ERROR;
-    }
+    parser->code_size = parser->code_end - parser->code_start;
 
     scope_size = njs_scope_offset(scope->next_index[0]);
 
@@ -2152,8 +2244,9 @@ njs_generate_scope(njs_vm_t *vm, njs_par
 }
 
 
-static void
-njs_generate_argument_closures(njs_parser_t *parser, njs_parser_node_t *node)
+static nxt_int_t
+njs_generate_argument_closures(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node)
 {
     nxt_uint_t         n;
     njs_index_t        index;
@@ -2164,7 +2257,7 @@ njs_generate_argument_closures(njs_parse
     n = node->scope->argument_closures;
 
     if (n == 0) {
-        return;
+        return NXT_OK;
     }
 
     nxt_lvlhsh_each_init(&lhe, &njs_variables_hash_proto);
@@ -2186,6 +2279,8 @@ njs_generate_argument_closures(njs_parse
         }
 
     } while(n != 0);
+
+    return NXT_OK;
 }
 
 
@@ -2224,6 +2319,7 @@ static nxt_int_t
 njs_generate_function_call(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
+    njs_ret_t                    func_offset;
     njs_ret_t                    ret;
     njs_parser_node_t            *name;
     njs_vmcode_function_frame_t  *func;
@@ -2246,6 +2342,7 @@ njs_generate_function_call(njs_vm_t *vm,
     }
 
     njs_generate_code(parser, njs_vmcode_function_frame_t, func);
+    func_offset = njs_code_offset(parser, func);
     func->code.operation = njs_vmcode_function_frame;
     func->code.operands = NJS_VMCODE_2OPERANDS;
     func->code.retval = NJS_VMCODE_NO_RETVAL;
@@ -2255,6 +2352,7 @@ njs_generate_function_call(njs_vm_t *vm,
     ret = njs_generate_call(vm, parser, node);
 
     if (nxt_fast_path(ret >= 0)) {
+        func = njs_code_ptr(parser, njs_vmcode_function_frame_t, func_offset);
         func->nargs = ret;
         return NXT_OK;
     }
@@ -2267,6 +2365,7 @@ static nxt_int_t
 njs_generate_method_call(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
+    njs_ret_t                  method_offset;
     nxt_int_t                  ret;
     njs_parser_node_t          *prop;
     njs_vmcode_method_frame_t  *method;
@@ -2288,6 +2387,7 @@ njs_generate_method_call(njs_vm_t *vm, n
     }
 
     njs_generate_code(parser, njs_vmcode_method_frame_t, method);
+    method_offset = njs_code_offset(parser, method);
     method->code.operation = njs_vmcode_method_frame;
     method->code.operands = NJS_VMCODE_3OPERANDS;
     method->code.retval = NJS_VMCODE_NO_RETVAL;
@@ -2303,6 +2403,7 @@ njs_generate_method_call(njs_vm_t *vm, n
     ret = njs_generate_call(vm, parser, node);
 
     if (nxt_fast_path(ret >= 0)) {
+        method = njs_code_ptr(parser, njs_vmcode_method_frame_t, method_offset);
         method->nargs = ret;
         return NXT_OK;
     }
@@ -2362,6 +2463,7 @@ static nxt_int_t
 njs_generate_try_statement(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
 {
+    njs_ret_t               try_offset, catch_offset;
     nxt_int_t               ret;
     njs_index_t             index, catch_index;
     njs_vmcode_catch_t      *catch;
@@ -2370,6 +2472,7 @@ njs_generate_try_statement(njs_vm_t *vm,
     njs_vmcode_try_start_t  *try_start;
 
     njs_generate_code(parser, njs_vmcode_try_start_t, try_start);
+    try_offset = njs_code_offset(parser, try_start);
     try_start->code.operation = njs_vmcode_try_start;
     try_start->code.operands = NJS_VMCODE_2OPERANDS;
     try_start->code.retval = NJS_VMCODE_NO_RETVAL;
@@ -2391,7 +2494,8 @@ njs_generate_try_statement(njs_vm_t *vm,
     try_end->code.operands = NJS_VMCODE_NO_OPERAND;
     try_end->code.retval = NJS_VMCODE_NO_RETVAL;
 
-    try_start->offset = parser->code_end - (u_char *) try_start;
+    njs_code_set_jump_offset(parser, njs_vmcode_try_start_t, try_offset);
+    try_offset = njs_code_offset(parser, try_end);
 
     node = node->right;
 
@@ -2415,7 +2519,7 @@ njs_generate_try_statement(njs_vm_t *vm,
             return ret;
         }
 
-        try_end->offset = parser->code_end - (u_char *) try_end;
+        njs_code_set_jump_offset(parser, njs_vmcode_try_end_t, try_offset);
 
         /* TODO: release exception variable index. */
 
@@ -2429,6 +2533,7 @@ njs_generate_try_statement(njs_vm_t *vm,
             }
 
             njs_generate_code(parser, njs_vmcode_catch_t, catch);
+            catch_offset = njs_code_offset(parser, catch);
             catch->code.operation = njs_vmcode_catch;
             catch->code.operands = NJS_VMCODE_2OPERANDS;
             catch->code.retval = NJS_VMCODE_NO_RETVAL;
@@ -2444,7 +2549,8 @@ njs_generate_try_statement(njs_vm_t *vm,
             catch_end->code.operands = NJS_VMCODE_NO_OPERAND;
             catch_end->code.retval = NJS_VMCODE_NO_RETVAL;
 
-            catch->offset = parser->code_end - (u_char *) catch;
+            njs_code_set_jump_offset(parser, njs_vmcode_catch_t, catch_offset);
+            catch_offset = njs_code_offset(parser, catch_end);
 
             /* TODO: release exception variable index. */
 
@@ -2455,7 +2561,8 @@ njs_generate_try_statement(njs_vm_t *vm,
             catch->offset = sizeof(njs_vmcode_catch_t);
             catch->exception = index;
 
-            catch_end->offset = parser->code_end - (u_char *) catch_end;
+            njs_code_set_jump_offset(parser, njs_vmcode_try_end_t,
+                                     catch_offset);
 
         } else {
             /* A try/finally case. */
@@ -2468,7 +2575,7 @@ njs_generate_try_statement(njs_vm_t *vm,
             catch->exception = index;
         }
 
-        try_end->offset = parser->code_end - (u_char *) try_end;
+        njs_code_set_jump_offset(parser, njs_vmcode_try_end_t, try_offset);
 
         ret = njs_generator(vm, parser, node->right);
         if (nxt_slow_path(ret != NXT_OK)) {
diff -r 23fecf3fcc60 -r 8eb112dcca79 njs/njs_generator.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/njs/njs_generator.h	Fri Dec 07 17:11:33 2018 +0300
@@ -0,0 +1,15 @@
+
+/*
+ * Copyright (C) Dmitry Volyntsev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NJS_GENERATOR_H_INCLUDED_
+#define _NJS_GENERATOR_H_INCLUDED_
+
+
+nxt_int_t njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node);
+
+
+#endif /* _NJS_GENERATOR_H_INCLUDED_ */
diff -r 23fecf3fcc60 -r 8eb112dcca79 njs/njs_parser.c
--- a/njs/njs_parser.c	Wed Dec 05 15:38:33 2018 +0300
+++ b/njs/njs_parser.c	Fri Dec 07 17:11:33 2018 +0300
@@ -523,7 +523,6 @@ njs_parser_function_expression(njs_vm_t 
     node->token_line = parser->lexer->token_line;
     node->scope = parser->scope;
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_function_t);
 
     parser = njs_parser_function_create(vm, parser);
     if (nxt_slow_path(parser == NULL)) {
@@ -732,8 +731,6 @@ njs_parser_function_lambda(njs_vm_t *vm,
         }
 
         node->right->token = NJS_TOKEN_RETURN;
-
-        parser->code_size += sizeof(njs_vmcode_return_t);
     }
 
     parser->parent->node->right = parser->node;
@@ -770,7 +767,6 @@ njs_parser_return_statement(njs_vm_t *vm
 
     node->token = NJS_TOKEN_RETURN;
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_return_t);
 
     token = njs_lexer_token(parser->lexer);
     if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
@@ -891,7 +887,6 @@ njs_parser_var_statement(njs_vm_t *vm, n
         stmt->left = left;
         stmt->right = assign;
         parser->node = stmt;
-        parser->code_size += sizeof(njs_vmcode_2addr_t);
 
         left = stmt;
 
@@ -942,7 +937,6 @@ njs_parser_if_statement(njs_vm_t *vm, nj
         node->left = stmt;
         node->right = parser->node;
         parser->node = node;
-        parser->code_size += sizeof(njs_vmcode_jump_t);
     }
 
     node = njs_parser_node_alloc(vm);
@@ -954,7 +948,6 @@ njs_parser_if_statement(njs_vm_t *vm, nj
     node->left = cond;
     node->right = parser->node;
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_cond_jump_t);
 
     return token;
 }
@@ -1020,8 +1013,6 @@ njs_parser_switch_statement(njs_vm_t *vm
 
                     branch->right = node;
 
-                    parser->code_size += sizeof(njs_vmcode_equal_jump_t);
-
                } else {
                     if (dflt != NULL) {
                         njs_parser_syntax_error(vm, parser,
@@ -1071,7 +1062,6 @@ njs_parser_switch_statement(njs_vm_t *vm
     }
 
     parser->node = swtch;
-    parser->code_size += sizeof(njs_vmcode_move_t) + sizeof(njs_vmcode_jump_t);
 
     return njs_parser_token(parser);
 }
@@ -1104,8 +1094,6 @@ njs_parser_while_statement(njs_vm_t *vm,
     node->left = parser->node;
     node->right = cond;
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_jump_t)
-                         + sizeof(njs_vmcode_cond_jump_t);
 
     return token;
 }
@@ -1147,7 +1135,6 @@ njs_parser_do_while_statement(njs_vm_t *
     node->left = stmt;
     node->right = parser->node;
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_cond_jump_t);
 
     return token;
 }
@@ -1272,8 +1259,7 @@ njs_parser_for_statement(njs_vm_t *vm, n
     body->right = update;
 
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_jump_t)
-                         + sizeof(njs_vmcode_cond_jump_t);
+
     return token;
 }
 
@@ -1368,7 +1354,6 @@ njs_parser_for_var_statement(njs_vm_t *v
         stmt->left = left;
         stmt->right = assign;
         parser->node = stmt;
-        parser->code_size += sizeof(njs_vmcode_2addr_t);
 
         left = stmt;
 
@@ -1424,8 +1409,7 @@ njs_parser_for_var_in_statement(njs_vm_t
     foreach->right = parser->node;
 
     parser->node = foreach;
-    parser->code_size += sizeof(njs_vmcode_prop_foreach_t)
-                         + sizeof(njs_vmcode_prop_next_t);
+
     return token;
 }
 
@@ -1466,8 +1450,7 @@ njs_parser_for_in_statement(njs_vm_t *vm
 
     node->right = parser->node;
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_prop_foreach_t)
-                         + sizeof(njs_vmcode_prop_next_t);
+
     return token;
 }
 
@@ -1486,7 +1469,6 @@ njs_parser_continue_statement(njs_vm_t *
     node->token = NJS_TOKEN_CONTINUE;
     node->token_line = parser->lexer->token_line;
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_jump_t);
 
     token = njs_lexer_token(parser->lexer);
 
@@ -1521,7 +1503,6 @@ njs_parser_break_statement(njs_vm_t *vm,
     node->token = NJS_TOKEN_BREAK;
     node->token_line = parser->lexer->token_line;
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_jump_t);
 
     token = njs_lexer_token(parser->lexer);
 
@@ -1563,8 +1544,6 @@ njs_parser_try_statement(njs_vm_t *vm, n
     try->token = NJS_TOKEN_TRY;
     try->scope = parser->scope;
     try->left = parser->node;
-    parser->code_size += sizeof(njs_vmcode_try_start_t)
-                         + sizeof(njs_vmcode_try_end_t);
 
     if (token == NJS_TOKEN_CATCH) {
         token = njs_parser_token(parser);
@@ -1617,8 +1596,6 @@ njs_parser_try_statement(njs_vm_t *vm, n
 
         catch->left = node;
 
-        parser->code_size += sizeof(njs_vmcode_catch_t);
-
         token = njs_parser_token(parser);
         if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
             return token;
@@ -1655,12 +1632,9 @@ njs_parser_try_statement(njs_vm_t *vm, n
 
         if (try->right != NULL) {
             node->left = try->right;
-            parser->code_size += sizeof(njs_vmcode_try_end_t);
         }
 
         try->right = node;
-        parser->code_size += sizeof(njs_vmcode_catch_t)
-                             + sizeof(njs_vmcode_finally_t);
     }
 
     if (try->right == NULL) {
@@ -1842,7 +1816,6 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
             return NJS_TOKEN_ERROR;
         }
 
-        parser->code_size += sizeof(njs_vmcode_object_copy_t);
         break;
 
     case NJS_TOKEN_OPEN_BRACE:
@@ -1861,8 +1834,6 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
             parser->node = node;
         }
 
-        parser->code_size += sizeof(njs_vmcode_1addr_t);
-
         return token;
 
     case NJS_TOKEN_OPEN_BRACKET:
@@ -1881,8 +1852,6 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
             parser->node = node;
         }
 
-        parser->code_size += sizeof(njs_vmcode_2addr_t);
-
         return token;
 
     case NJS_TOKEN_DIVISION:
@@ -1895,7 +1864,6 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
 
         node->token = NJS_TOKEN_REGEXP;
         node->scope = parser->scope;
-        parser->code_size += sizeof(njs_vmcode_regexp_t);
 
         break;
 
@@ -2003,8 +1971,6 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
 
         node->token = NJS_TOKEN_ARGUMENTS;
 
-        parser->code_size += sizeof(njs_vmcode_arguments_t);
-
         break;
 
     case NJS_TOKEN_OBJECT_CONSTRUCTOR:
@@ -2127,7 +2093,6 @@ njs_parser_builtin_object(njs_vm_t *vm, 
     node->scope = parser->scope;
 
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_object_copy_t);
 
     return njs_parser_token(parser);
 }
@@ -2160,7 +2125,6 @@ njs_parser_builtin_function(njs_vm_t *vm
     node->scope = parser->scope;
 
     parser->node = node;
-    parser->code_size += sizeof(njs_vmcode_object_copy_t);
 
     return njs_parser_token(parser);
 }
@@ -2207,7 +2171,6 @@ njs_parser_object(njs_vm_t *vm, njs_pars
         propref->token = NJS_TOKEN_PROPERTY;
         propref->left = object;
         propref->right = parser->node;
-        parser->code_size += sizeof(njs_vmcode_3addr_t);
 
         if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
             return token;
@@ -2242,7 +2205,6 @@ njs_parser_object(njs_vm_t *vm, njs_pars
         stmt->left = left;
         stmt->right = assign;
 
-        parser->code_size += sizeof(njs_vmcode_2addr_t);
         parser->node = stmt;
 
         left = stmt;
@@ -2311,7 +2273,6 @@ njs_parser_array(njs_vm_t *vm, njs_parse
         propref->token = NJS_TOKEN_PROPERTY;
         propref->left = object;
         propref->right = node;
-        parser->code_size += sizeof(njs_vmcode_3addr_t);
 
         token = njs_parser_assignment_expression(vm, parser, token);
         if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
diff -r 23fecf3fcc60 -r 8eb112dcca79 njs/njs_parser.h
--- a/njs/njs_parser.h	Wed Dec 05 15:38:33 2018 +0300
+++ b/njs/njs_parser.h	Fri Dec 07 17:11:33 2018 +0300


More information about the nginx-devel mailing list