aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 6d1fb62e0a..dac899e23f 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -235,18 +235,39 @@ void ArrayData::ensureAttributes(Object *o)
ArrayData::realloc(o, Heap::ArrayData::Simple, 0, true);
}
+// Note: This function, and the calls from SimpleArrayData::markObjects, is a partial backport
+// of the functionality of ValueArray in 5.11. It prevents huge arrays to overflow the JS stack
+// during the mark phase by draining it while marking the array contents.
+static void drainMarkStack(QV4::ExecutionEngine *engine, 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);
+ }
+}
void SimpleArrayData::markObjects(Heap::Base *d, ExecutionEngine *e)
{
+ Value *markBase = e->jsStackTop;
+ const auto *maxMarkStack = markBase + 32 * 1024;
+
Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(d);
uint end = dd->offset + dd->len;
if (end > dd->alloc) {
- for (uint i = 0; i < end - dd->alloc; ++i)
+ for (uint i = 0; i < end - dd->alloc; ++i) {
+ if (e->jsStackTop > maxMarkStack)
+ drainMarkStack(e, markBase);
dd->arrayData[i].mark(e);
+ }
end = dd->alloc;
}
- for (uint i = dd->offset; i < end; ++i)
+ for (uint i = dd->offset; i < end; ++i) {
+ if (e->jsStackTop > maxMarkStack)
+ drainMarkStack(e, markBase);
dd->arrayData[i].mark(e);
+ }
}
ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)