changeset 24031:ef85638c605a

also cache parent_function in symbol_table scope Inside a symbol table scope, we currently store a pointer to the parent scope (if it exists), but this is not sufficient to prevent the parent scope from being deleted. For example, this can happen when a function that contains an anonymous function definition is deleted. If the anonymous function remains accessible, then resolving any symbols that it references may fail when it is called. Caching the parent function avoids this problem as it increments the reference count for the function, and that will prevent the scope object from being deleted. * symtab.cc (symbol_table::scope::set_parent): Also cache parent function if it exists. * symtab.h (symbol_table::scope::m_parent): New data member. (symbol_table::scope::parent_fcn): New function. (symbol_table::scope::dup): Also copy m_parent_fcn.
author John W. Eaton <jwe@octave.org>
date Fri, 08 Sep 2017 18:15:50 -0400
parents ec3d37eeafa2
children c2ef0eddf6bc
files libinterp/corefcn/symtab.cc libinterp/corefcn/symtab.h
diffstat 2 files changed, 22 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/symtab.cc	Thu Aug 31 21:10:56 2017 +0200
+++ b/libinterp/corefcn/symtab.cc	Fri Sep 08 18:15:50 2017 -0400
@@ -1803,6 +1803,23 @@
   }
 
   void
+  symbol_table::scope::set_parent (scope *p)
+  {
+    m_parent = p;
+
+    if (m_parent)
+      {
+        // If m_parent is the top-level scope, there will be no parent
+        // function.
+
+        octave_function *ov_fcn = m_parent->function ();
+
+        if (ov_fcn)
+          m_parent_fcn = octave_value (ov_fcn, true);
+      }
+  }
+
+  void
   symbol_table::scope::update_nest (void)
   {
     if (m_parent)
--- a/libinterp/corefcn/symtab.h	Thu Aug 31 21:10:56 2017 +0200
+++ b/libinterp/corefcn/symtab.h	Fri Sep 08 18:15:50 2017 -0400
@@ -1567,7 +1567,7 @@
 
       scope (const std::string& name = "")
         : m_name (name), m_symbols (), m_persistent_symbols (), m_subfunctions (),
-          m_fcn (nullptr), m_parent (nullptr), m_children (), m_is_nested (false),
+          m_fcn (nullptr), m_parent (nullptr), m_parent_fcn (), m_children (), m_is_nested (false),
           m_is_static (false), m_context (0)
       { }
 
@@ -1593,6 +1593,7 @@
       void mark_static (void) { m_is_static = true; }
 
       scope * parent_scope (void) const { return m_parent; }
+      octave_value parent_fcn (void) const { return m_parent_fcn; }
 
       scope * dup (void) const
       {
@@ -1602,6 +1603,7 @@
           new_sid->insert_symbol_record (nm_sr.second.dup (new_sid));
 
         new_sid->m_parent = m_parent;
+        new_sid->m_parent_fcn = m_parent_fcn;
 
         return new_sid;
       }
@@ -2034,7 +2036,7 @@
 
       void set_function (octave_user_function *fcn) { m_fcn = fcn; }
 
-      void set_parent (scope *p) { m_parent = p; }
+      void set_parent (scope *p);
 
       void update_nest (void);
 
@@ -2061,6 +2063,7 @@
 
       // Parent of nested function (may be null).
       scope *m_parent;
+      octave_value m_parent_fcn;
 
       // Child nested functions.
       std::vector<scope*> m_children;