changeset 25399:6ca2c0d76d84

store unwind protect frame for function evaluation in call_stack object * call-stack.h, call-stack.cc (call_stack::m_unwind_protect_frame): New data member. (call_stack::push): Also handle unwind_protect frame. (call_stack::curr_fcn_unwind_protect_frame): New function. * variables.cc (curr_fcn_unwind_protect_frame): Access current unwind_protect frame from call_stack object. * pt-eval.cc (tree_evaluator::maybe_push_echo_state_cleanup): Likewise. * ov-usr-fcn.h (octave_user_code::curr_unwind_protect_frame): Delete member variable and all uses. (octave_user_code::unwind_protect_frame): Delete. * ov-usr-fcn.h, ov-usr-fcn.cc (octave_user_script::call, octave_user_function::call): Push current unwind_protect frame on call_stack object instead of saving and restoring octave_user_code::curr_unwind_protect_frame.
author John W. Eaton <jwe@octave.org>
date Mon, 21 May 2018 19:32:57 -0400
parents a78e5b8d5ee7
children d423ce60f5c8
files libinterp/corefcn/call-stack.cc libinterp/corefcn/call-stack.h libinterp/corefcn/variables.cc libinterp/octave-value/ov-usr-fcn.cc libinterp/octave-value/ov-usr-fcn.h libinterp/parse-tree/pt-eval.cc
diffstat 6 files changed, 51 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/call-stack.cc	Tue May 22 22:41:12 2018 +0200
+++ b/libinterp/corefcn/call-stack.cc	Mon May 21 19:32:57 2018 -0400
@@ -92,7 +92,7 @@
   {
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
-    push (nullptr, symtab.top_scope (), 0);
+    push (nullptr, nullptr, symtab.top_scope (), 0);
   }
 
   int
@@ -214,6 +214,24 @@
     return retval;
   }
 
+  unwind_protect *
+  call_stack::curr_fcn_unwind_protect_frame (void) const
+  {
+    auto p = cs.cend ();
+
+    while (p != cs.cbegin ())
+      {
+        const stack_frame& elt = *(--p);
+
+        octave_function *f = elt.m_fcn;
+
+        if (f && f->is_user_code ())
+          return elt.m_unwind_protect_frame;
+      }
+
+    return nullptr;
+  }
+
   int
   call_stack::caller_user_code_column (void) const
   {
@@ -354,15 +372,16 @@
   }
 
   void
-  call_stack::push (octave_function *fcn)
+  call_stack::push (octave_function *fcn, unwind_protect *up_frame)
   {
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
-    push (fcn, symtab.current_scope (), symtab.current_context ());
+    push (fcn, up_frame, symtab.current_scope (), symtab.current_context ());
   }
 
   void
