# HG changeset patch
# User Julien Bect <julien.bect@supelec.fr>
# Date 1403541992 -7200
#      lun. juin 23 18:46:32 2014 +0200
# Node ID 1bd6ef7acce4ac8e8113500a7118e44a52108078
# Parent  1773d68e09a6f6fd17dbe2a55aa0699615ee8034
Reduce profiling overhead using inlining and templates.

diff -r 1773d68e09a6 -r 1bd6ef7acce4 libinterp/corefcn/profiler.cc
--- a/libinterp/corefcn/profiler.cc	lun. oct. 13 11:58:18 2014 +0200
+++ b/libinterp/corefcn/profiler.cc	lun. juin 23 18:46:32 2014 +0200
@@ -32,29 +32,6 @@
 #include "pager.h"
 #include "profiler.h"
 
-profile_data_accumulator::enter::enter (profile_data_accumulator& a,
-                                        const std::string& f)
-  : acc (a)
-{
-  // FIXME: Add test for f != "" 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 (acc.is_active () && f != "")
-    {
-      fcn = f;
-      acc.enter_function (fcn);
-    }
-  else
-    fcn = "";
-}
-
-profile_data_accumulator::enter::~enter ()
-{
-  if (fcn != "")
-    acc.exit_function (fcn);
-}
-
 profile_data_accumulator::stats::stats ()
   : time (0.0), calls (0), recursive (false),
     parents (), children ()
diff -r 1773d68e09a6 -r 1bd6ef7acce4 libinterp/corefcn/profiler.h
--- a/libinterp/corefcn/profiler.h	lun. oct. 13 11:58:18 2014 +0200
+++ b/libinterp/corefcn/profiler.h	lun. juin 23 18:46:32 2014 +0200
@@ -39,17 +39,40 @@
 
   // This is a utility class that can be used to call the enter/exit
   // functions in a manner protected from stack unwinding.
-  class enter
+  template<class T> class enter
   {
   private:
 
     profile_data_accumulator& acc;
     std::string fcn;
+    bool is_active;
 
   public:
 
-    enter (profile_data_accumulator&, const std::string&);
-    virtual ~enter (void);
+    enter (profile_data_accumulator& a, const T& t) : acc (a)
+    {
+      // Profiling block cannot be active if the profiler is not
+      is_active = acc.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);
+        }
+    }
+
+    ~enter ()
+    {
+      if (is_active)
+	acc.exit_function (fcn);
+    }
 
   private:
 
@@ -181,10 +204,12 @@
 extern OCTINTERP_API profile_data_accumulator profiler;
 
 // Helper macro to profile a block of code.
-#define BEGIN_PROFILER_BLOCK(name) \
+
+#define BEGIN_PROFILER_BLOCK(classname)	\
   { \
-    profile_data_accumulator::enter pe (profiler, (name));
+    profile_data_accumulator::enter<classname> pe (profiler, *this)
+
 #define END_PROFILER_BLOCK \
-  }
+  }  // end of block => call pe's destructor
 
 #endif
