Repository navigation
Map.clear and Set.clear keep the bucket table - #100
Merged
Merged
Conversation
clear() shrank the buckets to length zero. Every lookup after it took the hash modulo that length: the compiler does the remainder in floating point, so it was NaN, and the index made from NaN is undefined. On x86-64 it came out as 0, and the emptied storage read as an empty bucket, so nothing showed; where the optimizer can see the length is zero it emits a trap. clear() now zeroes the buckets where they are. The next insert finds no room in the entries and resizes both, as before. map_clear_reuse.ts looks up, deletes from, walks and refills a cleared map and set. It passed before the change too: it guards the behaviour, it did not show the fault. Tested in release on Windows x64 for gc, rc, none and own, compiled and under the JIT; debug, Linux, x86 and wasm were not built locally. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Map.clearandSet.clearzero the bucket table in place and keep its length. They shrank it to length zero.Why
Every
get,has,setanddeletecomputeshash % buckets.length. After a clear that was a remainder by zero:uint % uintin floating point (frem), so the result was NaN;fptosi), which is undefined.It gave right answers only by luck. On x86-64 the conversion yields index 0, shrinking an array zero-fills its storage and keeps the block, so index 0 read as an empty bucket; and the first insert after a clear resizes before it writes. Where the optimizer can see the length is zero it emits a trap instead: the same lookup on a plain emptied array crashed under the JIT.
Change
src/generics/lib.generics.ts:clear()inMapand inSet. The next insert still finds no room in the entries and resizes both tables, as before.tests/map_clear_reuse.ts(new): lookups, delete and iteration on a cleared map and set, refilling past the first size, clear after deletes, clear twice.For the reviewer
uint % uintcompiled as a floating-point remainder is in the compiler. It is on the path of everyMapandSetoperation.Testing
🤖 Generated with Claude Code