Fixed some memory cleanup and destruction issues with ContextObj, ECData, CDList...
authorTim King <taking@cs.nyu.edu>
Tue, 23 Mar 2010 19:41:49 +0000 (19:41 +0000)
committerTim King <taking@cs.nyu.edu>
Tue, 23 Mar 2010 19:41:49 +0000 (19:41 +0000)
src/context/cdlist.h
src/context/cdmap.h
src/context/context.h
src/expr/node.h
src/expr/node_manager.cpp
src/expr/node_manager.h
src/expr/node_value.h
src/theory/uf/ecdata.h

index e3c7e155cf756aada28798c42911c8c80d6fc7cb..492dc793990d63ca3a3b25e35d08b01fcbdc8445 100644 (file)
@@ -138,9 +138,15 @@ public:
    * Destructor: delete the list
    */
   ~CDList() throw(AssertionException) {
-    T* list = d_list;
     destroy();
-    free(list);
+
+    if(d_callDestructor) {
+      for(unsigned i = 0; i < d_size; ++i) {
+        d_list[i].~T();
+      }
+    }
+
+    free(d_list);
   }
 
   /**
index 460f917ffe076f705b4adbed868055aa27139874..1dc44d0875b0369bd41dcf4f11a8ed29ceb7571d 100644 (file)
@@ -201,13 +201,13 @@ public:
 
   ~CDMap() throw(AssertionException) {
     // Delete all the elements and clear the map
-    for(typename table_type::iterator
-         i = d_map.begin(), iend = d_map.end(); i != iend; ++i) {
-      /*
+    /*for(typename table_type::iterator
+          i = d_map.begin(), iend = d_map.end(); i != iend; ++i) {
+
         delete (*i).second;
         free((*i).second);
-      */
-    }
+
+    }*/
     d_map.clear();
     emptyTrash();
   }
index 6b9f9fd6d85fa638f9891463f7b52abdfbfe0f3f..87e4e5fa15462da1d74b1021a9c79606cde7d5b7 100644 (file)
@@ -399,7 +399,7 @@ public:
   /**
    * Destructor does nothing: subclass must explicitly call destroy() instead.
    */
-  virtual ~ContextObj() {}
+  virtual ~ContextObj() { Debug("contextgc") << "context obj dest" << std::endl; }
 
   /**
    * If you want to allocate a ContextObj object on the heap, use this
@@ -426,6 +426,7 @@ public:
    * ContextMemoryManager as an argument.
    */
   void deleteSelf() {
+    this->~ContextObj();
     ::operator delete(this);
   }
 
index 25990cedfaa407d65dc76702a5780592db30926f..f7cef5a4cf126824de91182da808039565a98e6f 100644 (file)
@@ -522,7 +522,9 @@ NodeTemplate<ref_count>::~NodeTemplate() throw(AssertionException) {
   if(ref_count) {
     d_nv->dec();
   }
-  Assert(ref_count || d_nv->d_rc > 0,
+  Assert(ref_count ||
+         d_nv->d_rc > 0 ||
+         d_nv->isBeingDeleted(),
          "Temporary node pointing to an expired node");
 }
 
index 7b171a48b594a48149fcb7797dd1401e2f7e3bdb..ee370f68234dda864ba817aee43d374fd32dc366 100644 (file)
@@ -61,6 +61,19 @@ struct Reclaim {
   }
 };
 
+struct NVReclaim {
+  NodeValue*& d_reclaimField;
+  NVReclaim(NodeValue*& reclaim) :
+    d_reclaimField(reclaim) {
+
+    Debug("gc") << ">> setting NVRECLAIM field\n";
+  }
+  ~NVReclaim() {
+    Debug("gc") << "<< clearing NVRECLAIM field\n";
+    d_reclaimField = NULL;
+  }
+};
+
 void NodeManager::reclaimZombies() {
   // FIXME multithreading
 
@@ -104,6 +117,8 @@ void NodeManager::reclaimZombies() {
       if(nv->getKind() != kind::VARIABLE) {
         poolRemove(nv);
       }
+      NVReclaim rc(d_underTheShotgun);
+      d_underTheShotgun = nv;
 
       // remove attributes
       d_attrManager.deleteAllAttributes(nv);
index a3be61e487c1ca9fd4743ca55f483fbcb9522dc1..044deac7f5c836a05804bb2bb5c4b7b9daf75a9b 100644 (file)
@@ -72,6 +72,12 @@ class NodeManager {
   friend class NodeManagerScope;
   friend class expr::NodeValue;
 
+  bool isCurrentlyDeleting(const expr::NodeValue *nv) const{
+    return d_underTheShotgun == nv;
+  }
+
+  expr::NodeValue* d_underTheShotgun;
+
   bool d_reclaiming;
   ZombieSet d_zombies;
 
@@ -105,7 +111,10 @@ public:
 
   NodeManager(context::Context* ctxt) :
     d_attrManager(ctxt),
-    d_reclaiming(false) {
+    d_underTheShotgun(NULL),
+    d_reclaiming(false)
+
+  {
     poolInsert( &expr::NodeValue::s_null );
   }
 
index cbe4e718a504310374a2e073b21a787cc32d651c..9f106371550da28dedcf3b2a523f8fa9cf2e2bb0 100644 (file)
@@ -141,6 +141,8 @@ private:
   /** Decrement ref counts of children */
   inline void decrRefCounts();
 
+  bool isBeingDeleted() const;
+
 public:
 
   template <bool ref_count>
@@ -266,6 +268,9 @@ inline void NodeValue::decrRefCounts() {
 }
 
 inline void NodeValue::inc() {
+  Assert(!isBeingDeleted(),
+         "NodeValue is currently being deleted "
+         "and increment is being called on it. Don't Do That!");
   // FIXME multithreading
   if(EXPECT_TRUE( d_rc < MAX_RC )) {
     ++d_rc;
@@ -301,6 +306,13 @@ inline NodeValue::const_nv_iterator NodeValue::nv_end() const {
   return d_children + d_nchildren;
 }
 
+
+inline bool NodeValue::isBeingDeleted() const
+{
+  return NodeManager::currentNM() != NULL &&
+    NodeManager::currentNM()->isCurrentlyDeleting(this);
+}
+
 }/* CVC4::expr namespace */
 }/* CVC4 namespace */
 
index 199b091643ecc38a8405410f9297019f34bacb1e..248e1e54541688136a090960c5cd5449d085dc89 100644 (file)
@@ -175,6 +175,8 @@ public:
    */
   ECData(context::Context* context, TNode n);
 
+  ~ECData() { Debug("ufgc") << "Calling ECData destructor" << std::endl;}
+
   /**
    * An ECData takes over the watch list of another ECData.
    * This is the second step in the union operator for ECData.