# HG changeset patch # User John W. Eaton # Date 1601041433 14400 # Node ID c5953e65c6aaeb8de96de4ecf99d7474bec6077b # Parent 396d3e1df78b6544814d31bca71876a6842fd538 track direct caller in stack frames * stack-frame.h, stack-frame.cc (stack_frame::m_parent_link): New data member to track direct parent, not just user-defined function, script, or scope frames as m_static_link does. (stack_frame::parent_link): New function. (stack_frame::stack_frame): Accept parent_link argument. Change all uses. (stack_frame::create): Accept parent_link argument. Change all uses. * call-stack.cc (call_stack::pop): Set m_curr_frame to parent_link, not static_link. diff -r 396d3e1df78b -r c5953e65c6aa libinterp/corefcn/call-stack.cc --- a/libinterp/corefcn/call-stack.cc Wed Sep 23 21:23:01 2020 +0200 +++ b/libinterp/corefcn/call-stack.cc Fri Sep 25 09:43:53 2020 -0400 @@ -27,8 +27,6 @@ # include "config.h" #endif -#include - #include "lo-regexp.h" #include "str-vec.h" @@ -379,7 +377,8 @@ std::shared_ptr slink = get_static_link (prev_frame); std::shared_ptr - new_frame (stack_frame::create (m_evaluator, scope, m_curr_frame, slink)); + new_frame (stack_frame::create (m_evaluator, scope, m_curr_frame, + m_cs[prev_frame], slink)); m_cs.push_back (new_frame); } @@ -397,7 +396,8 @@ std::shared_ptr slink = get_static_link (prev_frame); std::shared_ptr - new_frame (stack_frame::create (m_evaluator, fcn, m_curr_frame, slink, + new_frame (stack_frame::create (m_evaluator, fcn, m_curr_frame, + m_cs[prev_frame], slink, closure_frames)); m_cs.push_back (new_frame); @@ -416,8 +416,8 @@ std::shared_ptr slink = get_static_link (prev_frame); std::shared_ptr - new_frame (stack_frame::create (m_evaluator, fcn, m_curr_frame, slink, - local_vars)); + new_frame (stack_frame::create (m_evaluator, fcn, m_curr_frame, + m_cs[prev_frame], slink, local_vars)); m_cs.push_back (new_frame); } @@ -435,7 +435,7 @@ std::shared_ptr new_frame (stack_frame::create (m_evaluator, script, m_curr_frame, - slink)); + m_cs[prev_frame], slink)); m_cs.push_back (new_frame); } @@ -452,7 +452,8 @@ std::shared_ptr slink = get_static_link (prev_frame); std::shared_ptr - new_frame (stack_frame::create (m_evaluator, fcn, m_curr_frame, slink)); + new_frame (stack_frame::create (m_evaluator, fcn, m_curr_frame, + m_cs[prev_frame], slink)); m_cs.push_back (new_frame); } @@ -752,7 +753,7 @@ { std::shared_ptr elt = m_cs.back (); - std::shared_ptr caller = elt->static_link (); + std::shared_ptr caller = elt->parent_link (); m_curr_frame = caller->index (); diff -r 396d3e1df78b -r c5953e65c6aa libinterp/corefcn/call-stack.h --- a/libinterp/corefcn/call-stack.h Wed Sep 23 21:23:01 2020 +0200 +++ b/libinterp/corefcn/call-stack.h Fri Sep 25 09:43:53 2020 -0400 @@ -308,16 +308,16 @@ tree_evaluator& m_evaluator; - // The current call stack. - // FIXME: maybe we should be using a std::shared_ptr to manage the - // individual stack frames? + // The list of stack frames. stack_frames m_cs; - // FIXME: Could we eliminate this variable and manage the current - // frame in the evaluator class instead? The current frame might - // always be the top of the stack. Restoring the previous/current - // frame would be managed by other means, such as an - // unwind_protect frame. + // The current frame. When a new frame is pushed, m_curr_frame + // moves to the end of the list of stack frames (also referred to as + // the top of the call stack) but may be temporarily moved to + // another location by evalin or debugging functions. + + // FIXME: should the current frame be managed by the evaluator + // instead? size_t m_curr_frame; int m_max_stack_depth; diff -r 396d3e1df78b -r c5953e65c6aa libinterp/corefcn/stack-frame.cc --- a/libinterp/corefcn/stack-frame.cc Wed Sep 23 21:23:01 2020 +0200 +++ b/libinterp/corefcn/stack-frame.cc Fri Sep 25 09:43:53 2020 -0400 @@ -57,8 +57,10 @@ compiled_fcn_stack_frame (tree_evaluator& tw, octave_function *fcn, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link) - : stack_frame (tw, index, static_link, static_link->access_link ()), + : stack_frame (tw, index, parent_link, static_link, + static_link->access_link ()), m_fcn (fcn) { } @@ -176,6 +178,7 @@ script_stack_frame (tree_evaluator& tw, octave_user_script *script, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link); script_stack_frame (const script_stack_frame& elt) = default; @@ -288,9 +291,10 @@ base_value_stack_frame (tree_evaluator& tw, size_t num_symbols, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link, const std::shared_ptr& access_link) - : stack_frame (tw, index, static_link, access_link), + : stack_frame (tw, index, parent_link, static_link, access_link), m_values (num_symbols, octave_value ()), m_flags (num_symbols, LOCAL), m_auto_vars (NUM_AUTO_VARS, octave_value ()) @@ -393,9 +397,11 @@ user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link, const std::shared_ptr& access_link = std::shared_ptr ()) - : base_value_stack_frame (tw, get_num_symbols (fcn), index, static_link, + : base_value_stack_frame (tw, get_num_symbols (fcn), index, + parent_link, static_link, (access_link ? access_link : get_access_link (fcn, static_link))), @@ -404,9 +410,11 @@ user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link, const local_vars_map& local_vars) - : base_value_stack_frame (tw, get_num_symbols (fcn), index, static_link, + : base_value_stack_frame (tw, get_num_symbols (fcn), index, + parent_link, static_link, get_access_link (fcn, static_link)), m_fcn (fcn), m_unwind_protect_frame (nullptr) { @@ -495,9 +503,10 @@ scope_stack_frame (tree_evaluator& tw, const symbol_scope& scope, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link) : base_value_stack_frame (tw, scope.num_symbols (), index, - static_link, nullptr), + parent_link, static_link, nullptr), m_scope (scope) { } @@ -1024,40 +1033,45 @@ stack_frame * stack_frame::create (tree_evaluator& tw, octave_function *fcn, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link) { - return new compiled_fcn_stack_frame (tw, fcn, index, static_link); + return new compiled_fcn_stack_frame (tw, fcn, index, parent_link, static_link); } stack_frame * stack_frame::create (tree_evaluator& tw, octave_user_script *script, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link) { - return new script_stack_frame (tw, script, index, static_link); + return new script_stack_frame (tw, script, index, parent_link, static_link); } stack_frame * stack_frame::create (tree_evaluator& tw, octave_user_function *fcn, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link, const std::shared_ptr& access_link) { - return new user_fcn_stack_frame (tw, fcn, index, static_link, access_link); + return new user_fcn_stack_frame (tw, fcn, index, parent_link, static_link, access_link); } stack_frame * stack_frame::create (tree_evaluator& tw, octave_user_function *fcn, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link, const local_vars_map& local_vars) { - return new user_fcn_stack_frame (tw, fcn, index, static_link, local_vars); + return new user_fcn_stack_frame (tw, fcn, index, parent_link, static_link, local_vars); } stack_frame * stack_frame::create (tree_evaluator& tw, const symbol_scope& scope, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link) { - return new scope_stack_frame (tw, scope, index, static_link); + return new scope_stack_frame (tw, scope, index, parent_link, static_link); } // This function is only implemented for user_fcn stack frames and @@ -1388,6 +1402,13 @@ os << "-- [stack_frame] (" << this << ") --" << std::endl; + os << "parent link: "; + if (m_parent_link) + os << m_parent_link.get (); + else + os << "NULL"; + os << std::endl; + os << "static link: "; if (m_static_link) os << m_static_link.get (); @@ -1441,8 +1462,10 @@ script_stack_frame::script_stack_frame (tree_evaluator& tw, octave_user_script *script, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link) - : stack_frame (tw, index, static_link, get_access_link (static_link)), + : stack_frame (tw, index, parent_link, static_link, + get_access_link (static_link)), m_script (script), m_unwind_protect_frame (nullptr), m_lexical_frame_offsets (get_num_symbols (script), 1), m_value_offsets (get_num_symbols (script), 0) diff -r 396d3e1df78b -r c5953e65c6aa libinterp/corefcn/stack-frame.h --- a/libinterp/corefcn/stack-frame.h Wed Sep 23 21:23:01 2020 +0200 +++ b/libinterp/corefcn/stack-frame.h Fri Sep 25 09:43:53 2020 -0400 @@ -140,38 +140,44 @@ stack_frame (void) = delete; stack_frame (tree_evaluator& tw, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link, const std::shared_ptr& access_link) : m_evaluator (tw), m_line (-1), m_column (-1), m_index (index), - m_static_link (static_link), m_access_link (access_link), - m_dispatch_class () + m_parent_link (parent_link), m_static_link (static_link), + m_access_link (access_link), m_dispatch_class () { } // Compiled function. static stack_frame * create (tree_evaluator& tw, octave_function *fcn, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link); // Script. static stack_frame * create (tree_evaluator& tw, octave_user_script *script, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link); // User-defined function. static stack_frame * create (tree_evaluator& tw, octave_user_function *fcn, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link, const std::shared_ptr& access_link = std::shared_ptr ()); // Anonymous user-defined function with init vars. static stack_frame * create (tree_evaluator& tw, octave_user_function *fcn, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link, const local_vars_map& local_vars); // Scope. static stack_frame * create (tree_evaluator& tw, const symbol_scope& scope, size_t index, + const std::shared_ptr& parent_link, const std::shared_ptr& static_link); stack_frame (const stack_frame& elt) = default; @@ -300,6 +306,9 @@ } std::shared_ptr + parent_link (void) const {return m_parent_link; } + + std::shared_ptr static_link (void) const {return m_static_link; } std::shared_ptr @@ -556,8 +565,13 @@ // Index in call stack. size_t m_index; + // Pointer to the nearest parent frame. May include compiled + // functions. + std::shared_ptr m_parent_link; + // Pointer to the nearest parent frame that contains variable - // information (script, function, or scope). + // information (script, function, or scope). This link skips over + // compiled function parent frames. std::shared_ptr m_static_link; // Pointer to the nearest lexical parent frame. Used to access