changeset 33435:066a27297ba3 bytecode-interpreter tip

maint: Merge default to bytecode-interpreter
author Arun Giridhar <arungiridhar@gmail.com>
date Fri, 19 Apr 2024 12:57:20 -0400
parents e4e172cb662c (current diff) 69eb4c27d8c8 (diff)
children
files etc/NEWS.9.md libinterp/parse-tree/pt-eval.cc
diffstat 6 files changed, 73 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS.9.md	Thu Apr 18 13:15:27 2024 -0400
+++ b/etc/NEWS.9.md	Fri Apr 19 12:57:20 2024 -0400
@@ -17,6 +17,8 @@
 - Correctly scale figure position on screen with DPI scaling (high DPI).
 - `profile ('on')` now clears any existing profile data as the documentation
   states (bug #65595).
+- Fix segmentation fault when trying to set breakpoint in non-existent method
+  of `classdef` class (bug #65610).
 
 ### GUI
 
--- a/libinterp/corefcn/debug.cc	Thu Apr 18 13:15:27 2024 -0400
+++ b/libinterp/corefcn/debug.cc	Fri Apr 19 12:57:20 2024 -0400
@@ -185,7 +185,7 @@
                                      class_name, lines, condition);
 
       if (lines.size () == 0)
-        lines.insert (1);
+        lines.insert (-1);
 
       if (symbol_name != "")
         {
--- a/libinterp/parse-tree/bp-table.cc	Thu Apr 18 13:15:27 2024 -0400
+++ b/libinterp/parse-tree/bp-table.cc	Fri Apr 19 12:57:20 2024 -0400
@@ -797,6 +797,9 @@
     if (is_function ())
       return find_fcn_by_line (m_fcn, line);
 
+    if (line < 0)
+      return nullptr;
+
     return m_cls.get_method (line).user_code_value (true);
   }
 
@@ -834,7 +837,7 @@
   {
       if (m_methods_cache.empty ())
         {
-          // Not the most effecient, but reuses code:
+          // Not the most efficient, but reuses code:
           const std::map<std::string, cdef_method>& map
             = m_cls.get_method_map (false, true);
           for (auto iter = map.cbegin (); iter != map.cend (); ++iter)
@@ -872,6 +875,10 @@
     {
       octave_user_code *dbg_fcn = user_code (lineno);
 
+      if (! dbg_fcn)
+        error ("add_breakpoints_in_function: unable to find function '%s'\n",
+               fcn_ident.c_str ());
+
       // We've found the right (sub)function.  Now insert the breakpoint.
       bp_lines line_info;
       line_info.insert (lineno);
@@ -879,14 +886,13 @@
       bp_lines ret_one;
 
       std::string ident = fcn_ident;
-      if (! user_code.is_function () && fcn_ident[0] != '@' && dbg_fcn)
+      if (! user_code.is_function () && fcn_ident[0] != '@')
         {
           // identifier of the form @class_name/method_name
           ident = "@" + fcn_ident + "/" + dbg_fcn->name ();
         }
 
-      if (dbg_fcn && add_breakpoint_1 (dbg_fcn, ident, line_info,
-                                       condition, ret_one))
+      if (add_breakpoint_1 (dbg_fcn, ident, line_info, condition, ret_one))
         {
           if (! ret_one.empty ())
             {
--- a/libinterp/parse-tree/pt-eval.cc	Thu Apr 18 13:15:27 2024 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Fri Apr 19 12:57:20 2024 -0400
@@ -3063,7 +3063,13 @@
 
           cdef_class cls = cdm.find_class (dispatch_type, false);
           if (cls.ok () && cls.get_name () == dispatch_type)
-            fcn = cls.find_method (method).get_function ();
+            {
+              cdef_method meth = cls.find_method (method);
+              if (meth.ok () && meth.get_name () == method)
+                fcn = meth.get_function ();
+              else
+                return nullptr;
+            }
 
           // If there is no classdef method, then try legacy classes.
           if (fcn.is_undefined ())
--- a/scripts/profiler/profile.m	Thu Apr 18 13:15:27 2024 -0400
+++ b/scripts/profiler/profile.m	Fri Apr 19 12:57:20 2024 -0400
@@ -41,7 +41,7 @@
 ## with @code{T = profile ("info")}.
 ##
 ## @item profile clear
-## Clear all collected profiler data.
+## Clear all collected profiler data and stop profiling.
 ##
 ## @item profile resume
 ## Restart profiling without clearing the old data.  All newly collected
@@ -84,18 +84,16 @@
       __profiler_enable__ (false);
 
     case "clear"
+      if (__profiler_enable__ ())
+        __profiler_enable__ (false);
+      endif
       __profiler_reset__ ();
 
     case "resume"
       __profiler_enable__ (true);
 
     case "status"
-      enabled = __profiler_enable__ ();
-      if (enabled)
-        enabled = "on";
-      else
-        enabled = "off";
-      endif
+      enabled = ifelse (__profiler_enable__ (), 'on', 'off');
       retval = struct ("ProfilerStatus", enabled);
 
     case "info"
@@ -156,5 +154,4 @@
 
 ## Test input validation
 %!error <Invalid call> profile ()
-%!error profile ("on", 2)
 %!error profile ("INVALID_OPTION")
--- a/test/classdef-debug/test-classdef-breakpoints.tst	Thu Apr 18 13:15:27 2024 -0400
+++ b/test/classdef-debug/test-classdef-breakpoints.tst	Fri Apr 19 12:57:20 2024 -0400
@@ -1,4 +1,5 @@
-##  Test script for setting breakpoints in classdefs using line numbers.
+##  Test script for setting breakpoints in classdefs
+##  using line numbers or method names.
 
 %!function assert_dbstatus (bp0)
 %!  dbs = dbstatus ();
@@ -10,6 +11,7 @@
 %!  endif
 %!endfunction
 
+## Set breakpoints by line numbers
 %!test <*46451>
 %! if (isguirunning ())
 %!   orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file",
@@ -33,6 +35,50 @@
 %!   endif
 %! end_unwind_protect
 
+## Set breakpoints by method name
+%!test
+%! if (isguirunning ())
+%!   orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file",
+%!                                                     "false");
+%! endif
+%! unwind_protect
+%!   ## Add breakpoint in constructor
+%!   dbstop @classdef_breakpoints/classdef_breakpoints;
+%!   assert_dbstatus ([7]);
+%!
+%!   ## Add breakpoints in methods.
+%!   dbstop @classdef_breakpoints/foo;
+%!   dbstop @classdef_breakpoints/bar;
+%!   assert_dbstatus ([7, 10, 13]);
+%!
+%!   ## Remove breakpoint from one method.
+%!   dbclear @classdef_breakpoints/foo;
+%!   assert_dbstatus ([7, 13]);
+%!
+%!   ## Clear all breakpoints, none should be left.
+%!   dbclear classdef_breakpoints;
+%!   assert_dbstatus ([]);
+%! unwind_protect_cleanup
+%!   if (isguirunning ())
+%!     __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg);
+%!   endif
+%! end_unwind_protect
+
+## Try to add breakpoint in non-existent method
+%!test <65610*>
+%! if (isguirunning ())
+%!   orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file",
+%!                                                     "false");
+%! endif
+%! unwind_protect
+%!   fail ("dbstop @classdef_breakpoints/baz;", "unable to find function");
+%! unwind_protect_cleanup
+%!   dbclear classdef_breakpoints;
+%!   if (isguirunning ())
+%!     __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg);
+%!   endif
+%! end_unwind_protect
+
 %!test <46451>
 %! if (isguirunning ())
 %!   orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file",
@@ -41,7 +87,7 @@
 %! unwind_protect
 %!   ## Add breakpoint in local function.
 %!   dbstop classdef_breakpoints 19;
-%!   assert_dbstatus ([7, 13, 20]);
+%!   assert_dbstatus ([20]);
 %! unwind_protect_cleanup
 %!   if (isguirunning ())
 %!     __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg);