changeset 23753:c3828bd031cd

move profiler inside evaluator and inside octave namespace * interpreter.h, interpreter.cc (interpreter::get_profiler): New function. * pt-eval.h, pt-eval.cc (tree_evaluator::m_profiler): New data member. (tree_evaluator::get_profiler): New function. * profiler.h, profiler.cc (profiler): Delete global variable. (class profiler): Rename from profile_data_accumulator. Move inside octave namespace. Change all uses.
author John W. Eaton <jwe@octave.org>
date Sat, 08 Jul 2017 10:33:07 -0400
parents 6be1bf9455e3
children afe45e9ff6b0
files libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/octave-value/ov-builtin.cc libinterp/octave-value/ov-mex-fcn.cc libinterp/octave-value/ov-usr-fcn.cc libinterp/parse-tree/profiler.cc libinterp/parse-tree/profiler.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h
diffstat 9 files changed, 511 insertions(+), 487 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/interpreter.cc	Sat Jul 08 10:14:32 2017 -0400
+++ b/libinterp/corefcn/interpreter.cc	Sat Jul 08 10:33:07 2017 -0400
@@ -1202,6 +1202,11 @@
     return m_evaluator.get_call_stack ();
   }
 
+  profiler& interpreter::get_profiler (void)
+  {
+    return m_evaluator.get_profiler ();
+  }
+
   void interpreter::mlock (void)
   {
     call_stack& cs = get_call_stack ();
--- a/libinterp/corefcn/interpreter.h	Sat Jul 08 10:14:32 2017 -0400
+++ b/libinterp/corefcn/interpreter.h	Sat Jul 08 10:33:07 2017 -0400
@@ -51,6 +51,7 @@
 
 namespace octave
 {
+  class profiler;
   class call_stack;
   class tree_evaluator;
 
@@ -171,6 +172,8 @@
 
     call_stack& get_call_stack (void);
 
+    profiler& get_profiler (void);
+
     tree_evaluator& get_evaluator (void);
 
     stream_list& get_stream_list (void);
--- a/libinterp/octave-value/ov-builtin.cc	Sat Jul 08 10:14:32 2017 -0400
+++ b/libinterp/octave-value/ov-builtin.cc	Sat Jul 08 10:33:07 2017 -0400
@@ -41,7 +41,7 @@
                                      "built-in function");
 
 octave_value_list
-octave_builtin::call (octave::tree_evaluator&, int nargout,
+octave_builtin::call (octave::tree_evaluator& tw, int nargout,
                       const octave_value_list& args)
 {
   octave_value_list retval;
@@ -57,7 +57,9 @@
 
   frame.add_method (cs, &octave::call_stack::pop);
 
-  profile_data_accumulator::enter<octave_builtin> block (profiler, *this);
+  octave::profiler& profiler = tw.get_profiler ();
+
+  octave::profiler::enter<octave_builtin> block (profiler, *this);
 
   if (f)
     retval = (*f) (args, nargout);
--- a/libinterp/octave-value/ov-mex-fcn.cc	Sat Jul 08 10:14:32 2017 -0400
+++ b/libinterp/octave-value/ov-mex-fcn.cc	Sat Jul 08 10:33:07 2017 -0400
@@ -88,7 +88,7 @@
           int nargout);
 
 octave_value_list
-octave_mex_function::call (octave::tree_evaluator&, int nargout,
+octave_mex_function::call (octave::tree_evaluator& tw, int nargout,
                            const octave_value_list& args)
 {
   octave_value_list retval;
@@ -105,7 +105,9 @@
 
   frame.add_method (cs, &octave::call_stack::pop);
 
-  profile_data_accumulator::enter<octave_mex_function> block (profiler, *this);
+  octave::profiler& profiler = tw.get_profiler ();
+
+  octave::profiler::enter<octave_mex_function> block (profiler, *this);
 
   retval = call_mex (*this, args, nargout);
 
--- a/libinterp/octave-value/ov-usr-fcn.cc	Sat Jul 08 10:14:32 2017 -0400
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Sat Jul 08 10:33:07 2017 -0400
@@ -200,8 +200,9 @@
       frame.protect_var (octave::tree_evaluator::statement_context);
       octave::tree_evaluator::statement_context = octave::tree_evaluator::script;
 
-      profile_data_accumulator::enter<octave_user_script>
-        block (profiler, *this);
+      octave::profiler& profiler = tw.get_profiler ();
+
+      octave::profiler::enter<octave_user_script> block (profiler, *this);
 
       if (tw.echo ())
         tw.push_echo_state (frame, octave::tree_evaluator::ECHO_SCRIPTS,
@@ -616,8 +617,9 @@
   octave::tree_evaluator::statement_context = octave::tree_evaluator::function;
 
   {
-    profile_data_accumulator::enter<octave_user_function>
-      block (profiler, *this);
+    octave::profiler& profiler = tw.get_profiler ();
+
+    octave::profiler::enter<octave_user_function> block (profiler, *this);
 
     if (tw.echo ())
       tw.push_echo_state (frame, octave::tree_evaluator::ECHO_FUNCTIONS,
--- a/libinterp/parse-tree/profiler.cc	Sat Jul 08 10:14:32 2017 -0400
+++ b/libinterp/parse-tree/profiler.cc	Sat Jul 08 10:33:07 2017 -0400
@@ -28,361 +28,363 @@
 #include <iostream>
 
 #include "defun.h"
+#include "interpreter.h"
 #include "oct-time.h"
 #include "ov-struct.h"
 #include "pager.h"
 #include "profiler.h"
 
-profile_data_accumulator::stats::stats ()
-  : time (0.0), calls (0), recursive (false),
-    parents (), children ()
-{ }
-
-octave_value
-profile_data_accumulator::stats::function_set_value (const function_set& list)
+namespace octave
 {
-  const octave_idx_type n = list.size ();
+  profiler::stats::stats ()
+    : time (0.0), calls (0), recursive (false),
+      parents (), children ()
+  { }
+
+  octave_value
+  profiler::stats::function_set_value (const function_set& list)
+  {
+    const octave_idx_type n = list.size ();
+
+    RowVector retval (n);
+    octave_idx_type i = 0;
+    for (const auto& nm : list)
+      retval(i++) = nm;
+
+    assert (i == n);
 
-  RowVector retval (n);
-  octave_idx_type i = 0;
-  for (const auto& nm : list)
-    retval(i++) = nm;
+    return retval;
+  }
+
+  profiler::tree_node::tree_node (tree_node *p, octave_idx_type f)
+    : parent (p), fcn_id (f), children (), time (0.0), calls (0)
+  { }
 
-  assert (i == n);
+  profiler::tree_node::~tree_node ()
+  {
+    for (auto& idx_tnode : children)
+      delete idx_tnode.second;
+  }
+
+  profiler::tree_node*
+  profiler::tree_node::enter (octave_idx_type fcn)
+  {
+    tree_node *retval;
 
-  return retval;
-}
+    child_map::iterator pos = children.find (fcn);
+    if (pos == children.end ())
+      {
+        retval = new tree_node (this, fcn);
+        children[fcn] = retval;
+      }
+    else
+      retval = pos->second;
 
-profile_data_accumulator::tree_node::tree_node (tree_node *p, octave_idx_type f)
-  : parent (p), fcn_id (f), children (), time (0.0), calls (0)
-{ }
+    ++retval->calls;
+    return retval;
+  }
+
+  profiler::tree_node*
+  profiler::tree_node::exit (octave_idx_type /* fcn */)
+  {
+    // FIXME: These assert statements don't make sense if profile() is called
+    //        from within a function hierarchy to begin with.  See bug #39587.
+    //  assert (parent);
+    //  assert (fcn_id == fcn);
 
-profile_data_accumulator::tree_node::~tree_node ()
-{
-  for (auto& idx_tnode : children)
-    delete idx_tnode.second;
-}
+    return parent;
+  }
 
-profile_data_accumulator::tree_node*
-profile_data_accumulator::tree_node::enter (octave_idx_type fcn)
-{
-  tree_node *retval;
+  void
+  profiler::tree_node::build_flat (flat_profile& data) const
+  {
+    // If this is not the top-level node, update profile entry for this function.
+    if (fcn_id != 0)
+      {
+        stats& entry = data[fcn_id - 1];
+
+        entry.time += time;
+        entry.calls += calls;
+
+        assert (parent);
+        if (parent->fcn_id != 0)
+          {
+            entry.parents.insert (parent->fcn_id);
+            data[parent->fcn_id - 1].children.insert (fcn_id);
+          }
 
-  child_map::iterator pos = children.find (fcn);
-  if (pos == children.end ())
-    {
-      retval = new tree_node (this, fcn);
-      children[fcn] = retval;
-    }
-  else
-    retval = pos->second;
+        if (! entry.recursive)
+          for (const tree_node *i = parent; i; i = i->parent)
+            if (i->fcn_id == fcn_id)
+              {
+                entry.recursive = true;
+                break;
+              }
+      }
+
+    // Recurse on children.
+    for (const auto& idx_tnode : children)
+      idx_tnode.second->build_flat (data);
+  }
 
-  ++retval->calls;
-  return retval;
-}
+  octave_value
+  profiler::tree_node::get_hierarchical (double *total) const
+  {
+    // Note that we don't generate the entry just for this node, but
+    // rather a struct-array with entries for all children.  This way, the
+    // top-node (for which we don't want a real entry) generates already
+    // the final hierarchical profile data.
+
+    const octave_idx_type n = children.size ();
+
+    Cell rv_indices (n, 1);
+    Cell rv_times (n, 1);
+    Cell rv_totals (n, 1);
+    Cell rv_calls (n, 1);
+    Cell rv_children (n, 1);
+
+    octave_idx_type i = 0;
+    for (const auto& idx_tnode : children)
+      {
+        const tree_node& entry = *idx_tnode.second;
+        double child_total = entry.time;
+
+        rv_indices(i) = octave_value (idx_tnode.first);
+        rv_times(i) = octave_value (entry.time);
+        rv_calls(i) = octave_value (entry.calls);
+        rv_children(i) = entry.get_hierarchical (&child_total);
+        rv_totals(i) = octave_value (child_total);
 
-profile_data_accumulator::tree_node*
-profile_data_accumulator::tree_node::exit (octave_idx_type /* fcn */)
-{
-  // FIXME: These assert statements don't make sense if profile() is called
-  //        from within a function hierarchy to begin with.  See bug #39587.
-  //  assert (parent);
-  //  assert (fcn_id == fcn);
+        if (total)
+          *total += child_total;
+
+        ++i;
+      }
+    assert (i == n);
+
+    octave_map retval;
 
-  return parent;
-}
+    retval.assign ("Index", rv_indices);
+    retval.assign ("SelfTime", rv_times);
+    retval.assign ("TotalTime", rv_totals);
+    retval.assign ("NumCalls", rv_calls);
+    retval.assign ("Children", rv_children);
+
+    return retval;
+  }
 
-void
-profile_data_accumulator::tree_node::build_flat (flat_profile& data) const
-{
-  // If this is not the top-level node, update profile entry for this function.
-  if (fcn_id != 0)
-    {
-      stats& entry = data[fcn_id - 1];
+  profiler::profiler (void)
+    : known_functions (), fcn_index (),
+      enabled (false), call_tree (new tree_node (0, 0)),
+      active_fcn (0), last_time (-1.0)
+  { }
+
+  profiler::~profiler (void)
+  {
+    delete call_tree;
+  }
 
-      entry.time += time;
-      entry.calls += calls;
+  void
+  profiler::set_active (bool value)
+  {
+    enabled = value;
+  }
+
+  void
+  profiler::enter_function (const std::string& fcn)
+  {
+    // The enter class will check and only call us if the profiler is active.
+    assert (is_active ());
+    assert (call_tree);
+
+    // If there is already an active function, add to its time before
+    // pushing the new one.
+    if (active_fcn && active_fcn != call_tree)
+      add_current_time ();
 
-      assert (parent);
-      if (parent->fcn_id != 0)
-        {
-          entry.parents.insert (parent->fcn_id);
-          data[parent->fcn_id - 1].children.insert (fcn_id);
-        }
+    // Map the function's name to its index.
+    octave_idx_type fcn_idx;
+    fcn_index_map::iterator pos = fcn_index.find (fcn);
+    if (pos == fcn_index.end ())
+      {
+        known_functions.push_back (fcn);
+        fcn_idx = known_functions.size ();
+        fcn_index[fcn] = fcn_idx;
+      }
+    else
+      fcn_idx = pos->second;
+
+    if (! active_fcn)
+      active_fcn = call_tree;
+
+    active_fcn = active_fcn->enter (fcn_idx);
+
+    last_time = query_time ();
+
+  }
 
-      if (! entry.recursive)
-        for (const tree_node *i = parent; i; i = i->parent)
-          if (i->fcn_id == fcn_id)
-            {
-              entry.recursive = true;
-              break;
-            }
-    }
+  void
+  profiler::exit_function (const std::string& fcn)
+  {
+    if (active_fcn)
+      {
+        assert (call_tree);
+        // FIXME: This assert statements doesn't make sense if profile() is called
+        //        from within a function hierarchy to begin with.  See bug #39587.
+        //assert (active_fcn != call_tree);
+
+        // Usually, if we are disabled this function is not even called.  But the
+        // call disabling the profiler is an exception.  So also check here
+        // and only record the time if enabled.
+        if (is_active ())
+          add_current_time ();
+
+        fcn_index_map::iterator pos = fcn_index.find (fcn);
+        // FIXME: This assert statements doesn't make sense if profile() is called
+        //        from within a function hierarchy to begin with.  See bug #39587.
+        //assert (pos != fcn_index.end ());
+        active_fcn = active_fcn->exit (pos->second);
 
-  // Recurse on children.
-  for (const auto& idx_tnode : children)
-    idx_tnode.second->build_flat (data);
-}
+        // If this was an "inner call", we resume executing the parent function
+        // up the stack.  So note the start-time for this!
+        last_time = query_time ();
+      }
+  }
+
+  void
+  profiler::reset (void)
+  {
+    if (is_active ())
+      error ("Can't reset active profiler.");
+
+    known_functions.clear ();
+    fcn_index.clear ();
+
+    if (call_tree)
+      {
+        delete call_tree;
+        call_tree = new tree_node (0, 0);
+        active_fcn = 0;
+      }
 
-octave_value
-profile_data_accumulator::tree_node::get_hierarchical (double *total) const
-{
-  // Note that we don't generate the entry just for this node, but
-  // rather a struct-array with entries for all children.  This way, the
-  // top-node (for which we don't want a real entry) generates already
-  // the final hierarchical profile data.
+    last_time = -1.0;
+  }
+
+  octave_value
+  profiler::get_flat (void) const
+  {
+    octave_value retval;
+
+    const octave_idx_type n = known_functions.size ();
 
-  const octave_idx_type n = children.size ();
+    flat_profile flat (n);
+
+    if (call_tree)
+      {
+        call_tree->build_flat (flat);
 
-  Cell rv_indices (n, 1);
-  Cell rv_times (n, 1);
-  Cell rv_totals (n, 1);
-  Cell rv_calls (n, 1);
-  Cell rv_children (n, 1);
+        Cell rv_names (n, 1);
+        Cell rv_times (n, 1);
+        Cell rv_calls (n, 1);
+        Cell rv_recursive (n, 1);
+        Cell rv_parents (n, 1);
+        Cell rv_children (n, 1);
 
-  octave_idx_type i = 0;
-  for (const auto& idx_tnode : children)
-    {
-      const tree_node& entry = *idx_tnode.second;
-      double child_total = entry.time;
+        for (octave_idx_type i = 0; i != n; ++i)
+          {
+            rv_names(i) = octave_value (known_functions[i]);
+            rv_times(i) = octave_value (flat[i].time);
+            rv_calls(i) = octave_value (flat[i].calls);
+            rv_recursive(i) = octave_value (flat[i].recursive);
+            rv_parents(i) = stats::function_set_value (flat[i].parents);
+            rv_children(i) = stats::function_set_value (flat[i].children);
+          }
+
+        octave_map m;
+
+        m.assign ("FunctionName", rv_names);
+        m.assign ("TotalTime", rv_times);
+        m.assign ("NumCalls", rv_calls);
+        m.assign ("IsRecursive", rv_recursive);
+        m.assign ("Parents", rv_parents);
+        m.assign ("Children", rv_children);
 
-      rv_indices(i) = octave_value (idx_tnode.first);
-      rv_times(i) = octave_value (entry.time);
-      rv_calls(i) = octave_value (entry.calls);
-      rv_children(i) = entry.get_hierarchical (&child_total);
-      rv_totals(i) = octave_value (child_total);
+        retval = m;
+      }
+    else
+      {
+        static const char *fn[] =
+          {
+            "FunctionName",
+            "TotalTime",
+            "NumCalls",
+            "IsRecursive",
+            "Parents",
+            "Children",
+            0
+          };
 
-      if (total)
-        *total += child_total;
+        static octave_map m (dim_vector (0, 1), string_vector (fn));
 
-      ++i;
-    }
-  assert (i == n);
+        retval = m;
+      }
 
-  octave_map retval;
+    return retval;
+  }
 
-  retval.assign ("Index", rv_indices);
-  retval.assign ("SelfTime", rv_times);
-  retval.assign ("TotalTime", rv_totals);
-  retval.assign ("NumCalls", rv_calls);
-  retval.assign ("Children", rv_children);
+  octave_value
+  profiler::get_hierarchical (void) const
+  {
+    octave_value retval;
 
-  return retval;
-}
+    if (call_tree)
+      retval = call_tree->get_hierarchical ();
+    else
+      {
+        static const char *fn[] =
+          {
+            "Index",
+            "SelfTime",
+            "NumCalls",
+            "Children",
+            0
+          };
+
+        static octave_map m (dim_vector (0, 1), string_vector (fn));
+
+        retval = m;
+      }
 
-profile_data_accumulator::profile_data_accumulator ()
-  : known_functions (), fcn_index (),
-    enabled (false), call_tree (new tree_node (0, 0)),
-    active_fcn (0), last_time (-1.0)
-{ }
+    return retval;
+  }
+
+  double
+  profiler::query_time (void) const
+  {
+    sys::time now;
+
+    // FIXME: is this volatile declaration really needed?
+    // See bug #34210 for additional details.
+    volatile double dnow = now.double_value ();
 
-profile_data_accumulator::~profile_data_accumulator ()
-{
-  delete call_tree;
-}
+    return dnow;
+  }
 
-void
-profile_data_accumulator::set_active (bool value)
-{
-  enabled = value;
+  void
+  profiler::add_current_time (void)
+  {
+    if (active_fcn)
+      {
+        const double t = query_time ();
+
+        active_fcn->add_time (t - last_time);
+      }
+  }
 }
 
-void
-profile_data_accumulator::enter_function (const std::string& fcn)
-{
-  // The enter class will check and only call us if the profiler is active.
-  assert (is_active ());
-  assert (call_tree);
-
-  // If there is already an active function, add to its time before
-  // pushing the new one.
-  if (active_fcn && active_fcn != call_tree)
-    add_current_time ();
-
-  // Map the function's name to its index.
-  octave_idx_type fcn_idx;
-  fcn_index_map::iterator pos = fcn_index.find (fcn);
-  if (pos == fcn_index.end ())
-    {
-      known_functions.push_back (fcn);
-      fcn_idx = known_functions.size ();
-      fcn_index[fcn] = fcn_idx;
-    }
-  else
-    fcn_idx = pos->second;
-
-  if (! active_fcn)
-    active_fcn = call_tree;
-
-  active_fcn = active_fcn->enter (fcn_idx);
-
-  last_time = query_time ();
-
-}
-
-void
-profile_data_accumulator::exit_function (const std::string& fcn)
-{
-  if (active_fcn)
-    {
-      assert (call_tree);
-      // FIXME: This assert statements doesn't make sense if profile() is called
-      //        from within a function hierarchy to begin with.  See bug #39587.
-      //assert (active_fcn != call_tree);
-
-      // Usually, if we are disabled this function is not even called.  But the
-      // call disabling the profiler is an exception.  So also check here
-      // and only record the time if enabled.
-      if (is_active ())
-        add_current_time ();
-
-      fcn_index_map::iterator pos = fcn_index.find (fcn);
-      // FIXME: This assert statements doesn't make sense if profile() is called
-      //        from within a function hierarchy to begin with.  See bug #39587.
-      //assert (pos != fcn_index.end ());
-      active_fcn = active_fcn->exit (pos->second);
-
-      // If this was an "inner call", we resume executing the parent function
-      // up the stack.  So note the start-time for this!
-      last_time = query_time ();
-    }
-}
-
-void
-profile_data_accumulator::reset (void)
-{
-  if (is_active ())
-    error ("Can't reset active profiler.");
-
-  known_functions.clear ();
-  fcn_index.clear ();
-
-  if (call_tree)
-    {
-      delete call_tree;
-      call_tree = new tree_node (0, 0);
-      active_fcn = 0;
-    }
-
-  last_time = -1.0;
-}
-
-octave_value
-profile_data_accumulator::get_flat (void) const
-{
-  octave_value retval;
-
-  const octave_idx_type n = known_functions.size ();
-
-  flat_profile flat (n);
-
-  if (call_tree)
-    {
-      call_tree->build_flat (flat);
-
-      Cell rv_names (n, 1);
-      Cell rv_times (n, 1);
-      Cell rv_calls (n, 1);
-      Cell rv_recursive (n, 1);
-      Cell rv_parents (n, 1);
-      Cell rv_children (n, 1);
-
-      for (octave_idx_type i = 0; i != n; ++i)
-        {
-          rv_names(i) = octave_value (known_functions[i]);
-          rv_times(i) = octave_value (flat[i].time);
-          rv_calls(i) = octave_value (flat[i].calls);
-          rv_recursive(i) = octave_value (flat[i].recursive);
-          rv_parents(i) = stats::function_set_value (flat[i].parents);
-          rv_children(i) = stats::function_set_value (flat[i].children);
-        }
-
-      octave_map m;
-
-      m.assign ("FunctionName", rv_names);
-      m.assign ("TotalTime", rv_times);
-      m.assign ("NumCalls", rv_calls);
-      m.assign ("IsRecursive", rv_recursive);
-      m.assign ("Parents", rv_parents);
-      m.assign ("Children", rv_children);
-
-      retval = m;
-    }
-  else
-    {
-      static const char *fn[] =
-      {
-        "FunctionName",
-        "TotalTime",
-        "NumCalls",
-        "IsRecursive",
-        "Parents",
-        "Children",
-        0
-      };
-
-      static octave_map m (dim_vector (0, 1), string_vector (fn));
-
-      retval = m;
-    }
-
-  return retval;
-}
-
-octave_value
-profile_data_accumulator::get_hierarchical (void) const
-{
-  octave_value retval;
-
-  if (call_tree)
-    retval = call_tree->get_hierarchical ();
-  else
-    {
-      static const char *fn[] =
-      {
-        "Index",
-        "SelfTime",
-        "NumCalls",
-        "Children",
-        0
-      };
-
-      static octave_map m (dim_vector (0, 1), string_vector (fn));
-
-      retval = m;
-    }
-
-  return retval;
-}
-
-double
-profile_data_accumulator::query_time (void) const
-{
-  octave::sys::time now;
-
-  // FIXME: is this volatile declaration really needed?
-  // See bug #34210 for additional details.
-  volatile double dnow = now.double_value ();
-
-  return dnow;
-}
-
-void
-profile_data_accumulator::add_current_time (void)
-{
-  if (active_fcn)
-    {
-      const double t = query_time ();
-
-      active_fcn->add_time (t - last_time);
-    }
-}
-
-profile_data_accumulator profiler;
-
 // Enable or disable the profiler data collection.
-DEFUN (__profiler_enable__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__profiler_enable__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __profiler_enable__ ()
 Undocumented internal function.
 @end deftypefn */)
@@ -392,6 +394,8 @@
   if (nargin > 1)
     print_usage ();
 
+  octave::profiler& profiler = interp.get_profiler ();
+
   if (nargin == 1)
     profiler.set_active (args(0).bool_value ());
 
@@ -399,8 +403,8 @@
 }
 
 // Clear all collected profiling data.
-DEFUN (__profiler_reset__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__profiler_reset__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __profiler_reset__ ()
 Undocumented internal function.
 @end deftypefn */)
@@ -408,14 +412,16 @@
   if (args.length () != 0)
     print_usage ();
 
+  octave::profiler& profiler = interp.get_profiler ();
+
   profiler.reset ();
 
   return ovl ();
 }
 
 // Query the timings collected by the profiler.
-DEFUN (__profiler_data__, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__profiler_data__, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __profiler_data__ ()
 Undocumented internal function.
 @end deftypefn */)
@@ -423,6 +429,8 @@
   if (args.length () != 0)
     print_usage ();
 
+  octave::profiler& profiler = interp.get_profiler ();
+
   if (nargout > 1)
     return ovl (profiler.get_flat (), profiler.get_hierarchical ());
   else
--- a/libinterp/parse-tree/profiler.h	Sat Jul 08 10:14:32 2017 -0400
+++ b/libinterp/parse-tree/profiler.h	Sat Jul 08 10:33:07 2017 -0400
@@ -34,182 +34,181 @@
 
 class octave_value;
 
-class
-OCTINTERP_API
-profile_data_accumulator
+namespace octave
 {
-public:
-
-  // This is a utility class that can be used to call the enter/exit
-  // functions in a manner protected from stack unwinding.
-  template <typename T> class enter
+  class
+  OCTINTERP_API
+  profiler
   {
-  private:
-
-    profile_data_accumulator& acc;
-    std::string fcn;
-    bool is_active;
-
   public:
 
-    enter (profile_data_accumulator& a, const T& t) : acc (a)
+    // This is a utility class that can be used to call the enter/exit
+    // functions in a manner protected from stack unwinding.
+    template <typename T> class enter
     {
-      // A profiling block cannot be active if the profiler is not
-      is_active = acc.is_active ();
+    private:
+
+      profiler& m_profiler;
+      std::string fcn;
+      bool is_active;
+
+    public:
 
-      if (is_active)
-        {
-          fcn = t.profiler_name ();
+      enter (profiler& p, const T& t) : m_profiler (p)
+      {
+        // A profiling block cannot be active if the profiler is not
+        is_active = m_profiler.is_active ();
+
+        if (is_active)
+          {
+            fcn = t.profiler_name ();
 
-          // NOTE: The test f != "" must be kept to prevent a blank line showing
-          //  up in profiler statistics.  See bug #39524.  The root cause is that
-          //  the function name is not set for the recurring readline hook function.
-          if (fcn == "")
-            is_active = false;  // Inactive profiling block
-          else
-            acc.enter_function (fcn);
-        }
-    }
+            // NOTE: The test f != "" must be kept to prevent a blank line showing
+            //  up in profiler statistics.  See bug #39524.  The root cause is that
+            //  the function name is not set for the recurring readline hook function.
+            if (fcn == "")
+              is_active = false;  // Inactive profiling block
+            else
+              m_profiler.enter_function (fcn);
+          }
+      }
+
+      // No copying!
+
+      enter (const enter&) = delete;
+
+      enter& operator = (const enter&) = delete;
+
+      ~enter (void)
+      {
+        if (is_active)
+          m_profiler.exit_function (fcn);
+      }
+    };
+
+    profiler (void);
 
     // No copying!
 
-    enter (const enter&) = delete;
-
-    enter& operator = (const enter&) = delete;
-
-    ~enter ()
-    {
-      if (is_active)
-        acc.exit_function (fcn);
-    }
-  };
-
-  profile_data_accumulator (void);
-
-  // No copying!
-
-  profile_data_accumulator (const profile_data_accumulator&) = delete;
-
-  profile_data_accumulator&
-  operator = (const profile_data_accumulator&) = delete;
+    profiler (const profiler&) = delete;
 
-  virtual ~profile_data_accumulator ();
-
-  bool is_active (void) const { return enabled; }
-  void set_active (bool);
-
-  void reset (void);
-
-  octave_value get_flat (void) const;
-  octave_value get_hierarchical (void) const;
+    profiler& operator = (const profiler&) = delete;
 
-private:
-
-  // One entry in the flat profile (i.e., a collection of data for a single
-  // function).  This is filled in when building the flat profile from the
-  // hierarchical call tree.
-  struct stats
-  {
-    stats ();
-
-    double time;
-    unsigned calls;
+    virtual ~profiler (void);
 
-    bool recursive;
-
-    typedef std::set<octave_idx_type> function_set;
-    function_set parents;
-    function_set children;
-
-    // Convert a function_set list to an Octave array of indices.
-    static octave_value function_set_value (const function_set&);
-  };
-
-  typedef std::vector<stats> flat_profile;
-
-  // Store data for one node in the call-tree of the hierarchical profiler
-  // data we collect.
-  class tree_node
-  {
-  public:
-
-    tree_node (tree_node*, octave_idx_type);
-    virtual ~tree_node ();
+    bool is_active (void) const { return enabled; }
+    void set_active (bool);
 
-    // No copying!
-
-    tree_node (const tree_node&) = delete;
-
-    tree_node& operator = (const tree_node&) = delete;
-
-    void add_time (double dt) { time += dt; }
-
-    // Enter a child function.  It is created in the list of children if it
-    // wasn't already there.  The now-active child node is returned.
-    tree_node *enter (octave_idx_type);
+    void reset (void);
 
-    // Exit function.  As a sanity-check, it is verified that the currently
-    // active function actually is the one handed in here.  Returned is the
-    // then-active node, which is our parent.
-    tree_node *exit (octave_idx_type);
-
-    void build_flat (flat_profile&) const;
-
-    // Get the hierarchical profile for this node and its children.  If total
-    // is set, accumulate total time of the subtree in that variable as
-    // additional return value.
-    octave_value get_hierarchical (double *total = nullptr) const;
+    octave_value get_flat (void) const;
+    octave_value get_hierarchical (void) const;
 
   private:
 
-    tree_node *parent;
-    octave_idx_type fcn_id;
+    // One entry in the flat profile (i.e., a collection of data for a single
+    // function).  This is filled in when building the flat profile from the
+    // hierarchical call tree.
+    struct stats
+    {
+      stats (void);
 
-    typedef std::map<octave_idx_type, tree_node*> child_map;
-    child_map children;
+      double time;
+      unsigned calls;
 
-    // This is only time spent *directly* on this level, excluding children!
-    double time;
+      bool recursive;
+
+      typedef std::set<octave_idx_type> function_set;
+      function_set parents;
+      function_set children;
 
-    unsigned calls;
-  };
+      // Convert a function_set list to an Octave array of indices.
+      static octave_value function_set_value (const function_set&);
+    };
+
+    typedef std::vector<stats> flat_profile;
 
-  // Each function we see in the profiler is given a unique index (which
-  // simply counts starting from 1).  We thus have to map profiler-names to
-  // those indices.  For all other stuff, we identify functions by their index.
+    // Store data for one node in the call-tree of the hierarchical profiler
+    // data we collect.
+    class tree_node
+    {
+    public:
+
+      tree_node (tree_node*, octave_idx_type);
+      virtual ~tree_node (void);
+
+      // No copying!
+
+      tree_node (const tree_node&) = delete;
 
-  typedef std::vector<std::string> function_set;
-  typedef std::map<std::string, octave_idx_type> fcn_index_map;
+      tree_node& operator = (const tree_node&) = delete;
+
+      void add_time (double dt) { time += dt; }
 
-  function_set known_functions;
-  fcn_index_map fcn_index;
+      // Enter a child function.  It is created in the list of children if it
+      // wasn't already there.  The now-active child node is returned.
+      tree_node *enter (octave_idx_type);
 
-  bool enabled;
+      // Exit function.  As a sanity-check, it is verified that the currently
+      // active function actually is the one handed in here.  Returned is the
+      // then-active node, which is our parent.
+      tree_node *exit (octave_idx_type);
+
+      void build_flat (flat_profile&) const;
 
-  tree_node *call_tree;
-  tree_node *active_fcn;
+      // Get the hierarchical profile for this node and its children.  If total
+      // is set, accumulate total time of the subtree in that variable as
+      // additional return value.
+      octave_value get_hierarchical (double *total = nullptr) const;
+
+    private:
+
+      tree_node *parent;
+      octave_idx_type fcn_id;
+
+      typedef std::map<octave_idx_type, tree_node*> child_map;
+      child_map children;
 
-  // Store last timestamp we had, when the currently active function was called.
-  double last_time;
+      // This is only time spent *directly* on this level, excluding children!
+      double time;
+
+      unsigned calls;
+    };
 
-  // These are private as only the unwind-protecting inner class enter
-  // should be allowed to call them.
-  void enter_function (const std::string&);
-  void exit_function (const std::string&);
+    // Each function we see in the profiler is given a unique index (which
+    // simply counts starting from 1).  We thus have to map profiler-names to
+    // those indices.  For all other stuff, we identify functions by their index.
+
+    typedef std::vector<std::string> function_set;
+    typedef std::map<std::string, octave_idx_type> fcn_index_map;
 
-  // Query a timestamp, used for timing calls (obviously).
-  // This is not static because in the future, maybe we want a flag
-  // in the profiler or something to choose between cputime, wall-time,
-  // user-time, system-time, ...
-  double query_time () const;
+    function_set known_functions;
+    fcn_index_map fcn_index;
+
+    bool enabled;
+
+    tree_node *call_tree;
+    tree_node *active_fcn;
+
+    // Store last timestamp we had, when the currently active function was called.
+    double last_time;
 
-  // Add the time elapsed since last_time to the function we're currently in.
-  // This is called from two different positions, thus it is useful to have
-  // it as a seperate function.
-  void add_current_time (void);
-};
+    // These are private as only the unwind-protecting inner class enter
+    // should be allowed to call them.
+    void enter_function (const std::string&);
+    void exit_function (const std::string&);
 
-// The instance used.
-extern OCTINTERP_API profile_data_accumulator profiler;
+    // Query a timestamp, used for timing calls (obviously).
+    // This is not static because in the future, maybe we want a flag
+    // in the profiler or something to choose between cputime, wall-time,
+    // user-time, system-time, ...
+    double query_time (void) const;
+
+    // Add the time elapsed since last_time to the function we're currently in.
+    // This is called from two different positions, thus it is useful to have
+    // it as a seperate function.
+    void add_current_time (void);
+  };
+}
 
 #endif
--- a/libinterp/parse-tree/pt-eval.cc	Sat Jul 08 10:14:32 2017 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Sat Jul 08 10:33:07 2017 -0400
@@ -220,8 +220,8 @@
 
             if (b.is_defined ())
               {
-                profile_data_accumulator::enter<tree_binary_expression>
-                  block (profiler, expr);
+                profiler::enter<tree_binary_expression>
+                  block (m_profiler, expr);
 
                 // Note: The profiler does not catch the braindead
                 // short-circuit evaluation code above, but that should be
@@ -1969,8 +1969,7 @@
 
             val = ref.value ();
 
-            profile_data_accumulator::enter<tree_postfix_expression>
-              block (profiler, expr);
+            profiler::enter<tree_postfix_expression> block (m_profiler, expr);
 
             ref.do_unary_op (etype);
           }
@@ -1980,8 +1979,8 @@
 
             if (op_val.is_defined ())
               {
-                profile_data_accumulator::enter<tree_postfix_expression>
-                  block (profiler, expr);
+                profiler::enter<tree_postfix_expression>
+                  block (m_profiler, expr);
 
                 val = ::do_unary_op (etype, op_val);
               }
@@ -2006,8 +2005,7 @@
           {
             octave_lvalue op_ref = op->lvalue (this);
 
-            profile_data_accumulator::enter<tree_prefix_expression>
-              block (profiler, expr);
+            profiler::enter<tree_prefix_expression> block (m_profiler, expr);
 
             op_ref.do_unary_op (etype);
 
@@ -2019,8 +2017,8 @@
 
             if (op_val.is_defined ())
               {
-                profile_data_accumulator::enter<tree_prefix_expression>
-                  block (profiler, expr);
+                profiler::enter<tree_prefix_expression>
+                  block (m_profiler, expr);
 
                 // Attempt to do the operation in-place if it is unshared
                 // (a temporary expression).
--- a/libinterp/parse-tree/pt-eval.h	Sat Jul 08 10:14:32 2017 -0400
+++ b/libinterp/parse-tree/pt-eval.h	Sat Jul 08 10:33:07 2017 -0400
@@ -32,6 +32,7 @@
 
 #include "call-stack.h"
 #include "ovl.h"
+#include "profiler.h"
 #include "pt-exp.h"
 #include "pt-walk.h"
 
@@ -114,7 +115,7 @@
 
     tree_evaluator (interpreter& interp)
       : m_interpreter (interp), m_value_stack (), m_lvalue_list_stack (),
-        m_nargout_stack (), m_call_stack (interp),
+        m_nargout_stack (), m_call_stack (interp), m_profiler (),
         m_max_recursion_depth (256), m_silent_functions (false),
         m_string_fill_char (' '), m_PS4 ("+ "), m_echo (ECHO_OFF),
         m_echo_state (false), m_echo_file_name (), m_echo_file_pos (1),
@@ -309,6 +310,8 @@
 
     call_stack& get_call_stack (void) { return m_call_stack; }
 
+    profiler& get_profiler (void) { return m_profiler; }
+
     int max_recursion_depth (void) const { return m_max_recursion_depth; }
 
     int max_recursion_depth (int n)
@@ -426,6 +429,8 @@
 
     call_stack m_call_stack;
 
+    profiler m_profiler;
+
     // Maximum nesting level for functions, scripts, or sourced files
     // called recursively.
     int m_max_recursion_depth;