# HG changeset patch
# User Petter Tomner <tomner@kth.se>
# Date 1641219736 -3600
#      Mon Jan 03 15:22:16 2022 +0100
# Node ID 47e146d3d15da7da772f057ab4118679df01e08f
# Parent  be202ca69ba9824931787c638d56752bce6f6489
interpreter: Binary op no nil construct. Break out code to separate function.

Avoid unessecary octave_value construction in binary_op ().
Also move some Octave OOP code to a separate function to reduce
function memory footprint.

libinterp/octave-value/ov.cc

diff -r be202ca69ba9 -r 47e146d3d15d libinterp/octave-value/ov.cc
--- a/libinterp/octave-value/ov.cc	Mon Jan 03 02:43:46 2022 +0100
+++ b/libinterp/octave-value/ov.cc	Mon Jan 03 15:22:16 2022 +0100
@@ -2638,29 +2638,129 @@
     error ("type conversion failed for binary operator '%s'", on.c_str ());
   }
 
+  // Helper function for binary_op, to keep the amount of instructions down
+  // in binary_op ()
+  static octave_value binary_op_fcnnotfound (int t1, int t2,
+                                             type_info& ti,
+                                             octave_value::binary_op op,
+                                             const octave_value& v1,
+                                             const octave_value& v2)
+  {
+    octave_value retval;
+    type_info::binary_op_fcn f;
+
+    octave_value tv1;
+    octave_base_value::type_conv_info cf1
+      = v1.numeric_conversion_function ();
+
+    octave_value tv2;
+    octave_base_value::type_conv_info cf2
+      = v2.numeric_conversion_function ();
+
+    // Try biased (one-sided) conversions first.
+    if (cf2.type_id () >= 0
+        && ti.lookup_binary_op (op, t1, cf2.type_id ()))
+      cf1 = nullptr;
+    else if (cf1.type_id () >= 0
+             && ti.lookup_binary_op (op, cf1.type_id (), t2))
+      cf2 = nullptr;
+
+    if (cf1)
+      {
+        octave_base_value *tmp = cf1 (v1.get_rep ());
+
+        if (! tmp)
+          err_binary_op_conv (octave_value::binary_op_as_string (op));
+
+        tv1 = octave_value (tmp);
+        t1 = tv1.type_id ();
+      }
+    else
+      tv1 = v1;
+
+    if (cf2)
+      {
+        octave_base_value *tmp = cf2 (v2.get_rep ());
+
+        if (! tmp)
+          err_binary_op_conv (octave_value::binary_op_as_string (op));
+
+        tv2 = octave_value (tmp);
+        t2 = tv2.type_id ();
+      }
+    else
+      tv2 = v2;
+
+    if (cf1 || cf2)
+      {
+        retval = binary_op (op, tv1, tv2);
+      }
+    else
+      {
+        //demote double -> single and try again
+        cf1 = tv1.numeric_demotion_function ();
+
+        cf2 = tv2.numeric_demotion_function ();
+
+        // Try biased (one-sided) conversions first.
+        if (cf2.type_id () >= 0
+            && ti.lookup_binary_op (op, t1, cf2.type_id ()))
+          cf1 = nullptr;
+        else if (cf1.type_id () >= 0
+                 && ti.lookup_binary_op (op, cf1.type_id (), t2))
+          cf2 = nullptr;
+
+        if (cf1)
+          {
+            octave_base_value *tmp = cf1 (tv1.get_rep ());
+
+            if (! tmp)
+              err_binary_op_conv (octave_value::binary_op_as_string (op));
+
+            tv1 = octave_value (tmp);
+            t1 = tv1.type_id ();
+          }
+
+        if (cf2)
+          {
+            octave_base_value *tmp = cf2 (tv2.get_rep ());
+
+            if (! tmp)
+              err_binary_op_conv (octave_value::binary_op_as_string (op));
+
+            tv2 = octave_value (tmp);
+            t2 = tv2.type_id ();
+          }
+
+        if (! cf1 && ! cf2)
+          err_binary_op (octave_value::binary_op_as_string (op),
+                         v1.type_name (), v2.type_name ());
+
+        f = ti.lookup_binary_op (op, t1, t2);
+
+        if (! f)
+          err_binary_op (octave_value::binary_op_as_string (op),
+                         v1.type_name (), v2.type_name ());
+
+        retval = f (tv1.get_rep (), tv2.get_rep ());
+      }
+
+    return retval;
+  }
+
   octave_value
   binary_op (type_info& ti, octave_value::binary_op op,
              const octave_value& v1, const octave_value& v2)
   {
-    octave_value retval;
-
     int t1 = v1.type_id ();
     int t2 = v2.type_id ();
 
-    if (t1 == octave_class::static_type_id ()
-        || t2 == octave_class::static_type_id ()
-        || t1 == octave_classdef::static_type_id ()
-        || t2 == octave_classdef::static_type_id ())
-      {
-        type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op);
-
-        if (! f)
-          err_binary_op (octave_value::binary_op_as_string (op),
-                         v1.class_name (), v2.class_name ());
-
-        retval = f (v1, v2);
-      }
-    else
+    bool either_is_class = (t1 == octave_class::static_type_id ()
+                            || t2 == octave_class::static_type_id ()
+                            || t1 == octave_classdef::static_type_id ()
+                            || t2 == octave_classdef::static_type_id ());
+
+    if (!either_is_class)
       {
         // FIXME: we need to handle overloading operators for built-in
         // classes (double, char, int8, etc.)
@@ -2669,108 +2769,20 @@
           = ti.lookup_binary_op (op, t1, t2);
 
         if (f)
-          retval = f (v1.get_rep (), v2.get_rep ());
+          return f (v1.get_rep (), v2.get_rep ());
         else
-          {
-            octave_value tv1;
-            octave_base_value::type_conv_info cf1
-              = v1.numeric_conversion_function ();
-
-            octave_value tv2;
-            octave_base_value::type_conv_info cf2
-              = v2.numeric_conversion_function ();
-
-            // Try biased (one-sided) conversions first.
-            if (cf2.type_id () >= 0
-                && ti.lookup_binary_op (op, t1, cf2.type_id ()))
-              cf1 = nullptr;
-            else if (cf1.type_id () >= 0
-                     && ti.lookup_binary_op (op, cf1.type_id (), t2))
-              cf2 = nullptr;
-
-            if (cf1)
-              {
-                octave_base_value *tmp = cf1 (v1.get_rep ());
-
-                if (! tmp)
-                  err_binary_op_conv (octave_value::binary_op_as_string (op));
-
-                tv1 = octave_value (tmp);
-                t1 = tv1.type_id ();
-              }
-            else
-              tv1 = v1;
-
-            if (cf2)
-              {
-                octave_base_value *tmp = cf2 (v2.get_rep ());
-
-                if (! tmp)
-                  err_binary_op_conv (octave_value::binary_op_as_string (op));
-
-                tv2 = octave_value (tmp);
-                t2 = tv2.type_id ();
-              }
-            else
-              tv2 = v2;
-
-            if (cf1 || cf2)
-              {
-                retval = binary_op (op, tv1, tv2);
-              }
-            else
-              {
-                //demote double -> single and try again
-                cf1 = tv1.numeric_demotion_function ();
-
-                cf2 = tv2.numeric_demotion_function ();
-
-                // Try biased (one-sided) conversions first.
-                if (cf2.type_id () >= 0
-                    && ti.lookup_binary_op (op, t1, cf2.type_id ()))
-                  cf1 = nullptr;
-                else if (cf1.type_id () >= 0
-                         && ti.lookup_binary_op (op, cf1.type_id (), t2))
-                  cf2 = nullptr;
-
-                if (cf1)
-                  {
-                    octave_base_value *tmp = cf1 (tv1.get_rep ());
-
-                    if (! tmp)
-                      err_binary_op_conv (octave_value::binary_op_as_string (op));
-
-                    tv1 = octave_value (tmp);
-                    t1 = tv1.type_id ();
-                  }
-
-                if (cf2)
-                  {
-                    octave_base_value *tmp = cf2 (tv2.get_rep ());
-
-                    if (! tmp)
-                      err_binary_op_conv (octave_value::binary_op_as_string (op));
-
-                    tv2 = octave_value (tmp);
-                    t2 = tv2.type_id ();
-                  }
-
-                if (! cf1 && ! cf2)
-                  err_binary_op (octave_value::binary_op_as_string (op),
-                                 v1.type_name (), v2.type_name ());
-
-                f = ti.lookup_binary_op (op, t1, t2);
-
-                if (! f)
-                  err_binary_op (octave_value::binary_op_as_string (op),
-                                 v1.type_name (), v2.type_name ());
-
-                retval = f (tv1.get_rep (), tv2.get_rep ());
-              }
-          }
+          return binary_op_fcnnotfound(t1, t2, ti, op, v1, v2);
       }
