changeset 32646:9faf6bc269a7 bytecode-interpreter

Handle quit_debug_exception in bytecode interpreter (bug #65056) To allow for escaping debugging in gui properly. * pt-bytecode-vm.cc: Catch quit_debug_exception, handle in unwind * pt-bytecode-vm.h: New field 'm_debug_quit_all' * pt-bytecode.h: New 'DEBUG_QUIT' error type * pt-eval.cc: Move quit_debug_exception def to header * pt-eval.h
author Petter T. <petter.vilhelm@gmail.com>
date Fri, 22 Dec 2023 22:50:09 +0100
parents 975f6d7fc3e6
children e02dc55325c4
files libinterp/parse-tree/pt-bytecode-vm.cc libinterp/parse-tree/pt-bytecode-vm.h libinterp/parse-tree/pt-bytecode.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h
diffstat 5 files changed, 50 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-bytecode-vm.cc	Sat Dec 23 14:16:26 2023 +0100
+++ b/libinterp/parse-tree/pt-bytecode-vm.cc	Fri Dec 22 22:50:09 2023 +0100
@@ -4855,14 +4855,17 @@
     // Save current exception to the error system in handle_error ()
     error_data errdat = handle_error (et);
 
-    // Only run unwind_protect code if the exception is the interrupt or OOM exception.
+    // Run only unwind_protect code if the exception is the interrupt exception.
     // I.e. no 'throw ... catch' code.
     bool only_unwind_protect = et == error_type::INTERRUPT_EXC;
 
     while (1)
       {
-        // Find unwind entry for current value of the instruction pointer
-        unwind_entry *entry = find_unwind_entry_for_current_state (only_unwind_protect);
+        // Find unwind entry for current value of the instruction pointer, unless we are dealing
+        // with a debug quit exception in which case no unwind entry is used.
+        unwind_entry *entry = nullptr;
+        if (et != error_type::DEBUG_QUIT)
+          entry = find_unwind_entry_for_current_state (only_unwind_protect);
 
         unwind_entry_type type = unwind_entry_type::INVALID;
         if (entry)
@@ -5017,6 +5020,8 @@
     // Rethrow exceptions out of the VM
     if (et == error_type::INTERRUPT_EXC)
       throw interrupt_exception {};
+    else if (et == error_type::DEBUG_QUIT)
+      throw quit_debug_exception {errdat.m_debug_quit_all};
     else if (et == error_type::EXIT_EXCEPTION)
       throw exit_exception (errdat.m_exit_status, errdat.m_safe_to_return);
     else
@@ -6433,6 +6438,12 @@
             CATCH_EXECUTION_EXCEPTION
             CATCH_BAD_ALLOC
             CATCH_EXIT_EXCEPTION
+            catch (const quit_debug_exception &qde)
+              {
+                (*sp++).i = qde.all ();
+                (*sp++).i = static_cast<int>(error_type::DEBUG_QUIT);
+                goto unwind;
+              }
           }
       }
   }
@@ -7153,6 +7164,13 @@
 
       break;
     }
+    case error_type::DEBUG_QUIT:
+    {
+      ret.m_debug_quit_all = m_sp[-1].i;
+      m_sp--;
+
+      break;
+    }
     default:
       TODO ("Unhandeled error type");
     }
@@ -8256,8 +8274,15 @@
 
     tw.pop_stack_frame ();
     throw;
+  } catch (const quit_debug_exception &qde) {
+    if (vm.m_dbg_proper_return == false)
+      panic ("quit debug exception escaping the vm");
+
+    tw.pop_stack_frame ();
+    throw;
   }
 
+
   tw.pop_stack_frame ();
   return ret;
 }
--- a/libinterp/parse-tree/pt-bytecode-vm.h	Sat Dec 23 14:16:26 2023 +0100
+++ b/libinterp/parse-tree/pt-bytecode-vm.h	Fri Dec 22 22:50:09 2023 +0100
@@ -589,6 +589,8 @@
     // Execution exception
     int m_exit_status;
     bool m_safe_to_return;
+    // Debug quit
+    bool m_debug_quit_all;
   };
 
   error_data
--- a/libinterp/parse-tree/pt-bytecode.h	Sat Dec 23 14:16:26 2023 +0100
+++ b/libinterp/parse-tree/pt-bytecode.h	Fri Dec 22 22:50:09 2023 +0100
@@ -347,6 +347,7 @@
   RHS_UNDEF_IN_ASSIGNMENT,
   BAD_ALLOC,
   EXIT_EXCEPTION,
+  DEBUG_QUIT,
 };
 
 enum class global_type
--- a/libinterp/parse-tree/pt-eval.cc	Sat Dec 23 14:16:26 2023 +0100
+++ b/libinterp/parse-tree/pt-eval.cc	Fri Dec 22 22:50:09 2023 +0100
@@ -81,25 +81,6 @@
 
 // Normal evaluator.
 
-class quit_debug_exception
-{
-public:
-
-  quit_debug_exception (bool all = false) : m_all (all) { }
-
-  quit_debug_exception (const quit_debug_exception&) = default;
-
-  quit_debug_exception& operator = (const quit_debug_exception&) = default;
-
-  ~quit_debug_exception () = default;
-
-  bool all () const { return m_all; }
-
-private:
-
-  bool m_all;
-};
-
 class debugger
 {
 public:
--- a/libinterp/parse-tree/pt-eval.h	Sat Dec 23 14:16:26 2023 +0100
+++ b/libinterp/parse-tree/pt-eval.h	Fri Dec 22 22:50:09 2023 +0100
@@ -1063,6 +1063,25 @@
   int m_num_indices;
 };
 
+class quit_debug_exception
+{
+public:
+
+  quit_debug_exception (bool all = false) : m_all (all) { }
+
+  quit_debug_exception (const quit_debug_exception&) = default;
+
+  quit_debug_exception& operator = (const quit_debug_exception&) = default;
+
+  ~quit_debug_exception () = default;
+
+  bool all () const { return m_all; }
+
+private:
+
+  bool m_all;
+};
+
 OCTAVE_END_NAMESPACE(octave)
 
 #endif