]> granicus.if.org Git - vim/commitdiff
patch 8.2.3893: Vim9: many local variables are initialized with an instruction v8.2.3893
authorBram Moolenaar <Bram@vim.org>
Sat, 25 Dec 2021 18:23:24 +0000 (18:23 +0000)
committerBram Moolenaar <Bram@vim.org>
Sat, 25 Dec 2021 18:23:24 +0000 (18:23 +0000)
Problem:    Vim9: many local variables are initialized with an instruction.
Solution:   Initialize local variables to zero to avoid the instructions.

src/proto/vim9instr.pro
src/testdir/test_vim9_disassemble.vim
src/version.c
src/vim9cmds.c
src/vim9compile.c
src/vim9execute.c
src/vim9instr.c

index 4df3af001826a7ce8a360c9036212d64329097fb..0083334d91f335d423f24396b2dc68ae2516940e 100644 (file)
@@ -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);
index b1ba6750acbbc537217a280ffc1bba4bf216721f..3b8e12d01b20e7c7b531d00534216739dbc9293e 100644 (file)
@@ -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())
index bca7604dc1f8eb9fed400858fa16cc51cff8ea6c..423ec6ecc195645ddb6002a14af359485d72d2cb 100644 (file)
@@ -749,6 +749,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3893,
 /**/
     3892,
 /**/
index 5c7a9387978533598bd768baf8c2f4c0c86fa997..4e5336cf23be0a221770c280e326411ee8ca0805 100644 (file)
@@ -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);
index 7565cfb01c16da8376ee524334ba270b0e4f8a27..e9d6089b10a20366f3cfe039b10936688e94f691 100644 (file)
@@ -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;
index 72cbb9044d8aacc7b15c7dcb4063b061ed419b1f..49336c0992daf43f5c073f9c4e1a87f822b1628d 100644 (file)
@@ -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)
        {
index 0468f336c783ea373b95c71d61a80d118aa42dad..0483068aa2c027225d5b63d09f23c07f7d9f4659 100644 (file)
@@ -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;
        }