diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-01-24 12:07:33 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-03-09 08:58:04 +0000 |
commit | 6b4b2f5f1bbd706742cbab8764a1d07cbd912600 (patch) | |
tree | d11734823cbf27c557fea8b9be5225c1303d7b12 /src/qml/memory/qv4mm.cpp | |
parent | 78dd18a0cd18449e1289e428ea6eca65e28fb114 (diff) |
New mark table implementation
Automatically generate a table containing the data where JS Values
and pointers are in objects in the JS heap.
This will allow making the GC mark phase a lot more efficient.
A bit of a special hack is currently required for MemberData and
ArrayData, as they have a variable length, and we need to read the
size from the object.
We keep backwards compatibility with the old markObjects() functions
for now (calling them if they are defined). Some further work on
QV4::String and in a few other places is required before we can get
remove the compatibility.
Change-Id: I78528ace67e886bdbe4a4330c9677c7fc9f08a33
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/memory/qv4mm.cpp')
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index a829e902fb..bb600c6c0f 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -740,13 +740,58 @@ Heap::Object *MemoryManager::allocObjectWithMemberData(std::size_t size, uint nM return o; } -static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase) +void MemoryManager::drainMarkStack(Value *markBase) { while (engine->jsStackTop > markBase) { Heap::Base *h = engine->popForGC(); Q_ASSERT(h); // at this point we should only have Heap::Base objects in this area on the stack. If not, weird things might happen. - Q_ASSERT (h->vtable()->markObjects); - h->vtable()->markObjects(h, engine); + if (h->vtable()->markObjects) + h->vtable()->markObjects(h, engine); + if (quint64 m = h->vtable()->markTable) { +// qDebug() << "using mark table:" << hex << m << "for" << h; + void **mem = reinterpret_cast<void **>(h); + while (m) { + MarkFlags mark = static_cast<MarkFlags>(m & 3); + switch (mark) { + case Mark_NoMark: + break; + case Mark_Value: +// qDebug() << "marking value at " << mem; + reinterpret_cast<Value *>(mem)->mark(engine); + break; + case Mark_Pointer: { +// qDebug() << "marking pointer at " << mem; + Heap::Pointer<Heap::Base> *p = reinterpret_cast<Heap::Pointer<Heap::Base> *>(mem); + if (*p) + (*p)->mark(engine); + break; + } + case Mark_ValueArray: { + Q_ASSERT(m == Mark_ValueArray); +// qDebug() << "marking Value Array at offset" << hex << (mem - reinterpret_cast<void **>(h)); + uint size; + Value *v = reinterpret_cast<Value *>(mem); + if (h->vtable() == QV4::MemberData::staticVTable()) { + size = static_cast<Heap::MemberData *>(h)->size; + } else if (h->vtable()->isArrayData) { + size = static_cast<Heap::ArrayData *>(h)->alloc; + } else { + size = 0; + Q_ASSERT(false); + } + const Value *end = v + size; + while (v < end) { + v->mark(engine); + ++v; + } + break; + } + } + + m >>= 2; + ++mem; + } + } } } @@ -788,10 +833,10 @@ void MemoryManager::mark() qobjectWrapper->mark(engine); if (engine->jsStackTop >= engine->jsStackLimit) - drainMarkStack(engine, markBase); + drainMarkStack(markBase); } - drainMarkStack(engine, markBase); + drainMarkStack(markBase); } void MemoryManager::sweep(bool lastSweep) |