diff libinterp/parse-tree/pt-unop.cc @ 27371:fcaecdbc8d8a

don't use visitor pattern for expression evaluation (bug #56752) Although it is desirable to have all parse tree evaluation functions grouped together in a single file, using the visitor pattern can be inefficient, especially when the visitor function is small and the extra levels of indirection and virtual function resolution can take more time than the evaluation function itself (evaluation of constants, for example). For all classes derived from tree_expression, introduce new evaluate and evaluate_n methods. Use those instead of visit_CLASS functions to perform expression evaluation. Results are now returned directly from the evaluation functions instead of storing them in the tree_evaluator object. Files affected: cdef-class.cc, oct-parse.yy, pt-assign.cc, pt-assign.h, pt-binop.cc, pt-binop.h, pt-cbinop.cc, pt-cbinop.h, pt-cell.cc, pt-cell.h, pt-classdef.cc, pt-classdef.h, pt-colon.cc, pt-colon.h, pt-const.h, pt-eval.cc, pt-eval.h, pt-exp.h, pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-loop.cc, pt-mat.cc, pt-mat.h, pt-select.cc, pt-tm-const.cc, pt-unop.cc, and pt-unop.h.
author John W. Eaton <jwe@octave.org>
date Fri, 30 Aug 2019 15:02:14 -0400
parents 00f796120a6d
children d171d356767b
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-unop.cc	Wed Aug 28 21:38:34 2019 -0400
+++ b/libinterp/parse-tree/pt-unop.cc	Fri Aug 30 15:02:14 2019 -0400
@@ -24,7 +24,9 @@
 #  include "config.h"
 #endif
 
+#include "interpreter.h"
 #include "ov.h"
+#include "profiler.h"
 #include "pt-unop.h"
 
 namespace octave
@@ -51,6 +53,53 @@
     return new_pe;
   }
 
+  octave_value
+  tree_prefix_expression::evaluate (tree_evaluator& tw, int)
+  {
+    octave_value val;
+
+    if (m_op)
+      {
+        if (m_etype == octave_value::op_incr
+            || m_etype == octave_value::op_decr)
+          {
+            octave_lvalue op_ref = m_op->lvalue (tw);
+
+            profiler::enter<tree_prefix_expression>
+              block (tw.get_profiler (), *this);
+
+            op_ref.do_unary_op (m_etype);
+
+            val = op_ref.value ();
+          }
+        else
+          {
+            octave_value op_val = std::move (m_op->evaluate (tw));
+
+            if (op_val.is_defined ())
+              {
+                profiler::enter<tree_prefix_expression>
+                  block (tw.get_profiler (), *this);
+
+                // Attempt to do the operation in-place if it is unshared
+                // (a temporary expression).
+                if (op_val.get_count () == 1)
+                  val = op_val.do_non_const_unary_op (m_etype);
+                else
+                  {
+                    interpreter& interp = tw.get_interpreter ();
+
+                    type_info& ti = interp.get_type_info ();
+
+                    val = ::do_unary_op (ti, m_etype, op_val);
+                  }
+              }
+          }
+      }
+
+    return val;
+  }
+
   // Postfix expressions.
 
   tree_expression *
@@ -64,4 +113,44 @@
 
     return new_pe;
   }
+
+  octave_value
+  tree_postfix_expression::evaluate (tree_evaluator& tw, int)
+  {
+    octave_value val;
+
+    if (m_op)
+      {
+        if (m_etype == octave_value::op_incr
+            || m_etype == octave_value::op_decr)
+          {
+            octave_lvalue ref = m_op->lvalue (tw);
+
+            val = ref.value ();
+
+            profiler::enter<tree_postfix_expression>
+              block (tw.get_profiler (), *this);
+
+            ref.do_unary_op (m_etype);
+          }
+        else
+          {
+            octave_value op_val = std::move (m_op->evaluate (tw));
+
+            if (op_val.is_defined ())
+              {
+                profiler::enter<tree_postfix_expression>
+                  block (tw.get_profiler (), *this);
+
+                interpreter& interp = tw.get_interpreter ();
+
+                type_info& ti = interp.get_type_info ();
+
+                val = ::do_unary_op (ti, m_etype, op_val);
+              }
+          }
+      }
+
+    return val;
+  }
 }