]> granicus.if.org Git - vim/commitdiff
patch 8.2.3026: Vim9: cannot set breakpoint in compiled function v8.2.3026
authorBram Moolenaar <Bram@vim.org>
Sun, 20 Jun 2021 17:28:14 +0000 (19:28 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 20 Jun 2021 17:28:14 +0000 (19:28 +0200)
Problem:    Vim9: cannot set breakpoint in compiled function.
Solution:   Check for breakpoint when calling a function.

src/debugger.c
src/structs.h
src/testdir/test_debugger.vim
src/version.c
src/vim.h
src/vim9.h
src/vim9execute.c

index b96846310ab848aff36dcc72ed8805cd4baad840..52a04907ef9c96c0c279e7acfe6d95969942b0a2 100644 (file)
@@ -606,7 +606,7 @@ dbg_parsearg(
     }
 
     if (bp->dbg_type == DBG_FUNC)
-       bp->dbg_name = vim_strsave(p);
+       bp->dbg_name = vim_strsave(STRNCMP(p, "g:", 2) == 0 ? p + 2 : p);
     else if (here)
        bp->dbg_name = vim_strsave(curbuf->b_ffname);
     else if (bp->dbg_type == DBG_EXPR)
index d62b10f3719047d104413d497b505773590de8ef..ae2c0b850c79eb3b356ca19ca97726e0685e83db 100644 (file)
@@ -1629,6 +1629,11 @@ typedef struct
 # endif
 
     garray_T   uf_lines;       // function lines
+
+    int                uf_debug_tick;  // when last checked for a breakpoint in this
+                               // function.
+    int                uf_has_breakpoint;  // TRUE when a breakpoint has been set in
+                                   // this function.
 # ifdef FEAT_PROFILE
     int                uf_profiling;   // TRUE when func is being profiled
     int                uf_prof_initialized;
index 411909d1c7dbbc93a06063165f73320105935638..a576a8c929c4bcedb9702656678cb20f75d54b4c 100644 (file)
@@ -932,6 +932,31 @@ func Test_Backtrace_DefFunction()
   call delete('Xtest2.vim')
 endfunc
 
+func Test_debug_DefFunction()
+  CheckCWD
+  let file =<< trim END
+    vim9script
+    def g:SomeFunc()
+      echo "here"
+      echo "and"
+      echo "there"
+    enddef
+    breakadd func 2 g:SomeFunc
+  END
+  call writefile(file, 'XtestDebug.vim')
+
+  let buf = RunVimInTerminal('-S XtestDebug.vim', {})
+
+  call RunDbgCmd(buf,':call SomeFunc()', ['line 2: echo "and"'])
+  call RunDbgCmd(buf,'next', ['line 3: echo "there"'])
+
+  call RunDbgCmd(buf, 'cont')
+
+  call StopVimInTerminal(buf)
+  call delete('Xtest1.vim')
+  call delete('Xtest2.vim')
+endfunc
+
 func Test_debug_def_function()
   CheckCWD
   let file =<< trim END
index 961238bf9b97710ef2e2bed0a7d0cb222a340465..6fe8fa4988ec35d3c41a81b87499b6efbcd3a163 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3026,
 /**/
     3025,
 /**/
index 22fe8d5fed4f0bf02429d9e323daf23535733acc..e45a1de2e09e9e088dbac9f014785717ace9edf3 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -1804,9 +1804,9 @@ typedef enum {
 
 // Keep in sync with INSTRUCTIONS().
 #ifdef FEAT_PROFILE
-# define COMPILE_TYPE(ufunc) (debug_break_level > 0 ? CT_DEBUG : do_profiling == PROF_YES && (ufunc)->uf_profiling ? CT_PROFILE : CT_NONE)
+# define COMPILE_TYPE(ufunc) (debug_break_level > 0 || ufunc->uf_has_breakpoint ? CT_DEBUG : do_profiling == PROF_YES && (ufunc)->uf_profiling ? CT_PROFILE : CT_NONE)
 #else
-# define COMPILE_TYPE(ufunc) debug_break_level > 0 ? CT_DEBUG : CT_NONE
+# define COMPILE_TYPE(ufunc) debug_break_level > 0 || ufunc->uf_has_breakpoint ? CT_DEBUG : CT_NONE
 #endif
 
 /*
index b8c713358633cd65c85a2c42ce09870ee8ca00b8..97e2132a3e2609e80bd141abbf1c24e90f2fe394 100644 (file)
@@ -498,7 +498,7 @@ extern garray_T def_functions;
 // Keep in sync with COMPILE_TYPE()
 #ifdef FEAT_PROFILE
 # define INSTRUCTIONS(dfunc) \
-       (debug_break_level > 0 \
+       (debug_break_level > 0 || dfunc->df_ufunc->uf_has_breakpoint \
            ? (dfunc)->df_instr_debug \
            : ((do_profiling == PROF_YES && (dfunc->df_ufunc)->uf_profiling) \
                ? (dfunc)->df_instr_prof \
index 218357a825b28ca8515596248632bf0c4c6838e9..8b817e4505f4d4fdd48d807abc3fe29556b90ba2 100644 (file)
@@ -147,6 +147,23 @@ exe_newlist(int count, ectx_T *ectx)
     return OK;
 }
 
+/*
+ * If debug_tick changed check if "ufunc" has a breakpoint and update
+ * "uf_has_breakpoint".
+ */
+    static void
+update_has_breakpoint(ufunc_T *ufunc)
+{
+    if (ufunc->uf_debug_tick != debug_tick)
+    {
+       linenr_T breakpoint;
+
+       ufunc->uf_debug_tick = debug_tick;
+       breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name, 0);
+       ufunc->uf_has_breakpoint = breakpoint > 0;
+    }
+}
+
 /*
  * Call compiled function "cdf_idx" from compiled code.
  * This adds a stack frame and sets the instruction pointer to the start of the
@@ -1444,6 +1461,20 @@ handle_debug(isn_T *iptr, ectx_T *ectx)
     garray_T   ga;
     int                lnum;
 
+    if (ex_nesting_level > debug_break_level)
+    {
+       linenr_T breakpoint;
+
+       if (!ufunc->uf_has_breakpoint)
+           return;
+
+       // check for the next breakpoint if needed
+       breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name,
+                                                          iptr->isn_lnum - 1);
+       if (breakpoint <= 0 || breakpoint > iptr->isn_lnum)
+           return;
+    }
+
     SOURCING_LNUM = iptr->isn_lnum;
     debug_context = ectx;
     debug_var_count = iptr->isn_arg.number;
@@ -4206,8 +4237,7 @@ exec_instructions(ectx_T *ectx)
                break;
 
            case ISN_DEBUG:
-               if (ex_nesting_level <= debug_break_level)
-                   handle_debug(iptr, ectx);
+               handle_debug(iptr, ectx);
                break;
 
            case ISN_SHUFFLE:
@@ -4383,6 +4413,9 @@ call_def_function(
 #undef STACK_TV_VAR
 #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx)
 
+    // Update uf_has_breakpoint if needed.
+    update_has_breakpoint(ufunc);
+
     if (ufunc->uf_def_status == UF_NOT_COMPILED
            || ufunc->uf_def_status == UF_COMPILE_ERROR
            || (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))