aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4identifiertable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4identifiertable.cpp')
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp11
1 files changed, 10 insertions, 1 deletions
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index 0412695404..7124a0a949 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -265,6 +265,8 @@ int sweepTable(Heap::StringOrSymbol **table, int alloc, std::function<Key(Heap::
break;
}
+ bool shiftWithinBucket = false;
+
for (int i = 0; i < alloc; ++i) {
int idx = (i + start) % alloc;
Heap::StringOrSymbol *entry = table[idx];
@@ -273,7 +275,7 @@ int sweepTable(Heap::StringOrSymbol **table, int alloc, std::function<Key(Heap::
continue;
}
if (entry->isMarked()) {
- if (lastEntry >= 0 && lastKey == (f(entry) % alloc)) {
+ if (lastEntry >= 0 && ((lastKey == f(entry) % alloc) || shiftWithinBucket)) {
Q_ASSERT(table[lastEntry] == nullptr);
table[lastEntry] = entry;
table[idx] = nullptr;
@@ -282,9 +284,16 @@ int sweepTable(Heap::StringOrSymbol **table, int alloc, std::function<Key(Heap::
do {
lastEntry = (lastEntry + 1) % alloc;
} while (table[lastEntry] != nullptr);
+
+ // Avoid gaps within a bucket by enabling shift mode
+ // if we've caught up to the current index.
+ shiftWithinBucket = lastEntry == idx;
}
continue;
}
+
+ shiftWithinBucket = false;
+
if (lastEntry == -1) {
lastEntry = idx;
lastKey = f(entry) % alloc;