# HG changeset patch
# User Petter Tomner <tomner@kth.se>
# Date 1640213128 -3600
#      Wed Dec 22 23:45:28 2021 +0100
# Node ID 15290efe37e30663e0c1339f6381e8e83af21738
# Parent  fa58b36eaffe1d2811c9a141a8b7168c60cd0e58
interpreter: Special immortal nil classes

Make octave_value's and idx_vector's nil objects be born
with an extra life to avoid checks for nil in destructors.

libinterp/octave-value/
	* ov.cc: Nil object def
	* ov.h: Nil class def

liboctave/array/
	* idx-vector.cc: Nil object def
	* idx-vector.h: Nil class def

diff -r fa58b36eaffe -r 15290efe37e3 libinterp/octave-value/ov.cc
--- a/libinterp/octave-value/ov.cc	Sun Nov 21 16:49:58 2021 +0100
+++ b/libinterp/octave-value/ov.cc	Wed Dec 22 23:45:28 2021 +0100
@@ -110,16 +110,8 @@
 
 static bool Voptimize_range = true;
 
-// FIXME
-
-// Octave's value type.
-
-octave_base_value *
-octave_value::nil_rep (void)
-{
-  static octave_base_value nr;
-  return &nr;
-}
+// The object that is the nil representation of a octave_value
+octave_value::octave_nil octave_value::nil_ov_base;
 
 std::string
 octave_value::unary_op_as_string (unary_op op)
diff -r fa58b36eaffe -r 15290efe37e3 libinterp/octave-value/ov.h
--- a/libinterp/octave-value/ov.h	Sun Nov 21 16:49:58 2021 +0100
+++ b/libinterp/octave-value/ov.h	Wed Dec 22 23:45:28 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;
@@ -1639,7 +1639,24 @@
 
 private:
 
-  static OCTINTERP_API octave_base_value * nil_rep (void);
+  // 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_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 fa58b36eaffe -r 15290efe37e3 liboctave/array/idx-vector.cc
--- a/liboctave/array/idx-vector.cc	Sun Nov 21 16:49:58 2021 +0100
+++ b/liboctave/array/idx-vector.cc	Wed Dec 22 23:45:28 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 fa58b36eaffe -r 15290efe37e3 liboctave/array/idx-vector.h
--- a/liboctave/array/idx-vector.h	Sun Nov 21 16:49:58 2021 +0100
+++ b/liboctave/array/idx-vector.h	Wed Dec 22 23:45:28 2021 +0100
@@ -438,10 +438,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.
@@ -515,7 +511,7 @@
 
     ~idx_vector (void)
     {
-      if (--m_rep->m_count == 0 && m_rep != nil_rep ())
+      if (--m_rep->m_count == 0)
         delete m_rep;
     }
 
@@ -523,7 +519,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;
@@ -1026,6 +1022,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;
 
   };
