mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.2985: Vim9: a compiled function cannot be debugged
Problem: Vim9: a compiled function cannot be debugged. Solution: Add initial debugging support.
This commit is contained in:
@@ -3536,7 +3536,7 @@ eval7(
|
|||||||
if (ufunc->uf_ret_type->tt_type == VAR_VOID)
|
if (ufunc->uf_ret_type->tt_type == VAR_VOID)
|
||||||
ufunc->uf_ret_type = &t_unknown;
|
ufunc->uf_ret_type = &t_unknown;
|
||||||
if (compile_def_function(ufunc,
|
if (compile_def_function(ufunc,
|
||||||
FALSE, PROFILING(ufunc), NULL) == FAIL)
|
FALSE, COMPILE_TYPE(ufunc), NULL) == FAIL)
|
||||||
{
|
{
|
||||||
clear_tv(rettv);
|
clear_tv(rettv);
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
|
@@ -3,7 +3,7 @@ int check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg);
|
|||||||
int check_compare_types(exprtype_T type, typval_T *tv1, typval_T *tv2);
|
int check_compare_types(exprtype_T type, typval_T *tv1, typval_T *tv2);
|
||||||
int use_typecheck(type_T *actual, type_T *expected);
|
int use_typecheck(type_T *actual, type_T *expected);
|
||||||
int need_type(type_T *actual, type_T *expected, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const);
|
int need_type(type_T *actual, type_T *expected, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const);
|
||||||
int func_needs_compiling(ufunc_T *ufunc, int profile);
|
int func_needs_compiling(ufunc_T *ufunc, compiletype_T compile_type);
|
||||||
int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx);
|
int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx);
|
||||||
imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx);
|
imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx);
|
||||||
imported_T *find_imported_in_script(char_u *name, size_t len, int sid);
|
imported_T *find_imported_in_script(char_u *name, size_t len, int sid);
|
||||||
@@ -17,7 +17,7 @@ void fill_exarg_from_cctx(exarg_T *eap, cctx_T *cctx);
|
|||||||
int assignment_len(char_u *p, int *heredoc);
|
int assignment_len(char_u *p, int *heredoc);
|
||||||
void vim9_declare_error(char_u *name);
|
void vim9_declare_error(char_u *name);
|
||||||
int check_vim9_unlet(char_u *name);
|
int check_vim9_unlet(char_u *name);
|
||||||
int compile_def_function(ufunc_T *ufunc, int check_return_type, int profiling, cctx_T *outer_cctx);
|
int compile_def_function(ufunc_T *ufunc, int check_return_type, compiletype_T compile_type, cctx_T *outer_cctx);
|
||||||
void set_function_type(ufunc_T *ufunc);
|
void set_function_type(ufunc_T *ufunc);
|
||||||
void delete_instr(isn_T *isn);
|
void delete_instr(isn_T *isn);
|
||||||
void unlink_def_function(ufunc_T *ufunc);
|
void unlink_def_function(ufunc_T *ufunc);
|
||||||
|
@@ -884,19 +884,20 @@ func Test_Backtrace_DefFunction()
|
|||||||
\ ':debug call GlobalFunction()',
|
\ ':debug call GlobalFunction()',
|
||||||
\ ['cmd: call GlobalFunction()'])
|
\ ['cmd: call GlobalFunction()'])
|
||||||
|
|
||||||
" FIXME: Vim9 lines are not debugged!
|
call RunDbgCmd(buf, 'step', ['line 1: CallAFunction()'])
|
||||||
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
|
|
||||||
|
|
||||||
" But they do appear in the backtrace
|
" FIXME: not quite right
|
||||||
call RunDbgCmd(buf, 'backtrace', [
|
call RunDbgCmd(buf, 'backtrace', [
|
||||||
\ '\V>backtrace',
|
\ '\V>backtrace',
|
||||||
\ '\V 2 function GlobalFunction[1]',
|
\ '\V->0 function GlobalFunction',
|
||||||
\ '\V 1 <SNR>\.\*_CallAFunction[1]',
|
\ '\Vline 1: CallAFunction()',
|
||||||
\ '\V->0 <SNR>\.\*_SourceAnotherFile',
|
\ ],
|
||||||
\ '\Vline 1: source Xtest2.vim'],
|
|
||||||
\ #{match: 'pattern'})
|
\ #{match: 'pattern'})
|
||||||
|
|
||||||
|
call RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
|
||||||
|
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
|
||||||
|
" FIXME: repeated line
|
||||||
|
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
|
||||||
call RunDbgCmd(buf, 'step', ['line 1: vim9script'])
|
call RunDbgCmd(buf, 'step', ['line 1: vim9script'])
|
||||||
call RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number'])
|
call RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number'])
|
||||||
call RunDbgCmd(buf, 'step', ['line 9: export def File2Function()'])
|
call RunDbgCmd(buf, 'step', ['line 9: export def File2Function()'])
|
||||||
@@ -913,7 +914,7 @@ func Test_Backtrace_DefFunction()
|
|||||||
\ #{match: 'pattern'})
|
\ #{match: 'pattern'})
|
||||||
|
|
||||||
" Don't step into compiled functions...
|
" Don't step into compiled functions...
|
||||||
call RunDbgCmd(buf, 'step', ['line 15: End of sourced file'])
|
call RunDbgCmd(buf, 'next', ['line 15: End of sourced file'])
|
||||||
call RunDbgCmd(buf, 'backtrace', [
|
call RunDbgCmd(buf, 'backtrace', [
|
||||||
\ '\V>backtrace',
|
\ '\V>backtrace',
|
||||||
\ '\V 3 function GlobalFunction[1]',
|
\ '\V 3 function GlobalFunction[1]',
|
||||||
@@ -923,7 +924,6 @@ func Test_Backtrace_DefFunction()
|
|||||||
\ '\Vline 15: End of sourced file'],
|
\ '\Vline 15: End of sourced file'],
|
||||||
\ #{match: 'pattern'})
|
\ #{match: 'pattern'})
|
||||||
|
|
||||||
|
|
||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
call delete('Xtest1.vim')
|
call delete('Xtest1.vim')
|
||||||
call delete('Xtest2.vim')
|
call delete('Xtest2.vim')
|
||||||
@@ -1116,6 +1116,7 @@ func Test_debug_backtrace_level()
|
|||||||
\ [ 'E121: Undefined variable: s:file1_var' ] )
|
\ [ 'E121: Undefined variable: s:file1_var' ] )
|
||||||
call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
|
call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
|
||||||
|
|
||||||
|
call RunDbgCmd(buf, 'cont')
|
||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
call delete('Xtest1.vim')
|
call delete('Xtest1.vim')
|
||||||
call delete('Xtest2.vim')
|
call delete('Xtest2.vim')
|
||||||
|
@@ -2153,7 +2153,7 @@ def Test_profiled()
|
|||||||
if !has('profile')
|
if !has('profile')
|
||||||
MissingFeature 'profile'
|
MissingFeature 'profile'
|
||||||
endif
|
endif
|
||||||
var res = execute('disass! s:Profiled')
|
var res = execute('disass profile s:Profiled')
|
||||||
assert_match('<SNR>\d*_Profiled\_s*' ..
|
assert_match('<SNR>\d*_Profiled\_s*' ..
|
||||||
'echo "profiled"\_s*' ..
|
'echo "profiled"\_s*' ..
|
||||||
'\d PROFILE START line 1\_s*' ..
|
'\d PROFILE START line 1\_s*' ..
|
||||||
@@ -2168,6 +2168,20 @@ def Test_profiled()
|
|||||||
res)
|
res)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_debugged()
|
||||||
|
var res = execute('disass debug s:Profiled')
|
||||||
|
assert_match('<SNR>\d*_Profiled\_s*' ..
|
||||||
|
'echo "profiled"\_s*' ..
|
||||||
|
'\d DEBUG line 1\_s*' ..
|
||||||
|
'\d PUSHS "profiled"\_s*' ..
|
||||||
|
'\d ECHO 1\_s*' ..
|
||||||
|
'return "done"\_s*' ..
|
||||||
|
'\d DEBUG line 2\_s*' ..
|
||||||
|
'\d PUSHS "done"\_s*' ..
|
||||||
|
'\d RETURN\_s*',
|
||||||
|
res)
|
||||||
|
enddef
|
||||||
|
|
||||||
def s:EchoMessages()
|
def s:EchoMessages()
|
||||||
echohl ErrorMsg | echom v:exception | echohl NONE
|
echohl ErrorMsg | echom v:exception | echohl NONE
|
||||||
enddef
|
enddef
|
||||||
|
@@ -4395,7 +4395,7 @@ ex_defcompile(exarg_T *eap UNUSED)
|
|||||||
&& ufunc->uf_def_status == UF_TO_BE_COMPILED
|
&& ufunc->uf_def_status == UF_TO_BE_COMPILED
|
||||||
&& (ufunc->uf_flags & FC_DEAD) == 0)
|
&& (ufunc->uf_flags & FC_DEAD) == 0)
|
||||||
{
|
{
|
||||||
(void)compile_def_function(ufunc, FALSE, FALSE, NULL);
|
(void)compile_def_function(ufunc, FALSE, CT_NONE, NULL);
|
||||||
|
|
||||||
if (func_hashtab.ht_changed != changed)
|
if (func_hashtab.ht_changed != changed)
|
||||||
{
|
{
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2985,
|
||||||
/**/
|
/**/
|
||||||
2984,
|
2984,
|
||||||
/**/
|
/**/
|
||||||
|
11
src/vim.h
11
src/vim.h
@@ -1794,10 +1794,17 @@ typedef struct timeval proftime_T;
|
|||||||
typedef int proftime_T; // dummy for function prototypes
|
typedef int proftime_T; // dummy for function prototypes
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Type of compilation passed to compile_def_function()
|
||||||
|
typedef enum {
|
||||||
|
CT_NONE, // use df_instr
|
||||||
|
CT_PROFILE, // use df_instr_prof
|
||||||
|
CT_DEBUG // use df_instr_debug, overrules CT_PROFILE
|
||||||
|
} compiletype_T;
|
||||||
|
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
# define PROFILING(ufunc) (do_profiling == PROF_YES && (ufunc)->uf_profiling)
|
# define COMPILE_TYPE(ufunc) (debug_break_level > 0 ? CT_DEBUG : do_profiling == PROF_YES && (ufunc)->uf_profiling ? CT_PROFILE : CT_NONE)
|
||||||
#else
|
#else
|
||||||
# define PROFILING(ufunc) FALSE
|
# define COMPILE_TYPE(ufunc) debug_break_level > 0 ? CT_DEBUG : CT_NONE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -168,6 +168,8 @@ typedef enum {
|
|||||||
ISN_PROF_START, // start a line for profiling
|
ISN_PROF_START, // start a line for profiling
|
||||||
ISN_PROF_END, // end a line for profiling
|
ISN_PROF_END, // end a line for profiling
|
||||||
|
|
||||||
|
ISN_DEBUG, // check for debug breakpoint
|
||||||
|
|
||||||
ISN_UNPACK, // unpack list into items, uses isn_arg.unpack
|
ISN_UNPACK, // unpack list into items, uses isn_arg.unpack
|
||||||
ISN_SHUFFLE, // move item on stack up or down
|
ISN_SHUFFLE, // move item on stack up or down
|
||||||
ISN_DROP, // pop stack and discard value
|
ISN_DROP, // pop stack and discard value
|
||||||
@@ -453,6 +455,8 @@ struct dfunc_S {
|
|||||||
isn_T *df_instr_prof; // like "df_instr" with profiling
|
isn_T *df_instr_prof; // like "df_instr" with profiling
|
||||||
int df_instr_prof_count; // size of "df_instr_prof"
|
int df_instr_prof_count; // size of "df_instr_prof"
|
||||||
#endif
|
#endif
|
||||||
|
isn_T *df_instr_debug; // like "df_instr" with debugging
|
||||||
|
int df_instr_debug_count; // size of "df_instr_debug"
|
||||||
|
|
||||||
int df_varcount; // number of local variables
|
int df_varcount; // number of local variables
|
||||||
int df_has_closure; // one if a closure was created
|
int df_has_closure; // one if a closure was created
|
||||||
|
@@ -174,7 +174,7 @@ struct cctx_S {
|
|||||||
char_u *ctx_line_start; // start of current line or NULL
|
char_u *ctx_line_start; // start of current line or NULL
|
||||||
garray_T ctx_instr; // generated instructions
|
garray_T ctx_instr; // generated instructions
|
||||||
|
|
||||||
int ctx_profiling; // when TRUE generate ISN_PROF_START
|
compiletype_T ctx_compile_type;
|
||||||
|
|
||||||
garray_T ctx_locals; // currently visible local variables
|
garray_T ctx_locals; // currently visible local variables
|
||||||
int ctx_locals_count; // total number of local variables
|
int ctx_locals_count; // total number of local variables
|
||||||
@@ -1857,7 +1857,7 @@ generate_BLOBAPPEND(cctx_T *cctx)
|
|||||||
* "profile" indicates profiling is to be done.
|
* "profile" indicates profiling is to be done.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
func_needs_compiling(ufunc_T *ufunc, int profile UNUSED)
|
func_needs_compiling(ufunc_T *ufunc, compiletype_T compile_type)
|
||||||
{
|
{
|
||||||
switch (ufunc->uf_def_status)
|
switch (ufunc->uf_def_status)
|
||||||
{
|
{
|
||||||
@@ -1866,15 +1866,18 @@ func_needs_compiling(ufunc_T *ufunc, int profile UNUSED)
|
|||||||
|
|
||||||
case UF_COMPILED:
|
case UF_COMPILED:
|
||||||
{
|
{
|
||||||
#ifdef FEAT_PROFILE
|
|
||||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||||
+ ufunc->uf_dfunc_idx;
|
+ ufunc->uf_dfunc_idx;
|
||||||
|
|
||||||
return profile ? dfunc->df_instr_prof == NULL
|
switch (compile_type)
|
||||||
: dfunc->df_instr == NULL;
|
{
|
||||||
#else
|
case CT_NONE:
|
||||||
break;
|
return dfunc->df_instr == NULL;
|
||||||
#endif
|
case CT_PROFILE:
|
||||||
|
return dfunc->df_instr_prof == NULL;
|
||||||
|
case CT_DEBUG:
|
||||||
|
return dfunc->df_instr_debug == NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case UF_NOT_COMPILED:
|
case UF_NOT_COMPILED:
|
||||||
@@ -1945,9 +1948,9 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (func_needs_compiling(ufunc, PROFILING(ufunc))
|
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
|
||||||
&& compile_def_function(ufunc, ufunc->uf_ret_type == NULL,
|
&& compile_def_function(ufunc, ufunc->uf_ret_type == NULL,
|
||||||
PROFILING(ufunc), NULL) == FAIL)
|
COMPILE_TYPE(ufunc), NULL) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
if (ufunc->uf_def_status == UF_COMPILE_ERROR)
|
if (ufunc->uf_def_status == UF_COMPILE_ERROR)
|
||||||
@@ -2313,14 +2316,28 @@ current_instr_idx(cctx_T *cctx)
|
|||||||
garray_T *instr = &cctx->ctx_instr;
|
garray_T *instr = &cctx->ctx_instr;
|
||||||
int idx = instr->ga_len;
|
int idx = instr->ga_len;
|
||||||
|
|
||||||
if (cctx->ctx_has_cmdmod && ((isn_T *)instr->ga_data)[idx - 1]
|
while (idx > 0)
|
||||||
|
{
|
||||||
|
if (cctx->ctx_has_cmdmod && ((isn_T *)instr->ga_data)[idx - 1]
|
||||||
.isn_type == ISN_CMDMOD)
|
.isn_type == ISN_CMDMOD)
|
||||||
--idx;
|
{
|
||||||
|
--idx;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[idx - 1]
|
if (((isn_T *)instr->ga_data)[idx - 1].isn_type == ISN_PROF_START)
|
||||||
.isn_type == ISN_PROF_START)
|
{
|
||||||
--idx;
|
--idx;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (((isn_T *)instr->ga_data)[idx - 1].isn_type == ISN_DEBUG)
|
||||||
|
{
|
||||||
|
--idx;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2328,7 +2345,7 @@ current_instr_idx(cctx_T *cctx)
|
|||||||
static void
|
static void
|
||||||
may_generate_prof_end(cctx_T *cctx, int prof_lnum)
|
may_generate_prof_end(cctx_T *cctx, int prof_lnum)
|
||||||
{
|
{
|
||||||
if (cctx->ctx_profiling && prof_lnum >= 0)
|
if (cctx->ctx_compile_type == CT_PROFILE && prof_lnum >= 0)
|
||||||
generate_instr(cctx, ISN_PROF_END);
|
generate_instr(cctx, ISN_PROF_END);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2972,8 +2989,8 @@ generate_funcref(cctx_T *cctx, char_u *name)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
// Need to compile any default values to get the argument types.
|
// Need to compile any default values to get the argument types.
|
||||||
if (func_needs_compiling(ufunc, PROFILING(ufunc))
|
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
|
||||||
&& compile_def_function(ufunc, TRUE, PROFILING(ufunc), NULL)
|
&& compile_def_function(ufunc, TRUE, COMPILE_TYPE(ufunc), NULL)
|
||||||
== FAIL)
|
== FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type);
|
return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type);
|
||||||
@@ -3570,7 +3587,7 @@ compile_lambda(char_u **arg, cctx_T *cctx)
|
|||||||
// compile_return().
|
// compile_return().
|
||||||
if (ufunc->uf_ret_type->tt_type == VAR_VOID)
|
if (ufunc->uf_ret_type->tt_type == VAR_VOID)
|
||||||
ufunc->uf_ret_type = &t_unknown;
|
ufunc->uf_ret_type = &t_unknown;
|
||||||
compile_def_function(ufunc, FALSE, PROFILING(ufunc), cctx);
|
compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), cctx);
|
||||||
|
|
||||||
// evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
|
// evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
|
||||||
// points into it. Point to the original line to avoid a dangling pointer.
|
// points into it. Point to the original line to avoid a dangling pointer.
|
||||||
@@ -5566,8 +5583,8 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func_needs_compiling(ufunc, PROFILING(ufunc))
|
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
|
||||||
&& compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx)
|
&& compile_def_function(ufunc, TRUE, COMPILE_TYPE(ufunc), cctx)
|
||||||
== FAIL)
|
== FAIL)
|
||||||
{
|
{
|
||||||
func_ptr_unref(ufunc);
|
func_ptr_unref(ufunc);
|
||||||
@@ -7376,7 +7393,7 @@ compile_if(char_u *arg, cctx_T *cctx)
|
|||||||
scope->se_u.se_if.is_if_label = -1;
|
scope->se_u.se_if.is_if_label = -1;
|
||||||
|
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES
|
if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
|
||||||
&& skip_save != SKIP_YES)
|
&& skip_save != SKIP_YES)
|
||||||
{
|
{
|
||||||
// generated a profile start, need to generate a profile end, since it
|
// generated a profile start, need to generate a profile end, since it
|
||||||
@@ -7457,13 +7474,19 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
|||||||
{
|
{
|
||||||
cctx->ctx_skip = SKIP_UNKNOWN;
|
cctx->ctx_skip = SKIP_UNKNOWN;
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx->ctx_profiling)
|
if (cctx->ctx_compile_type == CT_PROFILE)
|
||||||
{
|
{
|
||||||
// the previous block was skipped, need to profile this line
|
// the previous block was skipped, need to profile this line
|
||||||
generate_instr(cctx, ISN_PROF_START);
|
generate_instr(cctx, ISN_PROF_START);
|
||||||
instr_count = instr->ga_len;
|
instr_count = instr->ga_len;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (cctx->ctx_compile_type == CT_DEBUG)
|
||||||
|
{
|
||||||
|
// the previous block was skipped, may want to debug this line
|
||||||
|
generate_instr(cctx, ISN_DEBUG);
|
||||||
|
instr_count = instr->ga_len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (compile_expr1(&p, cctx, &ppconst) == FAIL)
|
if (compile_expr1(&p, cctx, &ppconst) == FAIL)
|
||||||
{
|
{
|
||||||
@@ -7531,12 +7554,13 @@ compile_else(char_u *arg, cctx_T *cctx)
|
|||||||
scope->se_u.se_if.is_seen_else = TRUE;
|
scope->se_u.se_if.is_seen_else = TRUE;
|
||||||
|
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx->ctx_profiling)
|
if (cctx->ctx_compile_type == CT_PROFILE)
|
||||||
{
|
{
|
||||||
if (cctx->ctx_skip == SKIP_NOT
|
if (cctx->ctx_skip == SKIP_NOT
|
||||||
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
||||||
.isn_type == ISN_PROF_START)
|
.isn_type == ISN_PROF_START)
|
||||||
// the previous block was executed, do not count "else" for profiling
|
// the previous block was executed, do not count "else" for
|
||||||
|
// profiling
|
||||||
--instr->ga_len;
|
--instr->ga_len;
|
||||||
if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
|
if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
|
||||||
{
|
{
|
||||||
@@ -7612,7 +7636,7 @@ compile_endif(char_u *arg, cctx_T *cctx)
|
|||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
// even when skipping we count the endif as executed, unless the block it's
|
// even when skipping we count the endif as executed, unless the block it's
|
||||||
// in is skipped
|
// in is skipped
|
||||||
if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES
|
if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
|
||||||
&& scope->se_skip_save != SKIP_YES)
|
&& scope->se_skip_save != SKIP_YES)
|
||||||
{
|
{
|
||||||
cctx->ctx_skip = SKIP_NOT;
|
cctx->ctx_skip = SKIP_NOT;
|
||||||
@@ -8183,7 +8207,8 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
|
|||||||
{
|
{
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
// the profile-start should be after the jump
|
// the profile-start should be after the jump
|
||||||
if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
if (cctx->ctx_compile_type == CT_PROFILE
|
||||||
|
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
||||||
.isn_type == ISN_PROF_START)
|
.isn_type == ISN_PROF_START)
|
||||||
--instr->ga_len;
|
--instr->ga_len;
|
||||||
#endif
|
#endif
|
||||||
@@ -8203,7 +8228,7 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
|
|||||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||||
}
|
}
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx->ctx_profiling)
|
if (cctx->ctx_compile_type == CT_PROFILE)
|
||||||
{
|
{
|
||||||
// a "throw" that jumps here needs to be counted
|
// a "throw" that jumps here needs to be counted
|
||||||
generate_instr(cctx, ISN_PROF_END);
|
generate_instr(cctx, ISN_PROF_END);
|
||||||
@@ -8211,6 +8236,8 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
|
|||||||
generate_instr(cctx, ISN_PROF_START);
|
generate_instr(cctx, ISN_PROF_START);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (cctx->ctx_compile_type == CT_DEBUG)
|
||||||
|
generate_instr(cctx, ISN_DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
p = skipwhite(arg);
|
p = skipwhite(arg);
|
||||||
@@ -8298,7 +8325,8 @@ compile_finally(char_u *arg, cctx_T *cctx)
|
|||||||
|
|
||||||
this_instr = instr->ga_len;
|
this_instr = instr->ga_len;
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
if (cctx->ctx_compile_type == CT_PROFILE
|
||||||
|
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
||||||
.isn_type == ISN_PROF_START)
|
.isn_type == ISN_PROF_START)
|
||||||
// jump to the profile start of the "finally"
|
// jump to the profile start of the "finally"
|
||||||
--this_instr;
|
--this_instr;
|
||||||
@@ -8367,7 +8395,8 @@ compile_endtry(char_u *arg, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
if (cctx->ctx_compile_type == CT_PROFILE
|
||||||
|
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
||||||
.isn_type == ISN_PROF_START)
|
.isn_type == ISN_PROF_START)
|
||||||
// move the profile start after "endtry" so that it's not counted when
|
// move the profile start after "endtry" so that it's not counted when
|
||||||
// the exception is rethrown.
|
// the exception is rethrown.
|
||||||
@@ -8399,7 +8428,7 @@ compile_endtry(char_u *arg, cctx_T *cctx)
|
|||||||
&& generate_instr(cctx, ISN_ENDTRY) == NULL)
|
&& generate_instr(cctx, ISN_ENDTRY) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx->ctx_profiling)
|
if (cctx->ctx_compile_type == CT_PROFILE)
|
||||||
generate_instr(cctx, ISN_PROF_START);
|
generate_instr(cctx, ISN_PROF_START);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -8965,10 +8994,10 @@ add_def_function(ufunc_T *ufunc)
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
compile_def_function(
|
compile_def_function(
|
||||||
ufunc_T *ufunc,
|
ufunc_T *ufunc,
|
||||||
int check_return_type,
|
int check_return_type,
|
||||||
int profiling UNUSED,
|
compiletype_T compile_type,
|
||||||
cctx_T *outer_cctx)
|
cctx_T *outer_cctx)
|
||||||
{
|
{
|
||||||
char_u *line = NULL;
|
char_u *line = NULL;
|
||||||
char_u *line_to_free = NULL;
|
char_u *line_to_free = NULL;
|
||||||
@@ -8987,6 +9016,7 @@ compile_def_function(
|
|||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
int prof_lnum = -1;
|
int prof_lnum = -1;
|
||||||
#endif
|
#endif
|
||||||
|
int debug_lnum = -1;
|
||||||
|
|
||||||
// When using a function that was compiled before: Free old instructions.
|
// When using a function that was compiled before: Free old instructions.
|
||||||
// The index is reused. Otherwise add a new entry in "def_functions".
|
// The index is reused. Otherwise add a new entry in "def_functions".
|
||||||
@@ -9007,9 +9037,7 @@ compile_def_function(
|
|||||||
|
|
||||||
CLEAR_FIELD(cctx);
|
CLEAR_FIELD(cctx);
|
||||||
|
|
||||||
#ifdef FEAT_PROFILE
|
cctx.ctx_compile_type = compile_type;
|
||||||
cctx.ctx_profiling = profiling;
|
|
||||||
#endif
|
|
||||||
cctx.ctx_ufunc = ufunc;
|
cctx.ctx_ufunc = ufunc;
|
||||||
cctx.ctx_lnum = -1;
|
cctx.ctx_lnum = -1;
|
||||||
cctx.ctx_outer = outer_cctx;
|
cctx.ctx_outer = outer_cctx;
|
||||||
@@ -9159,8 +9187,8 @@ compile_def_function(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum &&
|
if (cctx.ctx_compile_type == CT_PROFILE && cctx.ctx_lnum != prof_lnum
|
||||||
cctx.ctx_skip != SKIP_YES)
|
&& cctx.ctx_skip != SKIP_YES)
|
||||||
{
|
{
|
||||||
may_generate_prof_end(&cctx, prof_lnum);
|
may_generate_prof_end(&cctx, prof_lnum);
|
||||||
|
|
||||||
@@ -9168,6 +9196,12 @@ compile_def_function(
|
|||||||
generate_instr(&cctx, ISN_PROF_START);
|
generate_instr(&cctx, ISN_PROF_START);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (cctx.ctx_compile_type == CT_DEBUG && cctx.ctx_lnum != debug_lnum
|
||||||
|
&& cctx.ctx_skip != SKIP_YES)
|
||||||
|
{
|
||||||
|
debug_lnum = cctx.ctx_lnum;
|
||||||
|
generate_instr(&cctx, ISN_DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
// Some things can be recognized by the first character.
|
// Some things can be recognized by the first character.
|
||||||
switch (*ea.cmd)
|
switch (*ea.cmd)
|
||||||
@@ -9617,13 +9651,19 @@ nextline:
|
|||||||
dfunc->df_deleted = FALSE;
|
dfunc->df_deleted = FALSE;
|
||||||
dfunc->df_script_seq = current_sctx.sc_seq;
|
dfunc->df_script_seq = current_sctx.sc_seq;
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (cctx.ctx_profiling)
|
if (cctx.ctx_compile_type == CT_PROFILE)
|
||||||
{
|
{
|
||||||
dfunc->df_instr_prof = instr->ga_data;
|
dfunc->df_instr_prof = instr->ga_data;
|
||||||
dfunc->df_instr_prof_count = instr->ga_len;
|
dfunc->df_instr_prof_count = instr->ga_len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
if (cctx.ctx_compile_type == CT_DEBUG)
|
||||||
|
{
|
||||||
|
dfunc->df_instr_debug = instr->ga_data;
|
||||||
|
dfunc->df_instr_debug_count = instr->ga_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
dfunc->df_instr = instr->ga_data;
|
dfunc->df_instr = instr->ga_data;
|
||||||
dfunc->df_instr_count = instr->ga_len;
|
dfunc->df_instr_count = instr->ga_len;
|
||||||
@@ -9919,6 +9959,7 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_COMPARESTRING:
|
case ISN_COMPARESTRING:
|
||||||
case ISN_CONCAT:
|
case ISN_CONCAT:
|
||||||
case ISN_COND2BOOL:
|
case ISN_COND2BOOL:
|
||||||
|
case ISN_DEBUG:
|
||||||
case ISN_DROP:
|
case ISN_DROP:
|
||||||
case ISN_ECHO:
|
case ISN_ECHO:
|
||||||
case ISN_ECHOERR:
|
case ISN_ECHOERR:
|
||||||
@@ -9927,6 +9968,7 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_EXECCONCAT:
|
case ISN_EXECCONCAT:
|
||||||
case ISN_EXECUTE:
|
case ISN_EXECUTE:
|
||||||
case ISN_FINALLY:
|
case ISN_FINALLY:
|
||||||
|
case ISN_FINISH:
|
||||||
case ISN_FOR:
|
case ISN_FOR:
|
||||||
case ISN_GETITEM:
|
case ISN_GETITEM:
|
||||||
case ISN_JUMP:
|
case ISN_JUMP:
|
||||||
@@ -9949,7 +9991,6 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_NEWLIST:
|
case ISN_NEWLIST:
|
||||||
case ISN_OPANY:
|
case ISN_OPANY:
|
||||||
case ISN_OPFLOAT:
|
case ISN_OPFLOAT:
|
||||||
case ISN_FINISH:
|
|
||||||
case ISN_OPNR:
|
case ISN_OPNR:
|
||||||
case ISN_PCALL:
|
case ISN_PCALL:
|
||||||
case ISN_PCALL_END:
|
case ISN_PCALL_END:
|
||||||
|
@@ -204,8 +204,8 @@ call_dfunc(
|
|||||||
// Profiling might be enabled/disabled along the way. This should not
|
// Profiling might be enabled/disabled along the way. This should not
|
||||||
// fail, since the function was compiled before and toggling profiling
|
// fail, since the function was compiled before and toggling profiling
|
||||||
// doesn't change any errors.
|
// doesn't change any errors.
|
||||||
if (func_needs_compiling(ufunc, PROFILING(ufunc))
|
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
|
||||||
&& compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL)
|
&& compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
|
||||||
== FAIL)
|
== FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
@@ -264,6 +264,7 @@ call_dfunc(
|
|||||||
// If depth of calling is getting too high, don't execute the function.
|
// If depth of calling is getting too high, don't execute the function.
|
||||||
if (funcdepth_increment() == FAIL)
|
if (funcdepth_increment() == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
++ex_nesting_level;
|
||||||
|
|
||||||
// Only make a copy of funclocal if it contains something to restore.
|
// Only make a copy of funclocal if it contains something to restore.
|
||||||
if (ectx->ec_funclocal.floc_restore_cmdmod)
|
if (ectx->ec_funclocal.floc_restore_cmdmod)
|
||||||
@@ -647,6 +648,7 @@ func_return(ectx_T *ectx)
|
|||||||
ectx->ec_stack.ga_len = top;
|
ectx->ec_stack.ga_len = top;
|
||||||
|
|
||||||
funcdepth_decrement();
|
funcdepth_decrement();
|
||||||
|
--ex_nesting_level;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -737,13 +739,15 @@ call_ufunc(
|
|||||||
int idx;
|
int idx;
|
||||||
int did_emsg_before = did_emsg;
|
int did_emsg_before = did_emsg;
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
int profiling = do_profiling == PROF_YES && ufunc->uf_profiling;
|
compiletype_T compile_type = do_profiling == PROF_YES
|
||||||
|
&& ufunc->uf_profiling ? CT_PROFILE : CT_NONE;
|
||||||
#else
|
#else
|
||||||
# define profiling FALSE
|
# define compile_type CT_NONE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (func_needs_compiling(ufunc, profiling)
|
if (func_needs_compiling(ufunc, compile_type)
|
||||||
&& compile_def_function(ufunc, FALSE, profiling, NULL) == FAIL)
|
&& compile_def_function(ufunc, FALSE, compile_type, NULL)
|
||||||
|
== FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
if (ufunc->uf_def_status == UF_COMPILED)
|
if (ufunc->uf_def_status == UF_COMPILED)
|
||||||
{
|
{
|
||||||
@@ -4099,6 +4103,22 @@ exec_instructions(ectx_T *ectx)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ISN_DEBUG:
|
||||||
|
if (ex_nesting_level <= debug_break_level)
|
||||||
|
{
|
||||||
|
char_u *line;
|
||||||
|
ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data)
|
||||||
|
+ ectx->ec_dfunc_idx)->df_ufunc;
|
||||||
|
|
||||||
|
SOURCING_LNUM = iptr->isn_lnum;
|
||||||
|
line = ((char_u **)ufunc->uf_lines.ga_data)[
|
||||||
|
iptr->isn_lnum - 1];
|
||||||
|
if (line == NULL)
|
||||||
|
line = (char_u *)"[empty]";
|
||||||
|
do_debug(line);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ISN_SHUFFLE:
|
case ISN_SHUFFLE:
|
||||||
{
|
{
|
||||||
typval_T tmp_tv;
|
typval_T tmp_tv;
|
||||||
@@ -4258,6 +4278,7 @@ call_def_function(
|
|||||||
int save_emsg_silent_def = emsg_silent_def;
|
int save_emsg_silent_def = emsg_silent_def;
|
||||||
int save_did_emsg_def = did_emsg_def;
|
int save_did_emsg_def = did_emsg_def;
|
||||||
int orig_funcdepth;
|
int orig_funcdepth;
|
||||||
|
int orig_nesting_level = ex_nesting_level;
|
||||||
|
|
||||||
// Get pointer to item in the stack.
|
// Get pointer to item in the stack.
|
||||||
#undef STACK_TV
|
#undef STACK_TV
|
||||||
@@ -4273,8 +4294,8 @@ call_def_function(
|
|||||||
|
|
||||||
if (ufunc->uf_def_status == UF_NOT_COMPILED
|
if (ufunc->uf_def_status == UF_NOT_COMPILED
|
||||||
|| ufunc->uf_def_status == UF_COMPILE_ERROR
|
|| ufunc->uf_def_status == UF_COMPILE_ERROR
|
||||||
|| (func_needs_compiling(ufunc, PROFILING(ufunc))
|
|| (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
|
||||||
&& compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL)
|
&& compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
|
||||||
== FAIL))
|
== FAIL))
|
||||||
{
|
{
|
||||||
if (did_emsg_cumul + did_emsg == did_emsg_before)
|
if (did_emsg_cumul + did_emsg == did_emsg_before)
|
||||||
@@ -4310,6 +4331,7 @@ call_def_function(
|
|||||||
ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
|
ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
|
||||||
ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10);
|
ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10);
|
||||||
ectx.ec_did_emsg_before = did_emsg_before;
|
ectx.ec_did_emsg_before = did_emsg_before;
|
||||||
|
++ex_nesting_level;
|
||||||
|
|
||||||
idx = argc - ufunc->uf_args.ga_len;
|
idx = argc - ufunc->uf_args.ga_len;
|
||||||
if (idx > 0 && ufunc->uf_va_name == NULL)
|
if (idx > 0 && ufunc->uf_va_name == NULL)
|
||||||
@@ -4553,6 +4575,7 @@ failed_early:
|
|||||||
// Free all local variables, but not arguments.
|
// Free all local variables, but not arguments.
|
||||||
for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
|
for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
|
||||||
clear_tv(STACK_TV(idx));
|
clear_tv(STACK_TV(idx));
|
||||||
|
ex_nesting_level = orig_nesting_level;
|
||||||
|
|
||||||
vim_free(ectx.ec_stack.ga_data);
|
vim_free(ectx.ec_stack.ga_data);
|
||||||
vim_free(ectx.ec_trystack.ga_data);
|
vim_free(ectx.ec_trystack.ga_data);
|
||||||
@@ -5315,13 +5338,18 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
|||||||
case ISN_CMDMOD_REV: smsg("%s%4d CMDMOD_REV", pfx, current); break;
|
case ISN_CMDMOD_REV: smsg("%s%4d CMDMOD_REV", pfx, current); break;
|
||||||
|
|
||||||
case ISN_PROF_START:
|
case ISN_PROF_START:
|
||||||
smsg("%s%4d PROFILE START line %d", pfx, current, iptr->isn_lnum);
|
smsg("%s%4d PROFILE START line %d", pfx, current,
|
||||||
|
iptr->isn_lnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ISN_PROF_END:
|
case ISN_PROF_END:
|
||||||
smsg("%s%4d PROFILE END", pfx, current);
|
smsg("%s%4d PROFILE END", pfx, current);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ISN_DEBUG:
|
||||||
|
smsg("%s%4d DEBUG line %d", pfx, current, iptr->isn_lnum);
|
||||||
|
break;
|
||||||
|
|
||||||
case ISN_UNPACK: smsg("%s%4d UNPACK %d%s", pfx, current,
|
case ISN_UNPACK: smsg("%s%4d UNPACK %d%s", pfx, current,
|
||||||
iptr->isn_arg.unpack.unp_count,
|
iptr->isn_arg.unpack.unp_count,
|
||||||
iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : "");
|
iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : "");
|
||||||
@@ -5358,6 +5386,18 @@ ex_disassemble(exarg_T *eap)
|
|||||||
isn_T *instr;
|
isn_T *instr;
|
||||||
int instr_count;
|
int instr_count;
|
||||||
int is_global = FALSE;
|
int is_global = FALSE;
|
||||||
|
compiletype_T compile_type = CT_NONE;
|
||||||
|
|
||||||
|
if (STRNCMP(arg, "profile", 7) == 0)
|
||||||
|
{
|
||||||
|
compile_type = CT_PROFILE;
|
||||||
|
arg = skipwhite(arg + 7);
|
||||||
|
}
|
||||||
|
else if (STRNCMP(arg, "debug", 5) == 0)
|
||||||
|
{
|
||||||
|
compile_type = CT_DEBUG;
|
||||||
|
arg = skipwhite(arg + 5);
|
||||||
|
}
|
||||||
|
|
||||||
if (STRNCMP(arg, "<lambda>", 8) == 0)
|
if (STRNCMP(arg, "<lambda>", 8) == 0)
|
||||||
{
|
{
|
||||||
@@ -5389,8 +5429,8 @@ ex_disassemble(exarg_T *eap)
|
|||||||
semsg(_(e_cannot_find_function_str), eap->arg);
|
semsg(_(e_cannot_find_function_str), eap->arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (func_needs_compiling(ufunc, eap->forceit)
|
if (func_needs_compiling(ufunc, compile_type)
|
||||||
&& compile_def_function(ufunc, FALSE, eap->forceit, NULL) == FAIL)
|
&& compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
|
||||||
return;
|
return;
|
||||||
if (ufunc->uf_def_status != UF_COMPILED)
|
if (ufunc->uf_def_status != UF_COMPILED)
|
||||||
{
|
{
|
||||||
@@ -5403,14 +5443,24 @@ ex_disassemble(exarg_T *eap)
|
|||||||
msg((char *)ufunc->uf_name);
|
msg((char *)ufunc->uf_name);
|
||||||
|
|
||||||
dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
|
dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
|
||||||
|
switch (compile_type)
|
||||||
|
{
|
||||||
|
case CT_PROFILE:
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
instr = eap->forceit ? dfunc->df_instr_prof : dfunc->df_instr;
|
instr = dfunc->df_instr_prof;
|
||||||
instr_count = eap->forceit ? dfunc->df_instr_prof_count
|
instr_count = dfunc->df_instr_prof_count;
|
||||||
: dfunc->df_instr_count;
|
break;
|
||||||
#else
|
|
||||||
instr = dfunc->df_instr;
|
|
||||||
instr_count = dfunc->df_instr_count;
|
|
||||||
#endif
|
#endif
|
||||||
|
// FALLTHROUGH
|
||||||
|
case CT_NONE:
|
||||||
|
instr = dfunc->df_instr;
|
||||||
|
instr_count = dfunc->df_instr_count;
|
||||||
|
break;
|
||||||
|
case CT_DEBUG:
|
||||||
|
instr = dfunc->df_instr_debug;
|
||||||
|
instr_count = dfunc->df_instr_debug_count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
list_instructions("", instr, instr_count, ufunc);
|
list_instructions("", instr, instr_count, ufunc);
|
||||||
}
|
}
|
||||||
|
@@ -349,7 +349,7 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int do_member)
|
|||||||
// May need to get the argument types from default values by
|
// May need to get the argument types from default values by
|
||||||
// compiling the function.
|
// compiling the function.
|
||||||
if (ufunc->uf_def_status == UF_TO_BE_COMPILED
|
if (ufunc->uf_def_status == UF_TO_BE_COMPILED
|
||||||
&& compile_def_function(ufunc, TRUE, FALSE, NULL)
|
&& compile_def_function(ufunc, TRUE, CT_NONE, NULL)
|
||||||
== FAIL)
|
== FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (ufunc->uf_func_type == NULL)
|
if (ufunc->uf_func_type == NULL)
|
||||||
|
Reference in New Issue
Block a user