changeset 8456:c1709a45b45b

optimize structure components access
author Jaroslav Hajek <highegg@gmail.com>
date Sun, 11 Jan 2009 14:27:52 +0100
parents fd11a08a9b31
children c72207960242
files src/ChangeLog src/ov-struct.cc src/ov.h
diffstat 3 files changed, 43 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sun Jan 11 07:55:44 2009 +0100
+++ b/src/ChangeLog	Sun Jan 11 14:27:52 2009 +0100
@@ -1,3 +1,10 @@
+2009-01-11  Jaroslav Hajek  <highegg@gmail.com>
+	
+	* ov.h (octave_value::is_copy_of): New method.
+	* ov-struct.cc (numeric_conv): Add output parameter orig.
+	(octave_struct::subsasgn): Temporarily erase duplicate lhs value prior
+	to assignment.
+
 2009-01-11  Jaroslav Hajek  <highegg@gmail.com>
 
 	* oct-obj.cc (octave_value_list::all_scalars): New method.
--- a/src/ov-struct.cc	Sun Jan 11 07:55:44 2009 +0100
+++ b/src/ov-struct.cc	Sun Jan 11 14:27:52 2009 +0100
@@ -224,11 +224,26 @@
 		  u = octave_value::empty_conv (type.substr (2), rhs);
 		else
 		  {
-		    Cell map_val = map.contents (key);
+		    Cell& cell_ref = map.contents (key);
+
+                    octave_value u1 = cell_ref.index (idx.front (), true);
+                    u = numeric_conv (u1, type.substr (2));
 
-		    Cell map_elt = map_val.index (idx.front (), true);
+                    if (u.is_defined () && u.is_copy_of (u1))
+                      {
+                        // This is a bit of black magic. u is a shallow copy
+                        // of an element inside this struct, and maybe more. To
+                        // prevent make_unique from always forcing a copy, we
+                        // temporarily delete the stored value.
+                        u1 = octave_value ();
+                        cell_ref.assign (idx.front (), Cell (octave_value ()));
+                        u.make_unique ();
+                        cell_ref.assign (idx.front (), Cell (u));
+                      }
+                    else
+                      // Safe is safe.
+                      u.make_unique ();
 
-		    u = numeric_conv (map_elt, type.substr (2));
 		  }
 
 		if (! error_state)
@@ -241,8 +256,6 @@
 		    next_idx.erase (next_idx.begin ());
 		    next_idx.erase (next_idx.begin ());
 
-		    u.make_unique ();
-
 		    t_rhs = u.subsasgn (type.substr (2), next_idx, rhs);
 		  }
 	      }
@@ -265,9 +278,23 @@
 	      u = octave_value::empty_conv (type.substr (1), rhs);
 	    else
 	      {
-		Cell map_val = map.contents (key);
+        	Cell& cell_ref = map.contents (key);
+
+                u = numeric_conv (cell_ref, type.substr (2));
 
-		u = numeric_conv (map_val, type.substr (1));
+                if (u.is_defined () && u.is_copy_of (cell_ref(0)))
+                  {
+                    // This is a bit of black magic. u is a shallow copy
+                    // of an element inside this struct, and maybe more. To
+                    // prevent make_unique from always forcing a copy, we
+                    // temporarily delete the stored value.
+                    cell_ref(0) = octave_value ();
+                    u.make_unique ();
+                    cell_ref(0) = u;
+                  }
+                else
+                  // Safe is safe.
+                  u.make_unique ();
 	      }
 
 	    if (! error_state)
@@ -276,8 +303,6 @@
 
 		next_idx.erase (next_idx.begin ());
 
-		u.make_unique ();
-
 		t_rhs = u.subsasgn (type.substr (1), next_idx, rhs);
 	      }
 	  }
--- a/src/ov.h	Sun Jan 11 07:55:44 2009 +0100
+++ b/src/ov.h	Sun Jan 11 14:27:52 2009 +0100
@@ -915,6 +915,8 @@
 
   const octave_base_value& get_rep (void) const { return *rep; }
 
+  bool is_copy_of (const octave_value &val) const { return rep == val.rep; }
+
   void print_info (std::ostream& os,
 			   const std::string& prefix = std::string ()) const;