Mercurial > octave
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;