patch 8.2.2400: Vim9: compiled functions are not profiled
Problem: Vim9: compiled functions are not profiled.
Solution: Add initial changes to profile compiled functions. Fix that a
script-local function was hard to debug.
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 232c84e..e494885 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -294,7 +294,7 @@
// Set execution state to the start of the called function.
ectx->ec_dfunc_idx = cdf_idx;
ectx->ec_instr = dfunc->df_instr;
- entry = estack_push_ufunc(dfunc->df_ufunc, 1);
+ entry = estack_push_ufunc(ufunc, 1);
if (entry != NULL)
{
// Set the script context to the script where the function was defined.
@@ -645,9 +645,10 @@
int error;
int idx;
int did_emsg_before = did_emsg;
+ int profiling = do_profiling == PROF_YES && ufunc->uf_profiling;
- if (ufunc->uf_def_status == UF_TO_BE_COMPILED
- && compile_def_function(ufunc, FALSE, NULL) == FAIL)
+ if (func_needs_compiling(ufunc, profiling)
+ && compile_def_function(ufunc, FALSE, profiling, NULL) == FAIL)
return FAIL;
if (ufunc->uf_def_status == UF_COMPILED)
{
@@ -1130,6 +1131,7 @@
int save_did_emsg_def = did_emsg_def;
int trylevel_at_start = trylevel;
int orig_funcdepth;
+ int profiling = do_profiling == PROF_YES && ufunc->uf_profiling;
// Get pointer to item in the stack.
#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
@@ -1142,8 +1144,9 @@
#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
- || (ufunc->uf_def_status == UF_TO_BE_COMPILED
- && compile_def_function(ufunc, FALSE, NULL) == FAIL))
+ || (func_needs_compiling(ufunc, profiling)
+ && compile_def_function(ufunc, FALSE, profiling, NULL)
+ == FAIL))
{
if (did_emsg_cumul + did_emsg == did_emsg_before)
semsg(_(e_function_is_not_compiled_str),
@@ -1155,7 +1158,7 @@
// Check the function was really compiled.
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
+ ufunc->uf_dfunc_idx;
- if (dfunc->df_instr == NULL)
+ if ((profiling ? dfunc->df_instr_prof : dfunc->df_instr) == NULL)
{
iemsg("using call_def_function() on not compiled function");
return FAIL;
@@ -1294,7 +1297,7 @@
++ectx.ec_stack.ga_len;
}
- ectx.ec_instr = dfunc->df_instr;
+ ectx.ec_instr = profiling ? dfunc->df_instr_prof : dfunc->df_instr;
}
// Following errors are in the function, not the caller.
@@ -3495,6 +3498,26 @@
}
break;
+ case ISN_PROF_START:
+ case ISN_PROF_END:
+ {
+ funccall_T cookie;
+ ufunc_T *cur_ufunc =
+ (((dfunc_T *)def_functions.ga_data)
+ + ectx.ec_dfunc_idx)->df_ufunc;
+
+ cookie.func = cur_ufunc;
+ if (iptr->isn_type == ISN_PROF_START)
+ {
+ func_line_start(&cookie, iptr->isn_lnum);
+ // if we get here the instruction is executed
+ func_line_exec(&cookie);
+ }
+ else
+ func_line_end(&cookie);
+ }
+ break;
+
case ISN_SHUFFLE:
{
typval_T tmp_tv;
@@ -3642,6 +3665,7 @@
ufunc_T *ufunc;
dfunc_T *dfunc;
isn_T *instr;
+ int instr_count;
int current;
int line_idx = 0;
int prev_current = 0;
@@ -3677,8 +3701,8 @@
semsg(_(e_cannot_find_function_str), eap->arg);
return;
}
- if (ufunc->uf_def_status == UF_TO_BE_COMPILED
- && compile_def_function(ufunc, FALSE, NULL) == FAIL)
+ if (func_needs_compiling(ufunc, eap->forceit)
+ && compile_def_function(ufunc, FALSE, eap->forceit, NULL) == FAIL)
return;
if (ufunc->uf_def_status != UF_COMPILED)
{
@@ -3691,8 +3715,10 @@
msg((char *)ufunc->uf_name);
dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
- instr = dfunc->df_instr;
- for (current = 0; current < dfunc->df_instr_count; ++current)
+ instr = eap->forceit ? dfunc->df_instr_prof : dfunc->df_instr;
+ instr_count = eap->forceit ? dfunc->df_instr_prof_count
+ : dfunc->df_instr_count;
+ for (current = 0; current < instr_count; ++current)
{
isn_T *iptr = &instr[current];
char *line;
@@ -4319,6 +4345,14 @@
}
case ISN_CMDMOD_REV: smsg("%4d CMDMOD_REV", current); break;
+ case ISN_PROF_START:
+ smsg("%4d PROFILE START line %d", current, iptr->isn_lnum);
+ break;
+
+ case ISN_PROF_END:
+ smsg("%4d PROFILE END", current);
+ break;
+
case ISN_UNPACK: smsg("%4d UNPACK %d%s", current,
iptr->isn_arg.unpack.unp_count,
iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : "");