diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2014-10-21 11:05:00 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2014-10-22 16:39:44 +0200 |
commit | 9a66bb751bb5f5830e5f30a3c1a22ddb5f34f1bb (patch) | |
tree | c4bae9996f7945cbdc2a67dbab1da31bfb1b21b6 /src | |
parent | 3950a2694e6a327b84f037a2357014343d994a41 (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.cpp | 22 |
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) |