Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix float64 to uint{8,16,32} conversion. #1305

Merged
merged 1 commit into from
May 6, 2024

Conversation

nevkontakte
Copy link
Member

Before this change, GopherJS compiler emitted (f >> 0) expression to convert a float64 f to any non-64-bit unsigned integer type. This is incorrect, because >> is a signed bitshift operator in JS, so the returned value remained signed. Moreover, it did not take into account to bit size of the target type.

By removing the switch cause, we make the compiler fall through to the default clause where fc.fixNumber() actually does the right thing, taking the target into account.

Fixes #733.

Amazingly, this is what was causing flakiness of the hash/maphash.TestHashHighBytes since Go 1.19. There, the 64-bit hash value was computed as (uint64(hi) << 32) | uint64(lo), where hi and lo were randomly-generated unit32 values. In turn, those values were generated by converting a random [0, 2^32) float64 value into uint32. As per explanation above, this used to be done with the following JS expression (f >> 0), which meant that for values in the range of [2^31, 2^32) it would return a negative JS number. This would also set all the high bits of that number to 1. So when we come back to (uint64(hi) << 32) | uint64(lo), there was the 50% chance that all higher bits of the right bitwise-or operand would be 1, meaning the result would also have the higher bits set to 1, regardless of what hi was. That led to a high likelihood of failing said test 🕵️‍♂️

@nevkontakte nevkontakte requested a review from flimzy May 6, 2024 18:12
Before this change, GopherJS compiler emitted `(f >> 0)` expression to
convert a float64 `f` to any non-64-bit unsigned integer type. This is
incorrect, because `>>` is a signed bitshift operator in JS, so the
returned value remained signed. Moreover, it did not take into account
to bit size of the target type.

By removing the switch cause, we make the compiler fall through to the
default clause where `fc.fixNumber()` actually does the right thing,
taking the target into account.

Fixes gopherjs#733.
@nevkontakte nevkontakte merged commit 27071a8 into gopherjs:master May 6, 2024
7 checks passed
@nevkontakte nevkontakte deleted the flake branch May 6, 2024 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorrect conversion from float64 to uint8.
2 participants