diff options
-rw-r--r-- | src/qml/jsruntime/qv4persistent.cpp | 28 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4persistent_p.h | 3 | ||||
-rw-r--r-- | tests/auto/qml/qjsvalue/tst_qjsvalue.cpp | 1 |
3 files changed, 28 insertions, 4 deletions
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp index 3cbaec1dac..81153dd36f 100644 --- a/src/qml/jsruntime/qv4persistent.cpp +++ b/src/qml/jsruntime/qv4persistent.cpp @@ -142,6 +142,7 @@ PersistentValueStorage::PersistentValueStorage(ExecutionEngine *engine) PersistentValueStorage::~PersistentValueStorage() { + clearFreePageHint(); Page *p = static_cast<Page *>(firstPage); while (p) { for (int i = 0; i < kEntriesPerPage; ++i) { @@ -159,7 +160,9 @@ PersistentValueStorage::~PersistentValueStorage() Value *PersistentValueStorage::allocate() { - Page *p = static_cast<Page *>(firstPage); + Page *p = static_cast<Page *>(freePageHint); + if (p && p->header.freeList == -1) + p = static_cast<Page *>(firstPage); while (p) { if (p->header.freeList != -1) break; @@ -171,9 +174,15 @@ Value *PersistentValueStorage::allocate() Value *v = p->values + p->header.freeList; p->header.freeList = v->int_32(); - if (p->header.freeList != -1 && p != firstPage && !engine->isGCOngoing) { - unlink(p); - insertInFront(this, p); + if (p->header.freeList != -1 && p != freePageHint) { + if (auto oldHint = static_cast<Page *>(freePageHint)) { + oldHint->header.refCount--; + // no need to free - if the old page were unused, + // we would have used it to serve the allocation + Q_ASSERT(oldHint->header.refCount); + } + freePageHint = p; + p->header.refCount++; } ++p->header.refCount; @@ -207,6 +216,17 @@ void PersistentValueStorage::mark(MarkStack *markStack) } } +void PersistentValueStorage::clearFreePageHint() +{ + if (!freePageHint) + return; + auto page = static_cast<Page *>(freePageHint); + if (!--page->header.refCount) + freePage(page); + freePageHint = nullptr; + +} + ExecutionEngine *PersistentValueStorage::getEngine(const Value *v) { return getPage(v)->header.engine; diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h index 7e208bd4fd..c24d337b60 100644 --- a/src/qml/jsruntime/qv4persistent_p.h +++ b/src/qml/jsruntime/qv4persistent_p.h @@ -51,10 +51,13 @@ struct Q_QML_EXPORT PersistentValueStorage Iterator begin() { return Iterator(firstPage, 0); } Iterator end() { return Iterator(nullptr, 0); } + void clearFreePageHint(); + static ExecutionEngine *getEngine(const Value *v); ExecutionEngine *engine; void *firstPage; + void *freePageHint = nullptr; private: static void freeUnchecked(Value *v); static void freePage(void *page); diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index 6c7612b77e..7fd97f7231 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -2816,6 +2816,7 @@ void tst_QJSValue::deleteFromDifferentThread() thread->start(); condition.wait(&mutex); QTRY_VERIFY(thread->isFinished()); + storage.clearFreePageHint(); QTRY_COMPARE(storage.firstPage, nullptr); #endif } |