diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-01-25 21:01:48 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-01-25 21:01:48 +0100 |
commit | e5ea346a07a7750c02a89996b67716b43c767d06 (patch) | |
tree | 638de91e30f3a1add0c78c7b75bddf6cedd46ff5 | |
parent | 5c829bf229de463657e4ba1de6c4ee91899de14e (diff) | |
download | vim-git-e5ea346a07a7750c02a89996b67716b43c767d06.tar.gz |
patch 8.2.2409: Vim9: profiling only works for one functionv8.2.2409
Problem: Vim9: profiling only works for one function.
Solution: Select the right instructions when calling and returning.
(closes #7743)
-rw-r--r-- | src/testdir/test_profile.vim | 18 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9.h | 10 | ||||
-rw-r--r-- | src/vim9compile.c | 14 | ||||
-rw-r--r-- | src/vim9execute.c | 36 |
5 files changed, 54 insertions, 26 deletions
diff --git a/src/testdir/test_profile.vim b/src/testdir/test_profile.vim index 8aaac90e8..3abe89805 100644 --- a/src/testdir/test_profile.vim +++ b/src/testdir/test_profile.vim @@ -5,6 +5,7 @@ CheckFeature profile source shared.vim source screendump.vim +source vim9.vim func Test_profile_func() call RunProfileFunc('func', 'let', 'let') @@ -583,4 +584,21 @@ func Test_profile_typed_func() call delete('XtestProfile') endfunc +func Test_vim9_profiling() + " only tests that compiling and calling functions doesn't crash + let lines =<< trim END + vim9script + def Func() + Crash() + enddef + def Crash() + enddef + prof start /tmp/profile.log + prof func Func + Func() + END + call CheckScriptSuccess(lines) +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index dce32e733..279c49d0c 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2409, +/**/ 2408, /**/ 2407, diff --git a/src/vim9.h b/src/vim9.h index f8d51c502..76ec40303 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -408,3 +408,13 @@ extern garray_T def_functions; // Used for "lnum" when a range is to be taken from the stack and "!" is used. #define LNUM_VARIABLE_RANGE_ABOVE -888 + +#ifdef FEAT_PROFILE +# define PROFILING(ufunc) (do_profiling == PROF_YES && (ufunc)->uf_profiling) +# define INSTRUCTIONS(dfunc) \ + ((do_profiling == PROF_YES && (dfunc->df_ufunc)->uf_profiling) \ + ? (dfunc)->df_instr_prof : (dfunc)->df_instr) +#else +# define PROFILING FALSE +# define INSTRUCTIONS(dfunc) ((dfunc)->df_instr) +#endif diff --git a/src/vim9compile.c b/src/vim9compile.c index 2dd3a4ffe..5b9f7f518 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1775,9 +1775,9 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount) return FAIL; } } - if (func_needs_compiling(ufunc, cctx->ctx_profiling) + if (func_needs_compiling(ufunc, PROFILING(ufunc)) && compile_def_function(ufunc, ufunc->uf_ret_type == NULL, - cctx->ctx_profiling, NULL) == FAIL) + PROFILING(ufunc), NULL) == FAIL) return FAIL; } @@ -2615,8 +2615,8 @@ generate_funcref(cctx_T *cctx, char_u *name) return FAIL; // Need to compile any default values to get the argument types. - if (func_needs_compiling(ufunc, cctx->ctx_profiling) - && compile_def_function(ufunc, TRUE, cctx->ctx_profiling, NULL) + if (func_needs_compiling(ufunc, PROFILING(ufunc)) + && compile_def_function(ufunc, TRUE, PROFILING(ufunc), NULL) == FAIL) return FAIL; return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type); @@ -3111,7 +3111,7 @@ compile_lambda(char_u **arg, cctx_T *cctx) clear_tv(&rettv); // Compile the function into instructions. - compile_def_function(ufunc, TRUE, cctx->ctx_profiling, cctx); + compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx); clear_evalarg(&evalarg, NULL); @@ -5088,8 +5088,8 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) r = eap->skip ? OK : FAIL; goto theend; } - if (func_needs_compiling(ufunc, cctx->ctx_profiling) - && compile_def_function(ufunc, TRUE, cctx->ctx_profiling, cctx) + if (func_needs_compiling(ufunc, PROFILING(ufunc)) + && compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx) == FAIL) { func_ptr_unref(ufunc); diff --git a/src/vim9execute.c b/src/vim9execute.c index 4c144f67a..bcdc5d190 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -181,6 +181,16 @@ call_dfunc(int cdf_idx, partial_T *pt, int argcount_arg, ectx_T *ectx) return FAIL; } +#ifdef FEAT_PROFILE + // Profiling might be enabled/disabled along the way. This should not + // fail, since the function was compiled before and toggling profiling + // doesn't change any errors. + if (func_needs_compiling(ufunc, PROFILING(ufunc)) + && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL) + == FAIL) + return FAIL; +#endif + if (ufunc->uf_va_name != NULL) { // Need to make a list out of the vararg arguments. @@ -293,7 +303,7 @@ call_dfunc(int cdf_idx, partial_T *pt, int argcount_arg, ectx_T *ectx) // Set execution state to the start of the called function. ectx->ec_dfunc_idx = cdf_idx; - ectx->ec_instr = dfunc->df_instr; + ectx->ec_instr = INSTRUCTIONS(dfunc); entry = estack_push_ufunc(ufunc, 1); if (entry != NULL) { @@ -542,7 +552,7 @@ func_return(ectx_T *ectx) ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_IDX_OFF)->vval.v_number; dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; - ectx->ec_instr = dfunc->df_instr; + ectx->ec_instr = INSTRUCTIONS(dfunc); if (ret_idx > 0) { @@ -1103,6 +1113,7 @@ fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx) return OK; } + /* * Call a "def" function from old Vim script. * Return OK or FAIL. @@ -1135,11 +1146,6 @@ call_def_function( int save_did_emsg_def = did_emsg_def; int trylevel_at_start = trylevel; int orig_funcdepth; -#ifdef FEAT_PROFILE - int profiling = do_profiling == PROF_YES && ufunc->uf_profiling; -#else -# define profiling FALSE -#endif // Get pointer to item in the stack. #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) @@ -1152,8 +1158,8 @@ call_def_function( #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx) if (ufunc->uf_def_status == UF_NOT_COMPILED - || (func_needs_compiling(ufunc, profiling) - && compile_def_function(ufunc, FALSE, profiling, NULL) + || (func_needs_compiling(ufunc, PROFILING(ufunc)) + && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL) == FAIL)) { if (did_emsg_cumul + did_emsg == did_emsg_before) @@ -1166,11 +1172,7 @@ call_def_function( // Check the function was really compiled. dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; - if (( -#ifdef FEAT_PROFILE - profiling ? dfunc->df_instr_prof : -#endif - dfunc->df_instr) == NULL) + if (INSTRUCTIONS(dfunc) == NULL) { iemsg("using call_def_function() on not compiled function"); return FAIL; @@ -1309,11 +1311,7 @@ call_def_function( ++ectx.ec_stack.ga_len; } -#ifdef FEAT_PROFILE - ectx.ec_instr = profiling ? dfunc->df_instr_prof : dfunc->df_instr; -#else - ectx.ec_instr = dfunc->df_instr; -#endif + ectx.ec_instr = INSTRUCTIONS(dfunc); } // Following errors are in the function, not the caller. |