summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-12-25 18:23:24 +0000
committerBram Moolenaar <Bram@vim.org>2021-12-25 18:23:24 +0000
commit5cd647935d0834b3064aa36384b8f6730fadadd6 (patch)
treed0b40261ac7160d723f5bca46cf57d43641e9aed
parent35cfd793aad7c4bfba4a9bedf5c435c44e4293d0 (diff)
downloadvim-git-5cd647935d0834b3064aa36384b8f6730fadadd6.tar.gz
patch 8.2.3893: Vim9: many local variables are initialized with an instructionv8.2.3893
Problem: Vim9: many local variables are initialized with an instruction. Solution: Initialize local variables to zero to avoid the instructions.
-rw-r--r--src/proto/vim9instr.pro2
-rw-r--r--src/testdir/test_vim9_disassemble.vim23
-rw-r--r--src/version.c2
-rw-r--r--src/vim9cmds.c2
-rw-r--r--src/vim9compile.c11
-rw-r--r--src/vim9execute.c14
-rw-r--r--src/vim9instr.c20
7 files changed, 51 insertions, 23 deletions
diff --git a/src/proto/vim9instr.pro b/src/proto/vim9instr.pro
index 4df3af001..0083334d9 100644
--- a/src/proto/vim9instr.pro
+++ b/src/proto/vim9instr.pro
@@ -65,7 +65,7 @@ int generate_UNPACK(cctx_T *cctx, int var_count, int semicolon);
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
index b1ba6750a..3b8e12d01 100644
--- 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
index bca7604dc..423ec6ecc 100644
--- 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
index 5c7a93879..4e5336cf2 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -2092,7 +2092,7 @@ compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
&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
index 7565cfb01..e9d6089b1 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1963,6 +1963,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
{
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 *eap, cmdidx_T cmdidx, cctx_T *cctx)
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 *eap, cmdidx_T cmdidx, cctx_T *cctx)
// 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
index 72cbb9044..49336c099 100644
--- 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
index 0468f336c..0483068aa 100644
--- 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 *lhs, int instr_count)
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 *lhs, int instr_count)
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;
}