Mercurial > octave
changeset 28426:9a3deb17b4ea stable
use shared_ptr for stack frames in call stack and for accesss and static links
* call-stack.h, call-stack.cc: Use std::shared_ptr<stack_frame>
instead of bare pointer for elements of call stack. Change all uses.
* stack-frame.h, stack-frame.cc (stack_frame::static_link,
stack_frame::access_link): Use std::shared_ptr<stack_frame>
instead of bare pointer. Change all uses.
(stack_frame::workspace): New function.
* ov-fcn-handle.h, ov-fcn-handle.cc
(octave_fcn_handle::m_closure_frames): Now a
std::shared_ptr<stack_frame> object instead of a list of copied stack
frames. Change all uses.
(octave_fcn_handle::push_closure_context): Simply store
std::shared_ptr to current stack frame.
(octave_fcn_handle::workspace): Call stack_frame::workspace to get
workspace info when we have closure frames.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 25 Apr 2020 13:17:11 -0400 |
parents | a5be4fc661d6 |
children | 7a8c69c4eb55 |
files | libinterp/corefcn/call-stack.cc libinterp/corefcn/call-stack.h libinterp/corefcn/stack-frame.cc libinterp/corefcn/stack-frame.h libinterp/octave-value/ov-fcn-handle.cc libinterp/octave-value/ov-fcn-handle.h libinterp/octave-value/ov-fcn.cc libinterp/octave-value/ov-fcn.h libinterp/octave-value/ov-usr-fcn.cc libinterp/octave-value/ov-usr-fcn.h libinterp/parse-tree/oct-lvalue.cc libinterp/parse-tree/oct-lvalue.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-fcn-handle.cc |
diffstat | 15 files changed, 276 insertions(+), 267 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/call-stack.cc Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/corefcn/call-stack.cc Sat Apr 25 13:17:11 2020 -0400 @@ -94,7 +94,7 @@ if (! m_cs.empty ()) { - const stack_frame *elt = m_cs[m_curr_frame]; + const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame]; retval = elt->line (); } @@ -107,7 +107,7 @@ if (! m_cs.empty ()) { - const stack_frame *elt = m_cs[m_curr_frame]; + const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame]; retval = elt->column (); } @@ -122,7 +122,7 @@ if (xframe > 0) { - const stack_frame *elt = m_cs[xframe]; + const std::shared_ptr<stack_frame> elt = m_cs[xframe]; octave_function *f = elt->function (); @@ -141,7 +141,7 @@ if (xframe > 0) { - const stack_frame *elt = m_cs[xframe]; + const std::shared_ptr<stack_frame> elt = m_cs[xframe]; octave_function *f = elt->function (); @@ -165,7 +165,7 @@ if (xframe > 0) { - const stack_frame *elt = m_cs[xframe]; + const std::shared_ptr<stack_frame> elt = m_cs[xframe]; octave_function *f = elt->function (); @@ -189,7 +189,7 @@ if (xframe > 0) { - const stack_frame *elt = m_cs[xframe]; + const std::shared_ptr<stack_frame> elt = m_cs[xframe]; octave_function *f = elt->function (); @@ -212,7 +212,7 @@ while (i != 0) { - const stack_frame *elt = m_cs[i--]; + const std::shared_ptr<stack_frame> elt = m_cs[i--]; octave_function *f = elt->function (); @@ -238,7 +238,7 @@ while (i != 0) { - const stack_frame *elt = m_cs[i--]; + const std::shared_ptr<stack_frame> elt = m_cs[i--]; octave_function *f = elt->function (); @@ -268,7 +268,7 @@ while (i != 0) { - const stack_frame *elt = m_cs[i--]; + const std::shared_ptr<stack_frame> elt = m_cs[i--]; octave_function *f = elt->function (); @@ -331,7 +331,7 @@ while (p != m_cs.cbegin ()) { - const stack_frame *elt = *(--p); + const std::shared_ptr<stack_frame> elt = *(--p); octave_function *f = elt->function (); @@ -345,11 +345,12 @@ return retval; } - stack_frame * call_stack::get_static_link (size_t prev_frame) const + std::shared_ptr<stack_frame> + call_stack::get_static_link (size_t prev_frame) const { // FIXME: is there a better way? - stack_frame *slink = nullptr; + std::shared_ptr<stack_frame> slink; if (m_curr_frame > 0) { @@ -373,16 +374,16 @@ if (m_curr_frame > static_cast<size_t> (m_max_stack_depth)) error ("max_stack_depth exceeded"); - stack_frame *slink = get_static_link (prev_frame); + std::shared_ptr<stack_frame> slink = get_static_link (prev_frame); - stack_frame *new_frame - = stack_frame::create (m_evaluator, scope, m_curr_frame, slink); + std::shared_ptr<stack_frame> + new_frame (stack_frame::create (m_evaluator, scope, m_curr_frame, slink)); m_cs.push_back (new_frame); } void call_stack::push (octave_user_function *fcn, unwind_protect *up_frame, - stack_frame *closure_frames) + const std::shared_ptr<stack_frame>& closure_frames) { size_t prev_frame = m_curr_frame; m_curr_frame = m_cs.size (); @@ -391,11 +392,11 @@ if (m_curr_frame > static_cast<size_t> (m_max_stack_depth)) error ("max_stack_depth exceeded"); - stack_frame *slink = get_static_link (prev_frame); + std::shared_ptr<stack_frame> slink = get_static_link (prev_frame); - stack_frame *new_frame - = stack_frame::create (m_evaluator, fcn, up_frame, m_curr_frame, - slink, closure_frames); + std::shared_ptr<stack_frame> + new_frame (stack_frame::create (m_evaluator, fcn, up_frame, m_curr_frame, + slink, closure_frames)); m_cs.push_back (new_frame); } @@ -409,11 +410,11 @@ if (m_curr_frame > static_cast<size_t> (m_max_stack_depth)) error ("max_stack_depth exceeded"); - stack_frame *slink = get_static_link (prev_frame); + std::shared_ptr<stack_frame> slink = get_static_link (prev_frame); - stack_frame *new_frame - = stack_frame::create (m_evaluator, script, up_frame, m_curr_frame, - slink); + std::shared_ptr<stack_frame> + new_frame (stack_frame::create (m_evaluator, script, up_frame, + m_curr_frame, slink)); m_cs.push_back (new_frame); } @@ -427,10 +428,10 @@ if (m_curr_frame > static_cast<size_t> (m_max_stack_depth)) error ("max_stack_depth exceeded"); - stack_frame *slink = get_static_link (prev_frame); + std::shared_ptr<stack_frame> slink = get_static_link (prev_frame); - stack_frame *new_frame - = stack_frame::create (m_evaluator, fcn, m_curr_frame, slink); + std::shared_ptr<stack_frame> + new_frame (stack_frame::create (m_evaluator, fcn, m_curr_frame, slink)); m_cs.push_back (new_frame); } @@ -447,7 +448,7 @@ if (verbose) { - const stack_frame *elt = m_cs[n]; + const std::shared_ptr<stack_frame> elt = m_cs[n]; elt->display_stopped_in_message (octave_stdout); } @@ -460,7 +461,7 @@ { size_t user_frame = m_curr_frame; - stack_frame *frm = m_cs[user_frame]; + std::shared_ptr<stack_frame> frm = m_cs[user_frame]; if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame () || frm->is_scope_frame ())) @@ -473,7 +474,7 @@ return user_frame; } - stack_frame *call_stack::current_user_frame (void) const + std::shared_ptr<stack_frame> call_stack::current_user_frame (void) const { size_t frame = find_current_user_frame (); @@ -499,7 +500,7 @@ return start; } - stack_frame *frm = m_cs[start]; + std::shared_ptr<stack_frame> frm = m_cs[start]; if (! (frm && (frm->is_user_fcn_frame () || frm->is_user_script_frame () @@ -603,10 +604,10 @@ m_curr_frame = 0; } - std::list<stack_frame *> + std::list<std::shared_ptr<stack_frame>> call_stack::backtrace_frames (octave_idx_type& curr_user_frame) const { - std::list<stack_frame *> frames; + std::list<std::shared_ptr<stack_frame>> frames; // curr_frame is the index to the current frame in the overall call // stack, which includes any compiled function frames and scope @@ -619,7 +620,7 @@ for (size_t n = m_cs.size () - 1; n > 0; n--) { - stack_frame *frm = m_cs[n]; + std::shared_ptr<stack_frame> frm = m_cs[n]; if (frm->is_user_script_frame () || frm->is_user_fcn_frame () || frm->is_scope_frame ()) @@ -637,7 +638,7 @@ return frames; } - std::list<stack_frame *> + std::list<std::shared_ptr<stack_frame>> call_stack::backtrace_frames (void) const { octave_idx_type curr_user_frame = -1; @@ -649,11 +650,12 @@ call_stack::backtrace_info (octave_idx_type& curr_user_frame, bool print_subfn) const { - std::list<stack_frame *> frames = backtrace_frames (curr_user_frame); + std::list<std::shared_ptr<stack_frame>> frames + = backtrace_frames (curr_user_frame); std::list<frame_info> retval; - for (const auto *frm : frames) + for (const auto& frm : frames) { if (frm->is_user_script_frame () || frm->is_user_fcn_frame () || frm->is_scope_frame ()) @@ -677,7 +679,8 @@ octave_map call_stack::backtrace (octave_idx_type& curr_user_frame, bool print_subfn) const { - std::list<stack_frame *> frames = backtrace_frames (curr_user_frame); + std::list<std::shared_ptr<stack_frame>> frames + = backtrace_frames (curr_user_frame); size_t nframes = frames.size (); @@ -690,7 +693,7 @@ octave_idx_type k = 0; - for (const auto *frm : frames) + for (const auto& frm : frames) { if (frm->is_user_script_frame () || frm->is_user_fcn_frame () || frm->is_scope_frame ()) @@ -726,15 +729,13 @@ if (m_cs.size () > 1) { - stack_frame *elt = m_cs.back (); + std::shared_ptr<stack_frame> elt = m_cs.back (); - stack_frame *caller = elt->static_link (); + std::shared_ptr<stack_frame> caller = elt->static_link (); m_curr_frame = caller->index (); m_cs.pop_back (); - - delete elt; } }
--- a/libinterp/corefcn/call-stack.h Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/corefcn/call-stack.h Sat Apr 25 13:17:11 2020 -0400 @@ -29,6 +29,7 @@ #include "octave-config.h" #include <deque> +#include <memory> #include <string> class octave_function; @@ -55,7 +56,7 @@ { public: - typedef std::deque<stack_frame *> stack_frames; + typedef std::deque<std::shared_ptr<stack_frame>> stack_frames; typedef stack_frames::iterator iterator; typedef stack_frames::const_iterator const_iterator; @@ -87,14 +88,9 @@ size_t size (void) const { return m_cs.size (); } - const stack_frame& get_current_stack_frame (void) const + std::shared_ptr<stack_frame> get_current_stack_frame (void) const { - return *(m_cs[m_curr_frame]); - } - - stack_frame& get_current_stack_frame (void) - { - return *(m_cs[m_curr_frame]); + return m_cs[m_curr_frame]; } symbol_scope top_scope (void) const @@ -121,10 +117,7 @@ octave_function *retval = nullptr; if (m_cs.size () > n) - { - stack_frame *elt = m_cs[n]; - retval = elt->function (); - } + retval = m_cs[n]->function (); return retval; } @@ -160,12 +153,12 @@ // Return TRUE if all elements on the call stack are scripts. bool all_scripts (void) const; - stack_frame * get_static_link (size_t prev_frame) const; + std::shared_ptr<stack_frame> get_static_link (size_t prev_frame) const; void push (const symbol_scope& scope); void push (octave_user_function *fcn, unwind_protect *up_frame, - stack_frame *closure_frames = nullptr); + const std::shared_ptr<stack_frame>& closure_frames = std::shared_ptr<stack_frame> ()); void push (octave_user_script *script, unwind_protect *up_frame); @@ -175,7 +168,7 @@ { if (! m_cs.empty ()) { - stack_frame *elt = m_cs.back (); + std::shared_ptr<stack_frame> elt = m_cs.back (); elt->line (l); elt->column (c); @@ -186,7 +179,7 @@ { if (! m_cs.empty ()) { - stack_frame *elt = m_cs.back (); + std::shared_ptr<stack_frame> elt = m_cs.back (); elt->line (l); } @@ -196,7 +189,7 @@ { if (! m_cs.empty ()) { - stack_frame *elt = m_cs.back (); + std::shared_ptr<stack_frame> elt = m_cs.back (); elt->column (c); } @@ -210,7 +203,8 @@ } size_t find_current_user_frame (void) const; - stack_frame *current_user_frame (void) const; + + std::shared_ptr<stack_frame> current_user_frame (void) const; size_t dbupdown (size_t start, int n, bool verbose); size_t dbupdown (int n = -1, bool verbose = false); @@ -219,12 +213,12 @@ void goto_base_frame (void); - std::list<stack_frame *> + std::list<std::shared_ptr<stack_frame>> backtrace_frames (octave_idx_type& curr_user_frame) const; // List of raw stack frames. - std::list<stack_frame *> backtrace_frames (void) const; + std::list<std::shared_ptr<stack_frame>> backtrace_frames (void) const; // List of stack_info objects that can be used in liboctave and // stored in the execution_exception object.
--- a/libinterp/corefcn/stack-frame.cc Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/corefcn/stack-frame.cc Sat Apr 25 13:17:11 2020 -0400 @@ -56,7 +56,8 @@ compiled_fcn_stack_frame (void) = delete; compiled_fcn_stack_frame (tree_evaluator& tw, octave_function *fcn, - size_t index, stack_frame *static_link) + size_t index, + const std::shared_ptr<stack_frame>& static_link) : stack_frame (tw, index, static_link, static_link->access_link ()), m_fcn (fcn) { } @@ -177,7 +178,7 @@ script_stack_frame (tree_evaluator& tw, octave_user_script *script, unwind_protect *up_frame, size_t index, - stack_frame *static_link); + const std::shared_ptr<stack_frame>& static_link); script_stack_frame (const script_stack_frame& elt) = default; @@ -189,7 +190,8 @@ bool is_user_script_frame (void) const { return true; } - static stack_frame * get_access_link (stack_frame *static_link); + static std::shared_ptr<stack_frame> + get_access_link (const std::shared_ptr<stack_frame>& static_link); static size_t get_num_symbols (octave_user_script *script); @@ -287,8 +289,9 @@ base_value_stack_frame (void) = delete; base_value_stack_frame (tree_evaluator& tw, size_t num_symbols, - size_t index, stack_frame *static_link, - stack_frame *access_link) + size_t index, + const std::shared_ptr<stack_frame>& static_link, + const std::shared_ptr<stack_frame>& access_link) : stack_frame (tw, index, static_link, access_link), m_values (num_symbols, octave_value ()), m_flags (num_symbols, LOCAL), @@ -392,8 +395,8 @@ user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn, unwind_protect *up_frame, size_t index, - stack_frame *static_link, - stack_frame *access_link = nullptr) + const std::shared_ptr<stack_frame>& static_link, + const std::shared_ptr<stack_frame>& access_link = std::shared_ptr<stack_frame> ()) : base_value_stack_frame (tw, get_num_symbols (fcn), index, static_link, (access_link ? access_link @@ -412,8 +415,9 @@ bool is_user_fcn_frame (void) const { return true; } - static stack_frame * - get_access_link (octave_user_function *fcn, stack_frame *static_link); + static std::shared_ptr<stack_frame> + get_access_link (octave_user_function *fcn, + const std::shared_ptr<stack_frame>& static_link); static size_t get_num_symbols (octave_user_function *fcn) { @@ -478,7 +482,8 @@ scope_stack_frame (void) = delete; scope_stack_frame (tree_evaluator& tw, const symbol_scope& scope, - size_t index, stack_frame *static_link) + size_t index, + const std::shared_ptr<stack_frame>& static_link) : base_value_stack_frame (tw, scope.num_symbols (), index, static_link, nullptr), m_scope (scope) @@ -617,7 +622,7 @@ // link for a compiled_fcn_stack_frame be the same as the static // link? - stack_frame *slink = frame.static_link (); + std::shared_ptr<stack_frame> slink = frame.static_link (); if (slink) slink->accept (*this); @@ -625,7 +630,7 @@ void visit_script_stack_frame (script_stack_frame& frame) { - stack_frame *alink = frame.access_link (); + std::shared_ptr<stack_frame> alink = frame.access_link (); if (alink) alink->accept (*this); @@ -635,7 +640,7 @@ { clean_frame (frame); - stack_frame *alink = frame.access_link (); + std::shared_ptr<stack_frame> alink = frame.access_link (); if (alink) alink->accept (*this); @@ -645,7 +650,7 @@ { clean_frame (frame); - stack_frame *alink = frame.access_link (); + std::shared_ptr<stack_frame> alink = frame.access_link (); if (alink) alink->accept (*this); @@ -859,7 +864,7 @@ // link for a compiled_fcn_stack_frame be the same as the static // link? - stack_frame *slink = frame.static_link (); + std::shared_ptr<stack_frame> slink = frame.static_link (); if (slink) slink->accept (*this); @@ -867,7 +872,7 @@ void visit_script_stack_frame (script_stack_frame& frame) { - stack_frame *alink = frame.access_link (); + std::shared_ptr<stack_frame> alink = frame.access_link (); if (alink) alink->accept (*this); @@ -877,7 +882,7 @@ { append_list (frame); - stack_frame *alink = frame.access_link (); + std::shared_ptr<stack_frame> alink = frame.access_link (); if (alink) alink->accept (*this); @@ -887,7 +892,7 @@ { append_list (frame); - stack_frame *alink = frame.access_link (); + std::shared_ptr<stack_frame> alink = frame.access_link (); if (alink) alink->accept (*this); @@ -1008,7 +1013,8 @@ }; stack_frame * stack_frame::create (tree_evaluator& tw, octave_function *fcn, - size_t index, stack_frame *static_link) + size_t index, + const std::shared_ptr<stack_frame>& static_link) { return new compiled_fcn_stack_frame (tw, fcn, index, static_link); } @@ -1016,7 +1022,7 @@ stack_frame * stack_frame::create (tree_evaluator& tw, octave_user_script *script, unwind_protect *up_frame, size_t index, - stack_frame *static_link) + const std::shared_ptr<stack_frame>& static_link) { return new script_stack_frame (tw, script, up_frame, index, static_link); } @@ -1024,8 +1030,8 @@ stack_frame * stack_frame::create (tree_evaluator& tw, octave_user_function *fcn, unwind_protect *up_frame, size_t index, - stack_frame *static_link, - stack_frame *access_link) + const std::shared_ptr<stack_frame>& static_link, + const std::shared_ptr<stack_frame>& access_link) { return new user_fcn_stack_frame (tw, fcn, up_frame, index, static_link, access_link); @@ -1033,7 +1039,7 @@ stack_frame * stack_frame::create (tree_evaluator& tw, const symbol_scope& scope, size_t index, - stack_frame *static_link) + const std::shared_ptr<stack_frame>& static_link) { return new scope_stack_frame (tw, scope, index, static_link); } @@ -1120,6 +1126,41 @@ return sia.symbol_info (); } + octave_value stack_frame::workspace (void) + { + std::list<octave_scalar_map> ws_list; + + stack_frame *frame = this; + + while (frame) + { + octave::symbol_info_list symbols = frame->all_variables (); + + octave_scalar_map ws; + + for (const auto& sym_name : symbols.names ()) + { + octave_value val = symbols.varval (sym_name); + + if (val.is_defined ()) + ws.assign (sym_name, val); + } + + ws_list.push_back (ws); + + std::shared_ptr<stack_frame> nxt = frame->access_link (); + frame = nxt.get (); + } + + Cell ws_frames (ws_list.size (), 1); + + octave_idx_type i = 0; + for (const auto& elt : ws_list) + ws_frames(i++) = elt; + + return ws_frames; + } + // FIXME: Should this function also find any variables in parent // scopes accessible through access_links? @@ -1333,14 +1374,14 @@ os << "static link: "; if (m_static_link) - os << m_static_link; + os << m_static_link.get (); else os << "NULL"; os << std::endl; os << "access link: "; if (m_access_link) - os << m_access_link; + os << m_access_link.get (); else os << "NULL"; os << std::endl; @@ -1355,7 +1396,7 @@ return; os << "FOLLOWING ACCESS LINKS:" << std::endl; - const stack_frame *frm = access_link (); + std::shared_ptr<stack_frame> frm = access_link (); while (frm) { frm->display (false); @@ -1391,7 +1432,7 @@ octave_user_script *script, unwind_protect *up_frame, size_t index, - stack_frame *static_link) + const std::shared_ptr<stack_frame>& static_link) : stack_frame (tw, index, static_link, get_access_link (static_link)), m_script (script), m_unwind_protect_frame (up_frame), m_lexical_frame_offsets (get_num_symbols (script), 1), @@ -1542,15 +1583,13 @@ // If this is a nested scope, set access_link to nearest parent // stack frame that corresponds to the lexical parent of this scope. - stack_frame * - script_stack_frame::get_access_link (stack_frame *static_link) + std::shared_ptr<stack_frame> + script_stack_frame::get_access_link (const std::shared_ptr<stack_frame>& static_link) { - stack_frame *alink = nullptr; - // If this script is called from another script, set access // link to ultimate parent stack frame. - alink = static_link; + std::shared_ptr<stack_frame> alink = static_link; while (alink->is_user_script_frame ()) { @@ -1817,7 +1856,10 @@ const stack_frame *frame = this; for (size_t i = 0; i < frame_offset; i++) - frame = frame->access_link (); + { + std::shared_ptr<stack_frame> nxt = frame->access_link (); + frame = nxt.get (); + } if (! frame) error ("internal error: invalid access link in function call stack"); @@ -1844,7 +1886,10 @@ const stack_frame *frame = this; for (size_t i = 0; i < frame_offset; i++) - frame = frame->access_link (); + { + std::shared_ptr<stack_frame> nxt = frame->access_link (); + frame = nxt.get (); + } if (! frame) error ("internal error: invalid access link in function call stack"); @@ -1883,7 +1928,10 @@ stack_frame *frame = this; for (size_t i = 0; i < frame_offset; i++) - frame = frame->access_link (); + { + std::shared_ptr<stack_frame> nxt = frame->access_link (); + frame = nxt.get (); + } if (data_offset >= frame->size ()) frame->resize (data_offset+1); @@ -1920,7 +1968,7 @@ if (frame_offset > 1) error ("variables must be made PERSISTENT or GLOBAL in the first scope in which they are used"); - stack_frame *frame = access_link (); + std::shared_ptr<stack_frame> frame = access_link (); if (data_offset >= frame->size ()) frame->resize (data_offset+1); @@ -1988,11 +2036,11 @@ // If this is a nested scope, set access_link to nearest parent // stack frame that corresponds to the lexical parent of this scope. - stack_frame * + std::shared_ptr<stack_frame> user_fcn_stack_frame::get_access_link (octave_user_function *fcn, - stack_frame *static_link) + const std::shared_ptr<stack_frame>& static_link) { - stack_frame *alink = nullptr; + std::shared_ptr<stack_frame> alink; symbol_scope fcn_scope = fcn->scope (); @@ -2083,7 +2131,8 @@ if (sym) return sym; - frame = frame->access_link (); + std::shared_ptr<stack_frame> nxt = frame->access_link (); + frame = nxt.get (); } return symbol_record (); @@ -2139,7 +2188,10 @@ const stack_frame *frame = this; for (size_t i = 0; i < frame_offset; i++) - frame = frame->access_link (); + { + std::shared_ptr<stack_frame> nxt = frame->access_link (); + frame = nxt.get (); + } if (! frame) error ("internal error: invalid access link in function call stack"); @@ -2161,7 +2213,10 @@ const stack_frame *frame = this; for (size_t i = 0; i < frame_offset; i++) - frame = frame->access_link (); + { + std::shared_ptr<stack_frame> nxt = frame->access_link (); + frame = nxt.get (); + } if (! frame) error ("internal error: invalid access link in function call stack"); @@ -2199,7 +2254,10 @@ stack_frame *frame = this; for (size_t i = 0; i < frame_offset; i++) - frame = frame->access_link (); + { + std::shared_ptr<stack_frame> nxt = frame->access_link (); + frame = nxt.get (); + } if (data_offset >= frame->size ()) frame->resize (data_offset+1);
--- a/libinterp/corefcn/stack-frame.h Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/corefcn/stack-frame.h Sat Apr 25 13:17:11 2020 -0400 @@ -32,6 +32,7 @@ #include <iosfwd> #include <list> #include <map> +#include <memory> #include <string> class octave_value; @@ -139,7 +140,8 @@ stack_frame (void) = delete; stack_frame (tree_evaluator& tw, size_t index, - stack_frame *static_link, stack_frame *access_link) + const std::shared_ptr<stack_frame>& static_link, + const std::shared_ptr<stack_frame>& 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 () @@ -148,24 +150,25 @@ // Compiled function. static stack_frame * create (tree_evaluator& tw, octave_function *fcn, size_t index, - stack_frame *static_link); + const std::shared_ptr<stack_frame>& static_link); // Script. static stack_frame * create (tree_evaluator& tw, octave_user_script *script, unwind_protect *up_frame, size_t index, - stack_frame *static_link); + const std::shared_ptr<stack_frame>& static_link); // User-defined function. static stack_frame * create (tree_evaluator& tw, octave_user_function *fcn, unwind_protect *up_frame, size_t index, - stack_frame *static_link, stack_frame *access_link = nullptr); + const std::shared_ptr<stack_frame>& static_link, + const std::shared_ptr<stack_frame>& access_link = std::shared_ptr<stack_frame> ()); // Scope. static stack_frame * create (tree_evaluator& tw, const symbol_scope& scope, size_t index, - stack_frame *static_link); + const std::shared_ptr<stack_frame>& static_link); stack_frame (const stack_frame& elt) = default; @@ -242,6 +245,8 @@ symbol_info_list all_variables (void); + octave_value workspace (void); + std::list<std::string> variable_names (void) const; // Look for named symbol visible from current scope. Don't @@ -293,11 +298,13 @@ mark_global (sym); } - stack_frame * static_link (void) const {return m_static_link; } + std::shared_ptr<stack_frame> + static_link (void) const {return m_static_link; } - stack_frame * access_link (void) const {return m_access_link; } + std::shared_ptr<stack_frame> + access_link (void) const {return m_access_link; } - void set_closure_links (stack_frame *dup_frame) + void set_closure_links (const std::shared_ptr<stack_frame>& dup_frame) { m_static_link = dup_frame; m_access_link = dup_frame; @@ -556,12 +563,12 @@ // Pointer to the nearest parent frame that contains variable // information (script, function, or scope). - stack_frame *m_static_link; + std::shared_ptr<stack_frame> m_static_link; // Pointer to the nearest lexical parent frame. Used to access // non-local variables for nested and anonymous functions or as a // link to the parent frame in which a script is executed. - stack_frame *m_access_link; + std::shared_ptr<stack_frame> m_access_link; // Allow function handles to temporarily store their dispatch class // in the call stack.
--- a/libinterp/octave-value/ov-fcn-handle.cc Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/octave-value/ov-fcn-handle.cc Sat Apr 25 13:17:11 2020 -0400 @@ -85,7 +85,7 @@ octave_fcn_handle::octave_fcn_handle (const octave::symbol_scope& scope, const std::string& n) : m_fcn (), m_obj (), m_name (n), m_scope (scope), m_is_nested (false), - m_closure_frames (nullptr), m_dispatch_class () + m_closure_frames (), m_dispatch_class () { if (! m_name.empty () && m_name[0] == '@') m_name = m_name.substr (1); @@ -119,7 +119,7 @@ const octave_value& f, const std::string& n) : m_fcn (f), m_obj (), m_name (n), m_scope (scope), m_is_nested (false), - m_closure_frames (nullptr), m_dispatch_class () + m_closure_frames (), m_dispatch_class () { octave_user_function *uf = m_fcn.user_function_value (true); @@ -138,7 +138,7 @@ octave_fcn_handle::octave_fcn_handle (const octave_value& f, const std::string& n) : m_fcn (f), m_obj (), m_name (n), m_scope (), m_is_nested (false), - m_closure_frames (nullptr), m_dispatch_class () + m_closure_frames (), m_dispatch_class () { octave_user_function *uf = m_fcn.user_function_value (true); @@ -154,23 +154,6 @@ m_is_nested = true; } -octave_fcn_handle::~octave_fcn_handle (void) -{ - if (m_closure_frames) - { - while (m_closure_frames->size () > 0) - { - octave::stack_frame *elt = m_closure_frames->back (); - - delete elt; - - m_closure_frames->pop_back (); - } - - delete m_closure_frames; - } -} - octave_value_list octave_fcn_handle::subsref (const std::string& type, const std::list<octave_value_list>& idx, @@ -375,11 +358,6 @@ if (! fcn_to_call.is_defined ()) err_invalid_fcn_handle (m_name); - octave::stack_frame *closure_context = nullptr; - - if (m_closure_frames && m_closure_frames->size () > 0) - closure_context = m_closure_frames->front (); - octave::tree_evaluator& tw = interp.get_evaluator (); octave_function *of = fcn_to_call.function_value (); @@ -391,7 +369,7 @@ tw.set_dispatch_class (m_dispatch_class); - return of->call (tw, nargout, args, closure_context); + return of->call (tw, nargout, args, m_closure_frames); } dim_vector @@ -440,26 +418,7 @@ void octave_fcn_handle::push_closure_context (octave::tree_evaluator& tw) { - if (! m_closure_frames) - m_closure_frames = new std::list<octave::stack_frame *> (); - - octave::stack_frame& curr_frame = tw.get_current_stack_frame (); - - octave::stack_frame *dup_frame = curr_frame.dup (); - - if (! m_closure_frames->empty ()) - { - octave::stack_frame *top_frame = m_closure_frames->back (); - - // Arrange for static and access links in the top stack frame (the - // last one saved before this one) to point to the new duplicated - // frame. This way we will look up through the duplicated frames - // when evaluating the function. - - top_frame->set_closure_links (dup_frame); - } - - m_closure_frames->push_back (dup_frame); + m_closure_frames = tw.get_current_stack_frame (); } octave_value @@ -481,30 +440,7 @@ } else if (m_closure_frames) { - octave_idx_type num_frames = m_closure_frames->size (); - - Cell ws_frames (num_frames, 1); - - octave_idx_type i = 0; - - for (auto elt : *m_closure_frames) - { - octave::symbol_info_list symbols = elt->all_variables (); - - octave_scalar_map ws; - - for (auto sym_name : symbols.names ()) - { - octave_value val = symbols.varval (sym_name); - - if (val.is_defined ()) - ws.assign (sym_name, val); - } - - ws_frames(i++) = ws; - } - - return ws_frames; + return m_closure_frames->workspace (); } return Cell ();
--- a/libinterp/octave-value/ov-fcn-handle.h Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/octave-value/ov-fcn-handle.h Sat Apr 25 13:17:11 2020 -0400 @@ -56,7 +56,7 @@ octave_fcn_handle (void) : m_fcn (), m_obj (), m_name (), m_scope (), m_is_nested (false), - m_closure_frames (nullptr), m_dispatch_class () + m_closure_frames (), m_dispatch_class () { } octave_fcn_handle (const octave::symbol_scope& scope, const std::string& n); @@ -70,7 +70,7 @@ octave_fcn_handle (const octave_fcn_handle& fh) = default; - ~octave_fcn_handle (void); + ~octave_fcn_handle (void) = default; octave_base_value * clone (void) const { return new octave_fcn_handle (*this); } @@ -184,7 +184,7 @@ // Saved stack frames for handles to nested functions. This allows us // to access non-locals and other context info when calling nested // functions indirectly through handles. - std::list<octave::stack_frame *> *m_closure_frames; + std::shared_ptr<octave::stack_frame> m_closure_frames; // The name of the class in which this handle was created, if any. // Used to determine access permission when the referenced function is
--- a/libinterp/octave-value/ov-fcn.cc Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/octave-value/ov-fcn.cc Sat Apr 25 13:17:11 2020 -0400 @@ -47,7 +47,7 @@ octave_value_list octave_function::call (octave::tree_evaluator& tw, int nargout, const octave_value_list& args, - octave::stack_frame *closure_context) + const std::shared_ptr<octave::stack_frame>& closure_context) { if (closure_context) panic_impossible ();
--- a/libinterp/octave-value/ov-fcn.h Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/octave-value/ov-fcn.h Sat Apr 25 13:17:11 2020 -0400 @@ -230,7 +230,7 @@ virtual octave_value_list call (octave::tree_evaluator& tw, int nargout, const octave_value_list& args, - octave::stack_frame *closure_context); + const std::shared_ptr<octave::stack_frame>& closure_context); protected:
--- a/libinterp/octave-value/ov-usr-fcn.cc Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/octave-value/ov-usr-fcn.cc Sat Apr 25 13:17:11 2020 -0400 @@ -462,7 +462,7 @@ octave_value_list octave_user_function::call (octave::tree_evaluator& tw, int nargout, const octave_value_list& args, - octave::stack_frame *closure_frames) + const std::shared_ptr<octave::stack_frame>& closure_frames) { return tw.execute_user_function (*this, nargout, args, closure_frames); }
--- a/libinterp/octave-value/ov-usr-fcn.h Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/octave-value/ov-usr-fcn.h Sat Apr 25 13:17:11 2020 -0400 @@ -381,7 +381,8 @@ octave_value_list call (octave::tree_evaluator& tw, int nargout, - const octave_value_list& args, octave::stack_frame *); + const octave_value_list& args, + const std::shared_ptr<octave::stack_frame>&); octave::tree_parameter_list * parameter_list (void) { return param_list; }
--- a/libinterp/parse-tree/oct-lvalue.cc Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/parse-tree/oct-lvalue.cc Sat Apr 25 13:17:11 2020 -0400 @@ -36,7 +36,7 @@ { bool octave_lvalue::is_defined (void) const { - return ! is_black_hole () && m_frame.is_defined (m_sym); + return ! is_black_hole () && m_frame->is_defined (m_sym); } bool octave_lvalue::is_undefined (void) const @@ -46,14 +46,14 @@ void octave_lvalue::define (const octave_value& v) { - m_frame.assign (m_sym, v); + m_frame->assign (m_sym, v); } void octave_lvalue::assign (octave_value::assign_op op, const octave_value& rhs) { if (! is_black_hole ()) - m_frame.assign (op, m_sym, m_type, m_idx, rhs); + m_frame->assign (op, m_sym, m_type, m_idx, rhs); } void octave_lvalue::set_index (const std::string& t, @@ -97,12 +97,12 @@ void octave_lvalue::do_unary_op (octave_value::unary_op op) { if (! is_black_hole ()) - m_frame.do_non_const_unary_op (op, m_sym, m_type, m_idx); + m_frame->do_non_const_unary_op (op, m_sym, m_type, m_idx); } octave_value octave_lvalue::value (void) const { return (is_black_hole () - ? octave_value () : m_frame.value (m_sym, m_type, m_idx)); + ? octave_value () : m_frame->value (m_sym, m_type, m_idx)); } }
--- a/libinterp/parse-tree/oct-lvalue.h Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/parse-tree/oct-lvalue.h Sat Apr 25 13:17:11 2020 -0400 @@ -40,7 +40,8 @@ { public: - octave_lvalue (const symbol_record& sr, stack_frame& frame) + octave_lvalue (const symbol_record& sr, + const std::shared_ptr<stack_frame>& frame) : m_sym (sr), m_frame (frame), m_black_hole (false), m_type (), m_idx (), m_nel (1) { } @@ -87,7 +88,7 @@ symbol_record m_sym; - stack_frame& m_frame; + std::shared_ptr<stack_frame> m_frame; bool m_black_hole;
--- a/libinterp/parse-tree/pt-eval.cc Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/parse-tree/pt-eval.cc Sat Apr 25 13:17:11 2020 -0400 @@ -187,7 +187,7 @@ if (! silent) { - stack_frame *frm = tw.current_user_frame (); + std::shared_ptr<stack_frame> frm = tw.current_user_frame (); frm->display_stopped_in_message (buf); } @@ -894,17 +894,19 @@ bool tree_evaluator::is_variable (const std::string& name) const { - const stack_frame& frame = m_call_stack.get_current_stack_frame (); - - return frame.is_variable (name); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_variable (name); } bool tree_evaluator::is_local_variable (const std::string& name) const { - const stack_frame& frame = m_call_stack.get_current_stack_frame (); - - return frame.is_local_variable (name); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_local_variable (name); } bool @@ -941,49 +943,55 @@ bool tree_evaluator::is_variable (const symbol_record& sym) const { - const stack_frame& frame = m_call_stack.get_current_stack_frame (); - - return frame.is_variable (sym); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_variable (sym); } bool tree_evaluator::is_defined (const symbol_record& sym) const { - const stack_frame& frame = m_call_stack.get_current_stack_frame (); - - return frame.is_defined (sym); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_defined (sym); } bool tree_evaluator::is_global (const std::string& name) const { - const stack_frame& frame = m_call_stack.get_current_stack_frame (); - - return frame.is_global (name); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_global (name); } octave_value tree_evaluator::varval (const symbol_record& sym) const { - const stack_frame& frame = m_call_stack.get_current_stack_frame (); - - return frame.varval (sym); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + return frame->varval (sym); } octave_value tree_evaluator::varval (const std::string& name) const { - const stack_frame& frame = m_call_stack.get_current_stack_frame (); - - return frame.varval (name); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + return frame->varval (name); } void tree_evaluator::install_variable (const std::string& name, const octave_value& value, bool global) { - stack_frame& frame = m_call_stack.get_current_stack_frame (); - - return frame.install_variable (name, value, global); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + return frame->install_variable (name, value, global); } octave_value @@ -1021,9 +1029,10 @@ void tree_evaluator::assign (const std::string& name, const octave_value& val) { - stack_frame& frame = m_call_stack.get_current_stack_frame (); - - frame.assign (name, val); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + frame->assign (name, val); } void @@ -1521,7 +1530,7 @@ void tree_evaluator::push_stack_frame (octave_user_function *fcn, unwind_protect *up_frame, - stack_frame *closure_frames) + const std::shared_ptr<stack_frame>& closure_frames) { m_call_stack.push (fcn, up_frame, closure_frames); } @@ -1564,7 +1573,7 @@ void tree_evaluator::debug_where (std::ostream& os) const { - stack_frame *frm = m_call_stack.current_user_frame (); + std::shared_ptr<stack_frame> frm = m_call_stack.current_user_frame (); frm->display_stopped_in_message (os); } @@ -1636,13 +1645,13 @@ return m_call_stack.is_class_constructor_executing (dclass); } - std::list<stack_frame *> + std::list<std::shared_ptr<stack_frame>> tree_evaluator::backtrace_frames (octave_idx_type& curr_user_frame) const { return m_call_stack.backtrace_frames (curr_user_frame); } - std::list<stack_frame *> + std::list<std::shared_ptr<stack_frame>> tree_evaluator::backtrace_frames (void) const { return m_call_stack.backtrace_frames (); @@ -1782,9 +1791,10 @@ octave_value tree_evaluator::find (const std::string& name) { - const stack_frame& frame = m_call_stack.get_current_stack_frame (); - - octave_value val = frame.varval (name); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + octave_value val = frame->varval (name); if (val.is_defined ()) return val; @@ -1793,7 +1803,7 @@ // subfunctions if we are currently executing a function defined // from a .m file. - octave_value fcn = frame.find_subfunction (name); + octave_value fcn = frame->find_subfunction (name); if (fcn.is_defined ()) return fcn; @@ -1805,37 +1815,42 @@ void tree_evaluator::clear_objects (void) { - stack_frame& frame = m_call_stack.get_current_stack_frame (); - - frame.clear_objects (); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_objects (); } void tree_evaluator::clear_variable (const std::string& name) { - stack_frame& frame = m_call_stack.get_current_stack_frame (); - - frame.clear_variable (name); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variable (name); } void tree_evaluator::clear_variable_pattern (const std::string& pattern) { - stack_frame& frame = m_call_stack.get_current_stack_frame (); - - frame.clear_variable_pattern (pattern); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variable_pattern (pattern); } void tree_evaluator::clear_variable_regexp (const std::string& pattern) { - stack_frame& frame = m_call_stack.get_current_stack_frame (); - - frame.clear_variable_regexp (pattern); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variable_regexp (pattern); } void tree_evaluator::clear_variables (void) { - stack_frame& frame = m_call_stack.get_current_stack_frame (); - - frame.clear_variables (); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variables (); } void tree_evaluator::clear_global_variable (const std::string& name) @@ -2358,7 +2373,7 @@ tree_evaluator::execute_user_function (octave_user_function& user_function, int nargout, const octave_value_list& xargs, - stack_frame *closure_frames) + const std::shared_ptr<stack_frame>& closure_frames) { octave_value_list retval; @@ -3849,13 +3864,14 @@ void tree_evaluator::init_local_fcn_vars (octave_user_function& user_fcn) { - stack_frame& frame = m_call_stack.get_current_stack_frame (); + std::shared_ptr<stack_frame> frame + = m_call_stack.get_current_stack_frame (); const octave_user_function::local_vars_map& lviv = user_fcn.local_var_init_vals (); for (const auto& nm_ov : lviv) - frame.assign (nm_ov.first, nm_ov.second); + frame->assign (nm_ov.first, nm_ov.second); } std::string
--- a/libinterp/parse-tree/pt-eval.h Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/parse-tree/pt-eval.h Sat Apr 25 13:17:11 2020 -0400 @@ -212,7 +212,7 @@ octave_value_list execute_user_function (octave_user_function& user_function, int nargout, const octave_value_list& args, - stack_frame *closure_frames = nullptr); + const std::shared_ptr<stack_frame>& closure_frames = std::shared_ptr<stack_frame> ()); void visit_octave_user_function_header (octave_user_function&); @@ -378,7 +378,7 @@ void push_stack_frame (octave_user_function *fcn, unwind_protect *up_frame, - stack_frame *closure_frames = nullptr); + const std::shared_ptr<stack_frame>& closure_frames = std::shared_ptr<stack_frame> ()); void push_stack_frame (octave_user_script *script, unwind_protect *up_frame); @@ -387,17 +387,12 @@ void pop_stack_frame (void); - const stack_frame& get_current_stack_frame (void) const + std::shared_ptr<stack_frame> get_current_stack_frame (void) const { return m_call_stack.get_current_stack_frame (); } - stack_frame& get_current_stack_frame (void) - { - return m_call_stack.get_current_stack_frame (); - } - - stack_frame * current_user_frame (void) const + std::shared_ptr<stack_frame> current_user_frame (void) const { return m_call_stack.current_user_frame (); } @@ -443,10 +438,10 @@ bool is_class_constructor_executing (std::string& dispatch_class) const; - std::list<stack_frame *> + std::list<std::shared_ptr<stack_frame>> backtrace_frames (octave_idx_type& curr_user_frame) const; - std::list<stack_frame *> backtrace_frames () const; + std::list<std::shared_ptr<stack_frame>> backtrace_frames () const; std::list<frame_info> backtrace_info (octave_idx_type& curr_user_frame, bool print_subfn = true) const;
--- a/libinterp/parse-tree/pt-fcn-handle.cc Fri Apr 24 14:21:07 2020 -0400 +++ b/libinterp/parse-tree/pt-fcn-handle.cc Sat Apr 25 13:17:11 2020 -0400 @@ -134,11 +134,11 @@ call_stack& cs = tw.get_call_stack (); - stack_frame& frame = cs.get_current_stack_frame (); + std::shared_ptr<stack_frame> frame = cs.get_current_stack_frame (); for (auto& name : free_vars) { - octave_value val = frame.varval (name); + octave_value val = frame->varval (name); if (val.is_defined ()) local_var_init_vals[name] = val;