Mercurial > vim
diff src/vim9compile.c @ 23723:14e92f4c98c9 v8.2.2403
patch 8.2.2403: Vim9: profiling if/elseif/endif not correct
Commit: https://github.com/vim/vim/commit/ced68a0070dac059fc978a1a99e2893edf158116
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jan 24 17:53:47 2021 +0100
patch 8.2.2403: Vim9: profiling if/elseif/endif not correct
Problem: Vim9: profiling if/elseif/endif not correct.
Solution: Add profile instructions. Fix that "elseif" was wrong.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 24 Jan 2021 18:00:04 +0100 |
parents | 1a7c2685d780 |
children | f98692ae09a0 |
line wrap: on
line diff
--- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -44,6 +44,7 @@ struct endlabel_S { */ typedef struct { int is_seen_else; + int is_seen_skip_not; // a block was unconditionally executed int is_had_return; // every block ends in :return int is_if_label; // instruction idx at IF or ELSEIF endlabel_T *is_end_label; // instructions to set end label @@ -2098,13 +2099,7 @@ generate_undo_cmdmods(cctx_T *cctx) may_generate_prof_end(cctx_T *cctx, int prof_lnum) { if (cctx->ctx_profiling && prof_lnum >= 0) - { - int save_lnum = cctx->ctx_lnum; - - cctx->ctx_lnum = prof_lnum; generate_instr(cctx, ISN_PROF_END); - cctx->ctx_lnum = save_lnum; - } } #endif @@ -6735,6 +6730,18 @@ compile_if(char_u *arg, cctx_T *cctx) else scope->se_u.se_if.is_if_label = -1; +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES + && skip_save != SKIP_YES) + { + // generated a profile start, need to generate a profile end, since it + // won't be done after returning + cctx->ctx_skip = SKIP_NOT; + generate_instr(cctx, ISN_PROF_END); + cctx->ctx_skip = SKIP_YES; + } +#endif + return p; } @@ -6758,6 +6765,25 @@ compile_elseif(char_u *arg, cctx_T *cctx if (!cctx->ctx_had_return) scope->se_u.se_if.is_had_return = FALSE; + if (cctx->ctx_skip == SKIP_NOT) + { + // previous block was executed, this one and following will not + cctx->ctx_skip = SKIP_YES; + scope->se_u.se_if.is_seen_skip_not = TRUE; + } + if (scope->se_u.se_if.is_seen_skip_not) + { + // A previous block was executed, skip over expression and bail out. + // Do not count the "elseif" for profiling. +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1] + .isn_type == ISN_PROF_START) + --instr->ga_len; +#endif + skip_expr_cctx(&p, cctx); + return p; + } + if (cctx->ctx_skip == SKIP_UNKNOWN) { if (compile_jump_to_end(&scope->se_u.se_if.is_end_label, @@ -6771,7 +6797,17 @@ compile_elseif(char_u *arg, cctx_T *cctx // compile "expr"; if we know it evaluates to FALSE skip the block CLEAR_FIELD(ppconst); if (cctx->ctx_skip == SKIP_YES) + { cctx->ctx_skip = SKIP_UNKNOWN; +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling) + { + // the previous block was skipped, need to profile this line + generate_instr(cctx, ISN_PROF_START); + instr_count = instr->ga_len; + } +#endif + } if (compile_expr1(&p, cctx, &ppconst) == FAIL) { clear_ppconst(&ppconst); @@ -6829,7 +6865,27 @@ compile_else(char_u *arg, cctx_T *cctx) scope->se_u.se_if.is_had_return = FALSE; scope->se_u.se_if.is_seen_else = TRUE; - if (scope->se_skip_save != SKIP_YES) +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling) + { + if (cctx->ctx_skip == SKIP_NOT + && ((isn_T *)instr->ga_data)[instr->ga_len - 1] + .isn_type == ISN_PROF_START) + // the previous block was executed, do not count "else" for profiling + --instr->ga_len; + if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not) + { + // the previous block was not executed, this one will, do count the + // "else" for profiling + cctx->ctx_skip = SKIP_NOT; + generate_instr(cctx, ISN_PROF_END); + generate_instr(cctx, ISN_PROF_START); + cctx->ctx_skip = SKIP_YES; + } + } +#endif + + if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES) { // jump from previous block to the end, unless the else block is empty if (cctx->ctx_skip == SKIP_UNKNOWN) @@ -6884,6 +6940,17 @@ compile_endif(char_u *arg, cctx_T *cctx) } // Fill in the "end" label in jumps at the end of the blocks. compile_fill_jump_to_end(&ifscope->is_end_label, cctx); + +#ifdef FEAT_PROFILE + // even when skipping we count the endif as executed, unless the block it's + // in is skipped + if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES + && scope->se_skip_save != SKIP_YES) + { + cctx->ctx_skip = SKIP_NOT; + generate_instr(cctx, ISN_PROF_START); + } +#endif cctx->ctx_skip = scope->se_skip_save; // If all the blocks end in :return and there is an :else then the @@ -8005,7 +8072,8 @@ compile_def_function( { // beyond the last line #ifdef FEAT_PROFILE - may_generate_prof_end(&cctx, prof_lnum); + if (cctx.ctx_skip != SKIP_YES) + may_generate_prof_end(&cctx, prof_lnum); #endif break; } @@ -8023,7 +8091,8 @@ compile_def_function( } #ifdef FEAT_PROFILE - if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum) + if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum && + cctx.ctx_skip != SKIP_YES) { may_generate_prof_end(&cctx, prof_lnum);