-
-    return retval;
+    else
+      {
+        type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op);
+
+        if (! f)
+          err_binary_op (octave_value::binary_op_as_string (op),
+                         v1.class_name (), v2.class_name ());
+
+        return f (v1, v2);
+      }
   }
 
   octave_value
@@ -2837,34 +2849,32 @@
   binary_op (type_info& ti, octave_value::compound_binary_op op,
              const octave_value& v1, const octave_value& v2)
   {
-    octave_value retval;
-
     int t1 = v1.type_id ();
     int t2 = v2.type_id ();
 
-    if (t1 == octave_class::static_type_id ()
-        || t2 == octave_class::static_type_id ()
-        || t1 == octave_classdef::static_type_id ()
-        || t2 == octave_classdef::static_type_id ())
+    bool either_is_class = (t1 == octave_class::static_type_id ()
+                            || t2 == octave_class::static_type_id ()
+                            || t1 == octave_classdef::static_type_id ()
+                            || t2 == octave_classdef::static_type_id ());
+
+    if (!either_is_class)
+      {
+        type_info::binary_op_fcn f = ti.lookup_binary_op (op, t1, t2);
+
+        if (f)
+          return f (v1.get_rep (), v2.get_rep ());
+        else
+          return decompose_binary_op (ti, op, v1, v2);
+      }
+    else
       {
         type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op);
 
         if (f)
-          retval = f (v1, v2);
+          return f (v1, v2);
         else
-          retval = decompose_binary_op (ti, op, v1, v2);
+          return decompose_binary_op (ti, op, v1, v2);
       }
-    else
-      {
-        type_info::binary_op_fcn f = ti.lookup_binary_op (op, t1, t2);
-
-        if (f)
-          retval = f (v1.get_rep (), v2.get_rep ());
-        else
-          retval = decompose_binary_op (ti, op, v1, v2);
-      }
-
-    return retval;
   }
 
   octave_value
