Fix assertions in dictionary that can trigger for benign reasons.

These assertions were checking for a situation that I believe can
happen legitimately: a robust iterator pointing to an index that,
after some table resizing, happens to be inside the overflow area and
hence empty. We'll now move it to the end of the table in the case.
This commit is contained in:
Robin Sommer 2022-04-12 17:37:49 +02:00
parent b4f52ff311
commit 6491db6617
No known key found for this signature in database
GPG key ID: 6BEDA4DA6B8B23E3

View file

@ -1832,7 +1832,20 @@ detail::DictEntry Dictionary::GetNextRobustIteration(RobustDictIterator* iter)
if ( iter->next < 0 )
iter->next = Next(-1);
ASSERT(iter->next >= Capacity() || ! table[iter->next].Empty());
if ( iter->next < Capacity() && table[iter->next].Empty() )
{
// [Robin] I believe this means that the table has resized in a way
// that we're now inside the overflow area where elements are empty,
// because elsewhere empty slots aren't allowed. Assuming that's right,
// then it means we'll always be at the end of the table now and could
// also just set `next` to capacity. However, just to be sure, we
// instead reuse logic from below to move forward "to a valid position"
// and then double check, through an assertion in debug mode, that it's
// actually the end. If this ever triggered, the above assumption would
// be wrong (but the Next() call would probably still be right).
iter->next = Next(iter->next);
ASSERT(iter->next == Capacity());
}
// Filter out visited keys.
int capacity = Capacity();