From: Dmitry Volyntsev Date: Fri, 7 Dec 2018 14:11:33 +0000 (+0300) Subject: Code generator refactored. X-Git-Tag: 0.2.7~7 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=55ad9032ba5d2c827bb4ebed234dd4f992a11726;p=njs.git 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. --- diff --git a/njs/njs_core.h b/njs/njs_core.h index ea6d3726..4ec9b134 100644 --- a/njs/njs_core.h +++ b/njs/njs_core.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/njs/njs_generator.c b/njs/njs_generator.c index 75549050..06881f5f 100644 --- a/njs/njs_generator.c +++ b/njs/njs_generator.c @@ -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_declaration(njs_vm_t *vm, 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_debug(njs_vm_t *vm, nxt_str_t *name, 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 *parser, njs_parser_node_t *node) } +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, njs_parser_t *parser, 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, njs_parser_t *parser, 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, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, } 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 *vm, njs_parser_t *parser, } 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, } 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, */ 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, 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, njs_parser_t *parser, 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, njs_parser_t *parser, * 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, njs_parser_t *parser, /* 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, njs_parser_t *parser, /* 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, njs_parser_t *parser, 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, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, } 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 *vm, njs_parser_t *parser, /* 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 *vm, njs_parser_t *parser, 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 *vm, njs_parser_t *parser, } 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_vm_t *vm, njs_parser_t *parser) 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 *vm, njs_parser_t *parser) 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_t *vm, njs_parser_t *parser, } 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_t *vm, njs_parser_t *parser, 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, njs_function_lambda_t *lambda, 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_parser_t *parser, njs_parser_node_t *node) 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,23 +2189,17 @@ njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node) parser->code_start = p; parser->code_end = p; - njs_generate_argument_closures(parser, node); - - if (nxt_slow_path(njs_generator(vm, parser, node) != NXT_OK)) { + ret = njs_generate_argument_closures(vm, parser, node); + if (nxt_slow_path(ret != 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); + if (nxt_slow_path(njs_generator(vm, parser, node) != NXT_OK)) { return NXT_ERROR; } + parser->code_size = parser->code_end - parser->code_start; + scope_size = njs_scope_offset(scope->next_index[0]); if (scope->type == NJS_SCOPE_GLOBAL) { @@ -2152,8 +2244,9 @@ njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, 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) { nxt_uint_t n; njs_index_t index; @@ -2164,7 +2257,7 @@ njs_generate_argument_closures(njs_parser_t *parser, njs_parser_node_t *node) 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_parser_t *parser, njs_parser_node_t *node) } } 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_parser_t *parser, } 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, njs_parser_t *parser, 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, njs_parser_t *parser, } 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, njs_parser_t *parser, 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_parser_t *parser, 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, njs_parser_t *parser, 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, njs_parser_t *parser, 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_parser_t *parser, } 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, njs_parser_t *parser, 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, njs_parser_t *parser, 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, njs_parser_t *parser, 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 --git a/njs/njs_generator.h b/njs/njs_generator.h new file mode 100644 index 00000000..4b31b62f --- /dev/null +++ b/njs/njs_generator.h @@ -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 --git a/njs/njs_parser.c b/njs/njs_parser.c index 3942cea9..9f4b7256 100644 --- a/njs/njs_parser.c +++ b/njs/njs_parser.c @@ -523,7 +523,6 @@ njs_parser_function_expression(njs_vm_t *vm, njs_parser_t *parser) 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, njs_function_lambda_t *lambda, } 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, njs_parser_t *parser) 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, njs_parser_t *parser) 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, njs_parser_t *parser) 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, njs_parser_t *parser) 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, njs_parser_t *parser) 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, njs_parser_t *parser) } 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, njs_parser_t *parser) 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 *vm, njs_parser_t *parser) 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, njs_parser_t *parser) 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 *vm, njs_parser_t *parser) 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 *vm, njs_parser_t *parser, 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, njs_parser_t *parser, nxt_str_t *name, 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 *vm, njs_parser_t *parser) 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, njs_parser_t *parser) 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, njs_parser_t *parser) 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, njs_parser_t *parser) 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, njs_parser_t *parser) 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_parser_t *parser, njs_token_t token) 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_parser_t *parser, njs_token_t token) 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_parser_t *parser, njs_token_t token) 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_parser_t *parser, njs_token_t token) 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_parser_t *parser, njs_token_t token) 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, njs_parser_t *parser, 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, njs_parser_t *parser, 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_parser_t *parser, njs_parser_node_t *obj) 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_parser_t *parser, njs_parser_node_t *obj) 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_parser_t *parser, njs_parser_node_t *obj) 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 --git a/njs/njs_parser.h b/njs/njs_parser.h index 659b4468..809d2371 100644 --- a/njs/njs_parser.h +++ b/njs/njs_parser.h @@ -291,12 +291,12 @@ typedef struct njs_parser_patch_s njs_parser_patch_t; struct njs_parser_patch_s { /* - * The address field points to jump offset field which contains a small + * The jump_offset field points to jump offset field which contains a small * adjustment and the adjustment should be added as (njs_ret_t *) because * pointer to u_char accesses only one byte so this does not work on big * endian platforms. */ - njs_ret_t *address; + njs_ret_t jump_offset; njs_parser_patch_t *next; }; @@ -393,14 +393,6 @@ void njs_parser_syntax_error(njs_vm_t *vm, njs_parser_t *parser, const char* fmt, ...); void njs_parser_ref_error(njs_vm_t *vm, njs_parser_t *parser, const char* fmt, ...); -nxt_int_t njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_node_t *node); - - -#define njs_generate_code(parser, type, code) \ - do { \ - code = (type *) parser->code_end; parser->code_end += sizeof(type); \ - } while (0) extern const nxt_lvlhsh_proto_t njs_keyword_hash_proto; diff --git a/njs/njs_parser_expression.c b/njs/njs_parser_expression.c index d4a5c0a7..0f8f1f1b 100644 --- a/njs/njs_parser_expression.c +++ b/njs/njs_parser_expression.c @@ -233,7 +233,6 @@ njs_parser_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) njs_token_t njs_parser_var_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { - size_t size; njs_parser_node_t *node; njs_vmcode_operation_t operation; @@ -248,7 +247,6 @@ njs_parser_var_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) case NJS_TOKEN_ASSIGNMENT: nxt_thread_log_debug("JS: ="); operation = njs_vmcode_move; - size = sizeof(njs_vmcode_move_t); break; default: @@ -270,7 +268,6 @@ njs_parser_var_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) node->u.operation = operation; node->scope = parser->scope; node->left = parser->node; - parser->code_size += size; token = njs_parser_token(parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { @@ -300,7 +297,6 @@ njs_token_t njs_parser_assignment_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { - size_t size; njs_parser_node_t *node; njs_vmcode_operation_t operation; @@ -420,37 +416,6 @@ njs_parser_assignment_expression(njs_vm_t *vm, njs_parser_t *parser, node->right = parser->node; parser->node = node; - - if (node->left->token == NJS_TOKEN_NAME) { - - if (node->token == NJS_TOKEN_ASSIGNMENT) { - size = sizeof(njs_vmcode_move_t); - - } else { - if (njs_parser_has_side_effect(node->right)) { - size = sizeof(njs_vmcode_move_t) - + sizeof(njs_vmcode_3addr_t); - } else { - size = sizeof(njs_vmcode_3addr_t); - } - } - - } else { - if (node->token == NJS_TOKEN_ASSIGNMENT) { - size = sizeof(njs_vmcode_prop_set_t); - - if (njs_parser_has_side_effect(node->right)) { - size += 2 * sizeof(njs_vmcode_move_t); - } - - } else { - size = sizeof(njs_vmcode_prop_get_t) - + sizeof(njs_vmcode_3addr_t) - + sizeof(njs_vmcode_prop_set_t); - } - } - - parser->code_size += size; } } @@ -521,10 +486,6 @@ njs_parser_conditional_expression(njs_vm_t *vm, njs_parser_t *parser, node->right->dest = cond; parser->node = cond; - parser->code_size += sizeof(njs_vmcode_cond_jump_t) - + sizeof(njs_vmcode_move_t) - + sizeof(njs_vmcode_jump_t) - + sizeof(njs_vmcode_move_t); } } @@ -571,8 +532,6 @@ njs_parser_binary_expression(njs_vm_t *vm, njs_parser_t *parser, node->left = parser->node; node->left->dest = node; - parser->code_size += op->size; - token = njs_parser_token(parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; @@ -615,8 +574,6 @@ njs_parser_exponential_expression(njs_vm_t *vm, njs_parser_t *parser, node->left = parser->node; node->left->dest = node; - parser->code_size += sizeof(njs_vmcode_3addr_t); - token = njs_parser_token(parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; @@ -723,7 +680,6 @@ njs_parser_unary_expression(njs_vm_t *vm, njs_parser_t *parser, case NJS_TOKEN_PROPERTY: node->token = NJS_TOKEN_PROPERTY_DELETE; node->u.operation = njs_vmcode_property_delete; - parser->code_size += sizeof(njs_vmcode_3addr_t); return next; @@ -754,7 +710,6 @@ njs_parser_unary_expression(njs_vm_t *vm, njs_parser_t *parser, node->left = parser->node; node->left->dest = node; parser->node = node; - parser->code_size += sizeof(njs_vmcode_2addr_t); return next; } @@ -798,11 +753,6 @@ njs_parser_inc_dec_expression(njs_vm_t *vm, njs_parser_t *parser, return NJS_TOKEN_ILLEGAL; } - parser->code_size += (parser->node->token == NJS_TOKEN_NAME) - ? sizeof(njs_vmcode_3addr_t) - : sizeof(njs_vmcode_3addr_t) - + sizeof(njs_vmcode_prop_set_t); - node = njs_parser_node_alloc(vm); if (nxt_slow_path(node == NULL)) { return NJS_TOKEN_ERROR; @@ -859,11 +809,6 @@ njs_parser_post_inc_dec_expression(njs_vm_t *vm, njs_parser_t *parser, return NJS_TOKEN_ILLEGAL; } - parser->code_size += (parser->node->token == NJS_TOKEN_NAME) - ? sizeof(njs_vmcode_3addr_t) - : sizeof(njs_vmcode_3addr_t) - + sizeof(njs_vmcode_prop_set_t); - node = njs_parser_node_alloc(vm); if (nxt_slow_path(node == NULL)) { return NJS_TOKEN_ERROR; @@ -914,8 +859,7 @@ njs_parser_call_expression(njs_vm_t *vm, njs_parser_t *parser, func = node; func->token = NJS_TOKEN_FUNCTION_CALL; func->scope = parser->scope; - parser->code_size += sizeof(njs_vmcode_function_frame_t) - + sizeof(njs_vmcode_function_call_t); + break; case NJS_TOKEN_PROPERTY: @@ -927,8 +871,7 @@ njs_parser_call_expression(njs_vm_t *vm, njs_parser_t *parser, func->token = NJS_TOKEN_METHOD_CALL; func->scope = parser->scope; func->left = node; - parser->code_size += sizeof(njs_vmcode_method_frame_t) - + sizeof(njs_vmcode_function_call_t); + break; default: @@ -954,8 +897,7 @@ njs_parser_call_expression(njs_vm_t *vm, njs_parser_t *parser, func->token = NJS_TOKEN_FUNCTION_CALL; func->scope = parser->scope; func->left = node; - parser->code_size += sizeof(njs_vmcode_function_frame_t) - + sizeof(njs_vmcode_function_call_t); + break; } @@ -1010,8 +952,7 @@ njs_parser_new_expression(njs_vm_t *vm, njs_parser_t *parser, case NJS_TOKEN_NAME: func = node; func->token = NJS_TOKEN_FUNCTION_CALL; - parser->code_size += sizeof(njs_vmcode_function_frame_t) - + sizeof(njs_vmcode_function_call_t); + break; case NJS_TOKEN_PROPERTY: @@ -1023,8 +964,7 @@ njs_parser_new_expression(njs_vm_t *vm, njs_parser_t *parser, func->token = NJS_TOKEN_METHOD_CALL; func->scope = parser->scope; func->left = node; - parser->code_size += sizeof(njs_vmcode_method_frame_t) - + sizeof(njs_vmcode_function_call_t); + break; default: @@ -1050,8 +990,7 @@ njs_parser_new_expression(njs_vm_t *vm, njs_parser_t *parser, func->token = NJS_TOKEN_FUNCTION_CALL; func->scope = parser->scope; func->left = node; - parser->code_size += sizeof(njs_vmcode_function_frame_t) - + sizeof(njs_vmcode_function_call_t); + break; } @@ -1124,8 +1063,6 @@ njs_parser_property_expression(njs_vm_t *vm, njs_parser_t *parser, node->right = parser->node; parser->node = node; - - parser->code_size += sizeof(njs_vmcode_prop_get_t); } } @@ -1210,8 +1147,6 @@ njs_parser_arguments(njs_vm_t *vm, njs_parser_t *parser, parent->right = node; parent = node; - parser->code_size += sizeof(njs_vmcode_move_t); - } while (token == NJS_TOKEN_COMMA); if (nxt_slow_path(token != NJS_TOKEN_CLOSE_PARENTHESIS)) {