aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2014-10-21 11:05:00 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2014-10-22 16:39:44 +0200
commit9a66bb751bb5f5830e5f30a3c1a22ddb5f34f1bb (patch)
treec4bae9996f7945cbdc2a67dbab1da31bfb1b21b6 /src
parent3950a2694e6a327b84f037a2357014343d994a41 (diff)
Reduce memory pressure on the JS stack during garbage collection
As the example in QTBUG-42051 demonstrates, QML may produce a lot of binding objects and each of them produce a QV4::Persistent. During the mark phase we may run out of JS stack space. One fix (for the future) is to reduce the number of QV4::Persistent objects, but in the meantime we can also reduce the pressure on the stack by draining it earlier. Task-number: QTBUG-42051 Change-Id: Iea73f8a869048ea0bf3f4a64dbd24b6fb8c68f6b Reviewed-by: Ulf Hermann <ulf.hermann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/jsruntime/qv4mm.cpp22
1 files changed, 16 insertions, 6 deletions
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
index 0cb10b1506..442a27661b 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/jsruntime/qv4mm.cpp
@@ -255,6 +255,15 @@ Managed *MemoryManager::allocData(std::size_t size)
return m;
}
+static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
+{
+ while (engine->jsStackTop > markBase) {
+ Managed *m = engine->popForGC();
+ Q_ASSERT (m->internalClass()->vtable->markObjects);
+ m->internalClass()->vtable->markObjects(m, engine);
+ }
+}
+
void MemoryManager::mark()
{
Value *markBase = m_d->engine->jsStackTop;
@@ -272,6 +281,9 @@ void MemoryManager::mark()
}
persistent->value.mark(m_d->engine);
persistent = persistent->next;
+
+ if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit)
+ drainMarkStack(m_d->engine, markBase);
}
collectFromJSStack();
@@ -304,14 +316,12 @@ void MemoryManager::mark()
if (keepAlive)
qobjectWrapper->getPointer()->mark(m_d->engine);
- }
- // now that we marked all roots, start marking recursively and popping from the mark stack
- while (m_d->engine->jsStackTop > markBase) {
- Managed *m = m_d->engine->popForGC();
- Q_ASSERT (m->internalClass()->vtable->markObjects);
- m->internalClass()->vtable->markObjects(m, m_d->engine);
+ if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit)
+ drainMarkStack(m_d->engine, markBase);
}
+
+ drainMarkStack(m_d->engine, markBase);
}
void MemoryManager::sweep(bool lastSweep)