aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4identifiertable.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2018-08-29 22:05:36 +0200
committerLars Knoll <lars.knoll@qt.io>2018-08-30 07:08:37 +0000
commit86c4df64f1fe55297afdb68e94df867e8f05ef32 (patch)
treea8948e6188b58c1fab9f7f0db02c78af4f0c10d4 /src/qml/jsruntime/qv4identifiertable.cpp
parentf738abe53ed96d0d4e29290bc04b270cfc74569b (diff)
Fix another bug in sweeping the identifier hash table
When an identifier overflows into the next bucket and its original spot becomes free, it is not only important to move that identifier into the now free spot. It is also necessary to shift the entries in the bucket overflowed into one entry to the left, to avoid an accidental terminator in the bucket. Such a terminator can make entire strings disappear from the hash table. That in turn may result in repeated insertion of strings that are otherwise identical, leading to internalClass lookups failing (despite the members existing) after a GC. Task-number: QTBUG-70205 Change-Id: Idf931287896a8ff730af98d36de703157e9792d3 Reviewed-by: Liang Qi <liang.qi@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
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;