aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp28
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h3
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp1
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
}