diff options
author | Simon Hausmann <[email protected]> | 2018-08-29 22:05:36 +0200 |
---|---|---|
committer | Lars Knoll <[email protected]> | 2018-08-30 07:08:37 +0000 |
commit | 86c4df64f1fe55297afdb68e94df867e8f05ef32 (patch) | |
tree | a8948e6188b58c1fab9f7f0db02c78af4f0c10d4 /src/qml/jsruntime/qv4identifiertable.cpp | |
parent | f738abe53ed96d0d4e29290bc04b270cfc74569b (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 <[email protected]>
Reviewed-by: Lars Knoll <[email protected]>
Diffstat (limited to 'src/qml/jsruntime/qv4identifiertable.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4identifiertable.cpp | 11 |
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; |