-  call_stack::push (octave_function *fcn, const symbol_scope& scope,
+  call_stack::push (octave_function *fcn, unwind_protect *up_frame,
+                    const symbol_scope& scope,
                     symbol_record::context_id context)
   {
     size_t prev_frame = curr_frame;
@@ -372,7 +391,7 @@
     if (curr_frame > static_cast<size_t> (m_max_stack_depth))
       error ("max_stack_depth exceeded");
 
-    cs.push_back (stack_frame (fcn, scope, context, prev_frame));
+    cs.push_back (stack_frame (fcn, up_frame, scope, context, prev_frame));
 
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
--- a/libinterp/corefcn/call-stack.h	Tue May 22 22:41:12 2018 +0200
+++ b/libinterp/corefcn/call-stack.h	Mon May 21 19:32:57 2018 -0400
@@ -40,6 +40,7 @@
 namespace octave
 {
   class interpreter;
+  class unwind_protect;
 
   class
   OCTINTERP_API
@@ -54,15 +55,20 @@
       friend class call_stack;
 
       stack_frame (octave_function *fcn = nullptr,
+                   unwind_protect *up_frame = nullptr,
                    const symbol_scope& scope = symbol_scope (),
                    symbol_record::context_id context = 0, size_t prev = 0)
-        : m_fcn (fcn), m_line (-1), m_column (-1), m_scope (scope),
+        : m_fcn (fcn), m_unwind_protect_frame (up_frame),
+          m_line (-1), m_column (-1), m_scope (scope),
           m_context (context), m_prev (prev)
       { }
 
       stack_frame (const stack_frame& elt)
-        : m_fcn (elt.m_fcn), m_line (elt.m_line), m_column (elt.m_column),
-          m_scope (elt.m_scope), m_context (elt.m_context), m_prev (elt.m_prev)
+        : m_fcn (elt.m_fcn),
+          m_unwind_protect_frame (elt.m_unwind_protect_frame),
+          m_line (elt.m_line), m_column (elt.m_column),
+          m_scope (elt.m_scope), m_context (elt.m_context),
+          m_prev (elt.m_prev)
       { }
 
       int line (void) const { return m_line; }
@@ -78,6 +84,7 @@
     private:
 
       octave_function *m_fcn;
+      unwind_protect *m_unwind_protect_frame;
       int m_line;
       int m_column;
       symbol_scope m_scope;
@@ -156,6 +163,8 @@
     // User code caller.
     octave_user_code * caller_user_code (size_t nskip = 0) const;
 
+    unwind_protect *curr_fcn_unwind_protect_frame (void) const;
+
     // Line in user code caller.
     int caller_user_code_line (void) const;
 
@@ -174,18 +183,15 @@
     // Return TRUE if all elements on the call stack are scripts.
     bool all_scripts (void) const;
 
-    void push (octave_function *fcn);
-    void push (octave_function *fcn, const symbol_scope& scope,
-               symbol_record::context_id context);
+    void push (octave_function *fcn = nullptr,
+               unwind_protect *up_frame = nullptr);
 
-    void push (void)
-    {
-      push (nullptr);
-    }
+    void push (octave_function *fcn, unwind_protect *up_frame,
+               const symbol_scope& scope, symbol_record::context_id context);
 
     void push (const symbol_scope& scope, symbol_record::context_id context)
     {
-      push (nullptr, scope, context);
+      push (nullptr, nullptr, scope, context);
     }
 
     void set_location (int l, int c)
--- a/libinterp/corefcn/variables.cc	Tue May 22 22:41:12 2018 +0200
+++ b/libinterp/corefcn/variables.cc	Mon May 21 19:32:57 2018 -0400
@@ -707,13 +707,7 @@
   octave::call_stack& cs
     = octave::__get_call_stack__ ("curr_fcn_unwind_protect_frame");
 
-  octave_user_code *curr_usr_code = cs.caller_user_code ();
-
-  octave_user_function *curr_usr_fcn
-    = (curr_usr_code && curr_usr_code->is_user_function ()
-       ? dynamic_cast<octave_user_function *> (curr_usr_code) : nullptr);
-
-  return curr_usr_fcn ? curr_usr_fcn->unwind_protect_frame () : nullptr;
+  return cs.curr_fcn_unwind_protect_frame ();
 }
 
 template <typename T>
--- a/libinterp/octave-value/ov-usr-fcn.cc	Tue May 22 22:41:12 2018 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Mon May 21 19:32:57 2018 -0400
@@ -183,13 +183,7 @@
       octave::call_stack& cs
         = octave::__get_call_stack__ ("octave_user_script::call");
 
-      cs.push (this);
-
-      // Set pointer to the current unwind_protect frame to allow
-      // certain builtins register simple cleanup in a very optimized manner.
-      // This is *not* intended as a general-purpose on-cleanup mechanism,
-      frame.protect_var (curr_unwind_protect_frame);
-      curr_unwind_protect_frame = &frame;
+      cs.push (this, &frame);
 
       frame.add_method (cs, &octave::call_stack::pop);
 
@@ -522,13 +516,7 @@
   octave::symbol_record::context_id context
     = anonymous_function ? 0 : call_depth;
 
-  cs.push (this, m_scope, context);
-
-  // Set pointer to the current unwind_protect frame to allow
-  // certain builtins register simple cleanup in a very optimized manner.
-  // This is *not* intended as a general-purpose on-cleanup mechanism,
-  frame.protect_var (curr_unwind_protect_frame);
-  curr_unwind_protect_frame = &frame;
+  cs.push (this, &frame, m_scope, context);
 
   frame.protect_var (Vtrack_line_num);
   Vtrack_line_num = true;    // update source line numbers, even if debugging
--- a/libinterp/octave-value/ov-usr-fcn.h	Tue May 22 22:41:12 2018 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.h	Mon May 21 19:32:57 2018 -0400
@@ -68,7 +68,7 @@
       t_parsed (static_cast<time_t> (0)),
       t_checked (static_cast<time_t> (0)),
       call_depth (-1), m_file_info (nullptr),
-      curr_unwind_protect_frame (nullptr), cmd_list (cmds)
+      cmd_list (cmds)
   { }
 
 public:
@@ -83,12 +83,6 @@
 
   bool is_user_code (void) const { return true; }
 
-  octave::unwind_protect *
-  unwind_protect_frame (void)
-  {
-    return curr_unwind_protect_frame;
-  }
-
   std::string get_code_line (size_t line);
 
   std::deque<std::string> get_code_lines (size_t line, size_t num_lines);
@@ -144,9 +138,6 @@
   // calculated.
   octave::file_info *m_file_info;
 
-  // pointer to the current unwind_protect frame of this function.
-  octave::unwind_protect *curr_unwind_protect_frame;
-
   // The list of commands that make up the body of this function.
   octave::tree_statement_list *cmd_list;
 };
--- a/libinterp/parse-tree/pt-eval.cc	Tue May 22 22:41:12 2018 +0200
+++ b/libinterp/parse-tree/pt-eval.cc	Mon May 21 19:32:57 2018 -0400
@@ -2973,22 +2973,15 @@
   {
     // This function is expected to be called from ECHO, which would be
     // the top of the call stack.  If the caller of ECHO is a
-    // user-defined fucntion or script, then set up unwind-protect
+    // user-defined function or script, then set up unwind-protect
     // elements to restore echo state.
 
-    octave_function *caller = m_call_stack.caller ();
-
-    if (caller && caller->is_user_code ())
+    unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame ();
+
+    if (frame)
       {
-        octave_user_code *fcn = dynamic_cast<octave_user_code *> (caller);
-
-        unwind_protect *frame = fcn->unwind_protect_frame ();
-
-        if (frame)
-          {
-            push_echo_state_cleanup (*frame);
-            return true;
-          }
+        push_echo_state_cleanup (*frame);
+        return true;
       }
 
     return false;