diff -r 1773d68e09a6 -r 1bd6ef7acce4 libinterp/octave-value/ov-builtin.cc
--- a/libinterp/octave-value/ov-builtin.cc	lun. oct. 13 11:58:18 2014 +0200
+++ b/libinterp/octave-value/ov-builtin.cc	lun. juin 23 18:46:32 2014 +0200
@@ -127,7 +127,7 @@
 
       try
         {
-          BEGIN_PROFILER_BLOCK (profiler_name ())
+          BEGIN_PROFILER_BLOCK (octave_builtin);
 
           retval = (*f) (args, nargout);
           // Do not allow null values to be returned from functions.
@@ -142,7 +142,7 @@
           if (retval.length () == 1 && retval.xelem (0).is_undefined ())
             retval.clear ();
 
-          END_PROFILER_BLOCK
+          END_PROFILER_BLOCK;
         }
       catch (octave_execution_exception)
         {
diff -r 1773d68e09a6 -r 1bd6ef7acce4 libinterp/octave-value/ov-mex-fcn.cc
--- a/libinterp/octave-value/ov-mex-fcn.cc	lun. oct. 13 11:58:18 2014 +0200
+++ b/libinterp/octave-value/ov-mex-fcn.cc	lun. juin 23 18:46:32 2014 +0200
@@ -148,9 +148,11 @@
 
       try
         {
-          BEGIN_PROFILER_BLOCK (profiler_name ())
+          BEGIN_PROFILER_BLOCK (octave_mex_function);
+
           retval = call_mex (have_fmex, mex_fcn_ptr, args, nargout, this);
-          END_PROFILER_BLOCK
+
+          END_PROFILER_BLOCK;
         }
       catch (octave_execution_exception)
         {
diff -r 1773d68e09a6 -r 1bd6ef7acce4 libinterp/octave-value/ov-usr-fcn.cc
--- a/libinterp/octave-value/ov-usr-fcn.cc	lun. oct. 13 11:58:18 2014 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.cc	lun. juin 23 18:46:32 2014 +0200
@@ -149,9 +149,11 @@
                   frame.protect_var (tree_evaluator::statement_context);
                   tree_evaluator::statement_context = tree_evaluator::script;
 
-                  BEGIN_PROFILER_BLOCK (profiler_name ())
+                  BEGIN_PROFILER_BLOCK (octave_user_script);
+
                   cmd_list->accept (*current_evaluator);
-                  END_PROFILER_BLOCK
+
+                  END_PROFILER_BLOCK;
 
                   if (tree_return_command::returning)
                     tree_return_command::returning = 0;
@@ -614,7 +616,7 @@
   frame.protect_var (tree_evaluator::statement_context);
   tree_evaluator::statement_context = tree_evaluator::function;
 
-  BEGIN_PROFILER_BLOCK (profiler_name ())
+  BEGIN_PROFILER_BLOCK (octave_user_function);
 
   if (is_special_expr ())
     {
@@ -628,7 +630,7 @@
   else
     cmd_list->accept (*current_evaluator);
 
-  END_PROFILER_BLOCK
+  END_PROFILER_BLOCK;
 
   if (echo_commands)
     print_code_function_trailer ();
diff -r 1773d68e09a6 -r 1bd6ef7acce4 libinterp/parse-tree/pt-binop.cc
--- a/libinterp/parse-tree/pt-binop.cc	lun. oct. 13 11:58:18 2014 +0200
+++ b/libinterp/parse-tree/pt-binop.cc	lun. juin 23 18:46:32 2014 +0200
@@ -135,7 +135,7 @@
 
           if (! error_state && b.is_defined ())
             {
-              BEGIN_PROFILER_BLOCK ("binary " + oper ())
+              BEGIN_PROFILER_BLOCK (tree_binary_expression);
 
               // Note: The profiler does not catch the braindead
               // short-circuit evaluation code above, but that should be
@@ -148,7 +148,7 @@
               if (error_state)
                 retval = octave_value ();
 
-              END_PROFILER_BLOCK
+              END_PROFILER_BLOCK;
             }
         }
     }
diff -r 1773d68e09a6 -r 1bd6ef7acce4 libinterp/parse-tree/pt-binop.h
--- a/libinterp/parse-tree/pt-binop.h	lun. oct. 13 11:58:18 2014 +0200
+++ b/libinterp/parse-tree/pt-binop.h	lun. juin 23 18:46:32 2014 +0200
@@ -100,6 +100,9 @@
 
   void accept (tree_walker& tw);
 
+  std::string profiler_name (void) const {
+    return "binary " + oper (); }
+
 protected:
 
   // The operands for the expression.
diff -r 1773d68e09a6 -r 1bd6ef7acce4 libinterp/parse-tree/pt-unop.cc
--- a/libinterp/parse-tree/pt-unop.cc	lun. oct. 13 11:58:18 2014 +0200
+++ b/libinterp/parse-tree/pt-unop.cc	lun. juin 23 18:46:32 2014 +0200
@@ -73,14 +73,14 @@
 
           if (! error_state)
             {
-              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
-
+              BEGIN_PROFILER_BLOCK (tree_prefix_expression);
+              
               ref.do_unary_op (etype);
 
               if (! error_state)
                 retval = ref.value ();
 
-              END_PROFILER_BLOCK
+              END_PROFILER_BLOCK;
             }
         }
       else
@@ -89,7 +89,7 @@
 
           if (! error_state && val.is_defined ())
             {
-              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
+              BEGIN_PROFILER_BLOCK (tree_prefix_expression);
 
               // Attempt to do the operation in-place if it is unshared
               // (a temporary expression).
@@ -101,7 +101,7 @@
               if (error_state)
                 retval = octave_value ();
 
-              END_PROFILER_BLOCK
+              END_PROFILER_BLOCK;
             }
         }
     }
@@ -162,9 +162,11 @@
             {
               retval = ref.value ();
 
-              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
+              BEGIN_PROFILER_BLOCK (tree_postfix_expression);
+
               ref.do_unary_op (etype);
-              END_PROFILER_BLOCK
+
+              END_PROFILER_BLOCK;
             }
         }
       else
@@ -173,14 +175,14 @@
 
           if (! error_state && val.is_defined ())
             {
-              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
+              BEGIN_PROFILER_BLOCK (tree_postfix_expression);
 
               retval = ::do_unary_op (etype, val);
 
               if (error_state)
                 retval = octave_value ();
 
-              END_PROFILER_BLOCK
+              END_PROFILER_BLOCK;
             }
         }
     }
diff -r 1773d68e09a6 -r 1bd6ef7acce4 libinterp/parse-tree/pt-unop.h
--- a/libinterp/parse-tree/pt-unop.h	lun. oct. 13 11:58:18 2014 +0200
+++ b/libinterp/parse-tree/pt-unop.h	lun. juin 23 18:46:32 2014 +0200
@@ -108,6 +108,11 @@
 
   void accept (tree_walker& tw);
 
+  std::string profiler_name (void) const
+  {
+    return "prefix " + oper ();
+  }
+
 private:
 
   // No copying!
@@ -145,6 +150,11 @@
 
   void accept (tree_walker& tw);
 
+  std::string profiler_name (void) const
+  {
+    return "postfix " + oper ();
+  }
+
 private:
 
   // No copying!
