# HG changeset patch
# User Petter Tomner <tomner@kth.se>
# Date 1637544054 -3600
#      Mon Nov 22 02:20:54 2021 +0100
# Node ID 356f42f8497f3a7653966a57d337f119a715aaab
# Parent  bf619727bf6c2f00e70f95f471d447ef67ab2088
interpreter: Inline nil_rep

Adds a special class for octave_value and idx_vector_rep nil objects that
start their life with count==2 to avoid checks for nil objects in dtors.

Moves nil_rep getter function to header aswell as makes the object
visible for other translation units to avoid function calls.

libinterp/octave-value
	* ov.cc: New nil obj
	* ov.hh: New nil class

liboctave/array/
	* idx-vector.cc: New nil obj
	* idx_vector.h: New nil class

diff -r bf619727bf6c -r 356f42f8497f libinterp/octave-value/ov.cc
--- a/libinterp/octave-value/ov.cc	Sun Nov 21 15:25:04 2021 +0100
+++ b/libinterp/octave-value/ov.cc	Mon Nov 22 02:20:54 2021 +0100
@@ -110,17 +110,29 @@
 
 static bool Voptimize_range = true;
 
-// FIXME
-
+// The object that is the nil representation of a octave_value
+octave_value::octave_nil octave_value::nil_ov_base;
+
+// Special class to make a octave_base_value that will never have a zero count
+// so that we can create a static octave_base_value and not call delete on it
+// in the octave_value dtors, move constructors etc
+/*class octave_nil : public octave_base_value {
+public:
+  octave_nil ()
+  {
+    count++;
+  }
+};
+*/
 // Octave's value type.
-
+/*
 octave_base_value *
 octave_value::nil_rep (void)
 {
-  static octave_base_value nr;
+  static octave_nil nr;
   return &nr;
 }
-
+*/
 std::string
 octave_value::unary_op_as_string (unary_op op)
 {
diff -r bf619727bf6c -r 356f42f8497f libinterp/octave-value/ov.h
--- a/libinterp/octave-value/ov.h	Sun Nov 21 15:25:04 2021 +0100
+++ b/libinterp/octave-value/ov.h	Mon Nov 22 02:20:54 2021 +0100
@@ -383,7 +383,7 @@
     // operator, rep may be a nullptr here.  We should only need to
     // protect the move assignment operator in a similar way.
 
-    if (m_rep && --m_rep->count == 0 && m_rep != nil_rep ())
+    if (m_rep && --m_rep->count == 0)
       delete m_rep;
   }
 
@@ -393,7 +393,7 @@
       {
         octave_base_value *r = m_rep->unique_clone ();
 
-        if (--m_rep->count == 0 && m_rep != nil_rep ())
+        if (--m_rep->count == 0)
           delete m_rep;
 
         m_rep = r;
@@ -409,7 +409,7 @@
       {
         octave_base_value *r = m_rep->unique_clone ();
 
-        if (--m_rep->count == 0 && m_rep != nil_rep ())
+        if (--m_rep->count == 0)
           delete m_rep;
 
         m_rep = r;
@@ -428,7 +428,7 @@
   {
     if (m_rep != a.m_rep)
       {
-        if (--m_rep->count == 0 && m_rep != nil_rep ())
+        if (--m_rep->count == 0)
           delete m_rep;
 
         m_rep = a.m_rep;
@@ -446,7 +446,7 @@
 
     if (this != &a)
       {
-        if (m_rep && --m_rep->count == 0 && m_rep != nil_rep ())
+        if (m_rep && --m_rep->count == 0)
           delete m_rep;
 
         m_rep = a.m_rep;
@@ -1637,8 +1637,24 @@
   octave_base_value *m_rep;
 
 private:
+  // Special class to make a octave_base_value that will never have a zero count
+  // so that we can create a static octave_base_value and not call delete on it
+  // in the octave_value dtors, move constructors etc that check count for
+  // whether to call delete or not.
+  class octave_nil : public octave_base_value {
+  public:
+    octave_nil ()
+    {
+      count++;
+    }
+  };
 
-  static OCTINTERP_API octave_base_value *nil_rep (void);
+  static OCTINTERP_API octave_nil nil_ov_base;
+
+  static OCTINTERP_API octave_base_value *nil_rep (void)
+  {
+	return &nil_ov_base;
+  }
 
   OCTINTERP_API assign_op unary_op_to_assign_op (unary_op op);
 
diff -r bf619727bf6c -r 356f42f8497f liboctave/array/idx-vector.cc
--- a/liboctave/array/idx-vector.cc	Sun Nov 21 15:25:04 2021 +0100
+++ b/liboctave/array/idx-vector.cc	Mon Nov 22 02:20:54 2021 +0100
@@ -55,11 +55,8 @@
       ("internal error: idx_vector index out of range");
   }
 
-  idx_vector::idx_vector_rep * idx_vector::nil_rep (void)
-  {
-    static idx_vector_rep ivr;
-    return &ivr;
-  }
+  // Object for nil representation of idx_vector_rep
+  idx_vector::idx_vector_rep_nil idx_vector::nil_idx_vector_rep;
 
   Array<octave_idx_type> idx_vector::idx_base_rep::as_array (void)
   {
diff -r bf619727bf6c -r 356f42f8497f liboctave/array/idx-vector.h
--- a/liboctave/array/idx-vector.h	Sun Nov 21 15:25:04 2021 +0100
+++ b/liboctave/array/idx-vector.h	Mon Nov 22 02:20:54 2021 +0100
@@ -124,6 +124,8 @@
       refcount<octave_idx_type> m_count;
     };
 
+
+
     // The magic colon index.
     class OCTAVE_API idx_colon_rep : public idx_base_rep
     {
@@ -440,10 +442,6 @@
 
     idx_vector (idx_base_rep *r) : m_rep (r) { }
 
-    // The shared empty vector representation (for fast default
-    // constructor).
-    static OCTAVE_API idx_vector_rep *nil_rep (void);
-
     public:
 
     // Fast empty constructor.
@@ -517,7 +515,7 @@
 
     ~idx_vector (void)
     {
-      if (--m_rep->m_count == 0 && m_rep != nil_rep ())
+      if (--m_rep->m_count == 0)
         delete m_rep;
     }
 
@@ -525,7 +523,7 @@
     {
       if (this != &a)
         {
-          if (--m_rep->m_count == 0 && m_rep != nil_rep ())
+          if (--m_rep->m_count == 0)
             delete m_rep;
 
           m_rep = a.m_rep;
@@ -1028,6 +1026,28 @@
 
     private:
 
+    // Special class to make a idx_vector_rep that will never have a zero count
+    // so that we can create a static idx_vector_rep and not call delete on it
+    // in dtors, move constructors etc. See idx_vector::nil_rep
+    class idx_vector_rep_nil : public idx_vector_rep
+	{
+	  public:
+      idx_vector_rep_nil ()
+      {
+    	m_count++;
+      }
+	};
+
+    // Object for nil representation of idx_vector_rep
+    static OCTAVE_API idx_vector_rep_nil nil_idx_vector_rep;
+
+    // The shared empty vector representation (for fast default
+    // constructor).
+    static OCTAVE_API idx_vector_rep *nil_rep (void)
+    {
+    	return &nil_idx_vector_rep;
+    }
+
     idx_base_rep *m_rep;
 
   };
