# HG changeset patch # User Bram Moolenaar # Date 1640457003 -3600 # Node ID b969fdb8cd4640605d4361432c6c6a4a2f29cec8 # Parent 71ae885c1426a04424f6d682a607c0a8bb883137 patch 8.2.3893: Vim9: many local variables are initialized with an instruction Commit: https://github.com/vim/vim/commit/5cd647935d0834b3064aa36384b8f6730fadadd6 Author: Bram Moolenaar Date: Sat Dec 25 18:23:24 2021 +0000 patch 8.2.3893: Vim9: many local variables are initialized with an instruction Problem: Vim9: many local variables are initialized with an instruction. Solution: Initialize local variables to zero to avoid the instructions. diff --git a/src/proto/vim9instr.pro b/src/proto/vim9instr.pro --- a/src/proto/vim9instr.pro +++ b/src/proto/vim9instr.pro @@ -65,7 +65,7 @@ int generate_UNPACK(cctx_T *cctx, int va int generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod); int generate_undo_cmdmods(cctx_T *cctx); int generate_store_var(cctx_T *cctx, assign_dest_T dest, int opt_flags, int vimvaridx, int scriptvar_idx, int scriptvar_sid, type_T *type, char_u *name); -int generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count); +int generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl); void may_generate_prof_end(cctx_T *cctx, int prof_lnum); void delete_instr(isn_T *isn); void clear_instr_ga(garray_T *gap); diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -1773,6 +1773,7 @@ enddef def ReturnBool(): bool var one = 1 var zero = 0 + var none: number var name: bool = one && zero || one return name enddef @@ -1783,19 +1784,19 @@ def Test_disassemble_return_bool() 'var one = 1\_s*' .. '0 STORE 1 in $0\_s*' .. 'var zero = 0\_s*' .. - '1 STORE 0 in $1\_s*' .. + 'var none: number\_s*' .. 'var name: bool = one && zero || one\_s*' .. - '2 LOAD $0\_s*' .. - '3 COND2BOOL\_s*' .. - '4 JUMP_IF_COND_FALSE -> 7\_s*' .. - '5 LOAD $1\_s*' .. - '6 COND2BOOL\_s*' .. - '7 JUMP_IF_COND_TRUE -> 10\_s*' .. - '8 LOAD $0\_s*' .. - '9 COND2BOOL\_s*' .. - '10 STORE $2\_s*' .. + '1 LOAD $0\_s*' .. + '2 COND2BOOL\_s*' .. + '3 JUMP_IF_COND_FALSE -> 6\_s*' .. + '4 LOAD $1\_s*' .. + '5 COND2BOOL\_s*' .. + '6 JUMP_IF_COND_TRUE -> 9\_s*' .. + '7 LOAD $0\_s*' .. + '8 COND2BOOL\_s*' .. + '9 STORE $3\_s*' .. 'return name\_s*' .. - '\d\+ LOAD $2\_s*' .. + '\d\+ LOAD $3\_s*' .. '\d\+ RETURN', instr) assert_equal(true, InvertBool()) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3893, +/**/ 3892, /**/ 3891, diff --git a/src/vim9cmds.c b/src/vim9cmds.c --- a/src/vim9cmds.c +++ b/src/vim9cmds.c @@ -2092,7 +2092,7 @@ compile_redir(char_u *line, exarg_T *eap &t_string, cctx) == FAIL) return NULL; } - else if (generate_store_lhs(cctx, lhs, -1) == FAIL) + else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL) return NULL; VIM_CLEAR(lhs->lhs_name); diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1963,6 +1963,7 @@ compile_assignment(char_u *arg, exarg_T { int instr_count = -1; int save_lnum; + int skip_store = FALSE; if (var_start[0] == '_' && !eval_isnamec(var_start[1])) { @@ -2186,7 +2187,12 @@ compile_assignment(char_u *arg, exarg_T case VAR_VOID: case VAR_INSTR: case VAR_SPECIAL: // cannot happen - generate_PUSHNR(cctx, 0); + // This is skipped for local variables, they are + // always initialized to zero. + if (lhs.lhs_dest == dest_local) + skip_store = TRUE; + else + generate_PUSHNR(cctx, 0); break; } } @@ -2278,7 +2284,8 @@ compile_assignment(char_u *arg, exarg_T // type of "val" is used. generate_SETTYPE(cctx, lhs.lhs_type); - if (generate_store_lhs(cctx, &lhs, instr_count) == FAIL) + if (!skip_store && generate_store_lhs(cctx, &lhs, + instr_count, is_decl) == FAIL) { cctx->ctx_lnum = save_lnum; goto theend; diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -397,7 +397,12 @@ call_dfunc( // Initialize local variables for (idx = 0; idx < dfunc->df_varcount; ++idx) - STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN; + { + typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + idx); + + tv->v_type = VAR_NUMBER; + tv->vval.v_number = 0; + } if (dfunc->df_has_closure) { typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + dfunc->df_varcount); @@ -5002,8 +5007,13 @@ call_def_function( dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; + // Initialize variables to zero. That avoids having to generate + // initializing instructions for "var nr: number", "var x: any", etc. for (idx = 0; idx < dfunc->df_varcount; ++idx) - STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; + { + STACK_TV_VAR(idx)->v_type = VAR_NUMBER; + STACK_TV_VAR(idx)->vval.v_number = 0; + } ectx.ec_stack.ga_len += dfunc->df_varcount; if (dfunc->df_has_closure) { diff --git a/src/vim9instr.c b/src/vim9instr.c --- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -1886,7 +1886,7 @@ generate_store_var( } int -generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count) +generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl) { if (lhs->lhs_dest != dest_local) return generate_store_var(cctx, lhs->lhs_dest, @@ -1899,8 +1899,9 @@ generate_store_lhs(cctx_T *cctx, lhs_T * garray_T *instr = &cctx->ctx_instr; isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1; - // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE into - // ISN_STORENR + // Optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE into + // ISN_STORENR. + // And "var = 0" does not need any instruction. if (lhs->lhs_lvar->lv_from_outer == 0 && instr->ga_len == instr_count + 1 && isn->isn_type == ISN_PUSHNR) @@ -1908,9 +1909,16 @@ generate_store_lhs(cctx_T *cctx, lhs_T * varnumber_T val = isn->isn_arg.number; garray_T *stack = &cctx->ctx_type_stack; - isn->isn_type = ISN_STORENR; - isn->isn_arg.storenr.stnr_idx = lhs->lhs_lvar->lv_idx; - isn->isn_arg.storenr.stnr_val = val; + if (val == 0 && is_decl) + { + --instr->ga_len; + } + else + { + isn->isn_type = ISN_STORENR; + isn->isn_arg.storenr.stnr_idx = lhs->lhs_lvar->lv_idx; + isn->isn_arg.storenr.stnr_val = val; + } if (stack->ga_len > 0) --stack->ga_len; }