Use a doubly linked list for PersistentValue
authorLars Knoll <lars.knoll@digia.com>
Mon, 6 May 2013 13:11:01 +0000 (15:11 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Mon, 6 May 2013 13:55:59 +0000 (15:55 +0200)
This makes cleanup easier, more consistent and actually
work.

Change-Id: I5b58b6649ed527fd9f216c67ea609b49228c874a
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/qml/v4/qv4mm.cpp
src/qml/qml/v4/qv4value.cpp
src/qml/qml/v4/qv4value_p.h

index f71f7a8..b400415 100644 (file)
@@ -399,8 +399,9 @@ MemoryManager::~MemoryManager()
 {
     PersistentValuePrivate *persistent = m_persistentValues;
     while (persistent) {
-        persistent->value = Value::deletedValue();
         PersistentValuePrivate *n = persistent->next;
+        persistent->value = Value::deletedValue();
+        persistent->prev = 0;
         persistent->next = 0;
         persistent = n;
     }
index 7e2f164..f330aeb 100644 (file)
@@ -247,6 +247,16 @@ PersistentValue &PersistentValue::operator=(const PersistentValue &other)
 PersistentValue &PersistentValue::operator =(const Value &other)
 {
     d->value = other;
+    if (!d->prev) {
+        if (Managed *m = d->value.asManaged()) {
+            ExecutionEngine *engine = m->engine();
+            if (engine) {
+                d->prev = &engine->memoryManager->m_persistentValues;
+                d->next = engine->memoryManager->m_persistentValues;
+                *d->prev = d;
+            }
+        }
+    }
 }
 
 PersistentValue::~PersistentValue()
@@ -257,13 +267,16 @@ PersistentValue::~PersistentValue()
 PersistentValuePrivate::PersistentValuePrivate(const Value &v)
     : value(v)
     , refcount(1)
+    , prev(0)
     , next(0)
 {
     if (Managed *m = v.asManaged()) {
         ExecutionEngine *engine = m->engine();
         if (engine) {
+            prev = &engine->memoryManager->m_persistentValues;
             next = engine->memoryManager->m_persistentValues;
-            engine->memoryManager->m_persistentValues = this;
+            if (next)
+                next->prev = &this->next;
         }
     }
 }
@@ -272,11 +285,11 @@ void PersistentValuePrivate::deref()
 {
     // if engine is not 0, they are registered with the memory manager
     // and will get cleaned up in the next gc run
-    if (!--refcount && !next) {
-        ExecutionEngine *e = 0;
-        if (Managed *m = value.asManaged())
-            e = m->engine();
-        if (!e)
-            delete this;
+    if (!--refcount) {
+        if (prev) {
+            next->prev = prev;
+            *prev = next;
+        }
+        delete this;
     }
 }
index 29fc68b..d583826 100644 (file)
@@ -554,11 +554,13 @@ struct PersistentValuePrivate
     PersistentValuePrivate()
         : value(Value::deletedValue())
         , refcount(1)
+        , prev(0)
         , next(0)
     {}
     PersistentValuePrivate(const Value &v);
     Value value;
     int refcount;
+    PersistentValuePrivate **prev;
     PersistentValuePrivate *next;
 
     void ref() { ++refcount; }