Add a mechanism to protect managed objects from deletion
authorLars Knoll <lars.knoll@digia.com>
Mon, 28 Jan 2013 12:32:08 +0000 (13:32 +0100)
committerJędrzej Nowacki <jedrzej.nowacki@digia.com>
Mon, 28 Jan 2013 12:34:06 +0000 (13:34 +0100)
Change-Id: I6700dc94ad481e12ee7f00c04c0c37261e22a715
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
qv4mm.cpp
qv4mm.h

index e4f1fbe..71e6def 100644 (file)
--- a/qv4mm.cpp
+++ b/qv4mm.cpp
@@ -64,6 +64,7 @@ struct MemoryManager::Data
     };
 
     QVector<Chunk> heapChunks;
+    QHash<Managed *, uint> protectedObject;
 
     // statistics:
 #ifdef DETAILED_MM_STATS
@@ -165,12 +166,12 @@ void MemoryManager::scribble(Managed *obj, int c, int size) const
         ::memset((void *)(obj + 1), c, size - sizeof(Managed));
 }
 
-void MemoryManager::mark(const QVector<Object *> &objects)
+void MemoryManager::mark(const QVector<Managed *> &objects)
 {
-    foreach (Object *o, objects) {
-        if (!o)
+    foreach (Managed *m, objects) {
+        if (!m)
             continue;
-        o->mark();
+        m->mark();
     }
 
     return;
@@ -239,7 +240,7 @@ void MemoryManager::runGC()
 //    QTime t; t.start();
 
 //    qDebug() << ">>>>>>>>runGC";
-    QVector<Object *> roots;
+    QVector<Managed *> roots;
     collectRoots(roots);
 //    std::cerr << "GC: found " << roots.size()
 //              << " roots in " << t.elapsed()
@@ -268,7 +269,18 @@ MemoryManager::~MemoryManager()
     sweep();
 }
 
-static inline void add(QVector<Object *> &values, const Value &v)
+void MemoryManager::protect(Managed *m)
+{
+    ++m_d->protectedObject[m];
+}
+
+void MemoryManager::unprotect(Managed *m)
+{
+    if (!--m_d->protectedObject[m])
+        m_d->protectedObject.remove(m);
+}
+
+static inline void add(QVector<Managed *> &values, const Value &v)
 {
     if (Object *o = v.asObject())
         values.append(o);
@@ -310,7 +322,7 @@ void MemoryManager::willAllocate(std::size_t size)
 
 #endif // DETAILED_MM_STATS
 
-void MemoryManager::collectRoots(QVector<VM::Object *> &roots) const
+void MemoryManager::collectRoots(QVector<Managed *> &roots) const
 {
     add(roots, m_d->engine->globalObject);
     add(roots, m_d->engine->exception);
@@ -342,9 +354,12 @@ void MemoryManager::collectRoots(QVector<VM::Object *> &roots) const
     }
 
     collectRootsOnStack(roots);
+
+    for (QHash<Managed *, uint>::const_iterator it = m_d->protectedObject.begin(); it != m_d->protectedObject.constEnd(); ++it)
+        roots.append(it.key());
 }
 
-void MemoryManager::collectRootsOnStack(QVector<VM::Object *> &roots) const
+void MemoryManager::collectRootsOnStack(QVector<VM::Managed *> &roots) const
 {
     if (!m_d->heapChunks.count())
         return;
diff --git a/qv4mm.h b/qv4mm.h
index 0dd3e61..07c6e95 100644 (file)
--- a/qv4mm.h
+++ b/qv4mm.h
@@ -73,6 +73,9 @@ public:
     MemoryManager();
     ~MemoryManager();
 
+    void protect(Managed *m);
+    void unprotect(Managed *m);
+
     // TODO: this is only for 64bit (and x86 with SSE/AVX), so exend it for other architectures to be slightly more efficient (meaning, align on 8-byte boundaries).
     // Note: all occurances of "16" in alloc/dealloc are also due to the alignment.
     static inline std::size_t align(std::size_t size)
@@ -101,7 +104,7 @@ protected:
 
     void scribble(Managed *obj, int c, int size) const;
 
-    void collectRootsOnStack(QVector<VM::Object *> &roots) const;
+    void collectRootsOnStack(QVector<Managed *> &roots) const;
 
     ExecutionEngine *engine() const;
 
@@ -110,8 +113,8 @@ protected:
 #endif // DETAILED_MM_STATS
 
 private:
-    void collectRoots(QVector<VM::Object *> &roots) const;
-    static void mark(const QVector<Object *> &objects);
+    void collectRoots(QVector<VM::Managed *> &roots) const;
+    static void mark(const QVector<Managed *> &objects);
     std::size_t sweep();
     std::size_t sweep(char *chunkStart, std::size_t chunkSize, size_t size);