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

Change the semantics of bitwise operations to be fully platform-dependent #807

Open
giacomocavalieri opened this issue Feb 16, 2025 · 7 comments

Comments

@giacomocavalieri
Copy link
Member

What @joshi-monster proposed here
Joshi brings up some good points, I'd like to discuss this more

@lpil
Copy link
Member

lpil commented Feb 16, 2025

Is the idea here to sacrifice all other bit manipulation use cases for a faster multiply and divide by 2?

Bitwise operations can be used for platform specific optimisations, but they are more commonly used for manipulating bits, which this proposal seems to make impossible as the results are no longer reliable?

If you are already doing platform specific optimisations then you are already using FFI, so using platform specific operators causes you no problems that I can see.

@yoshi-monster
Copy link
Contributor

yoshi-monster commented Feb 16, 2025

Hi!!

First of all: sorry, I'm always a little bit overwhelmed by github and the process; the PR was meant to be a discussion 🙂

I would definitely like to see peoples' opinions on this change, and on what integer semantics on JavaScript should be in general. Right now Gleam seems to target the full range (52-bit) of safe integers.

Of note here is also that JavaScript engines include special optimisations if they can figure out that values are 32-bit integers. Patterns like (a + b)|0 are emitted by Emscripten (asm.js), and JIT engines will recognise those and generate really good code for these!

Prior art: The following other compile-to-javascript languages all use 32-bit integer semantics for their respective natural numbers type: Elm, Reason, F# uses int32 by default and has a separate bigint type, PureScript uses 32-bit semantics for all operations except division where it matches Gleams implementation, Scala.js, js_of_ocaml. I have in fact not found one that doesn't do that at least as a default.

Many thanks also to Jak for opening this issue!! ~ 💜

@lpil
Copy link
Member

lpil commented Feb 16, 2025

We deliberately moved away from this as it was repeatedly resulting in surprisingly bugs in real programs.

A future optimising compiler could apply this as an operation if we could infer the ints are small enough, but this seems unrelated to the changing of the bitwise functions?

@hayleigh-dot-dev
Copy link
Member

At the very least it would be good to document that this is surprisingly slow on the JavaScript target. "Surprising" in the sense that it is unreasonable to expect the conversion to BigInt and back without documentation.

Engines typically have an optimisation for BigInt operations performed on fixed-sized numbers. We should benchmark if wrapping our big int casts in BigInt.asIntN and fixing them to 64 bits triggers this and speeds things up.

@yoshi-monster
Copy link
Contributor

yoshi-monster commented Feb 16, 2025

That's cool I didn't know about this method! Unfortunately, asIntN requires its argument to already be a BigInt, so it makes things strictly worse:

Input               Function                       IPS           Min           P99
input               stdlib                   1291.0057        0.6915        0.8967
input               native                  90096.9753        0.0094        0.0619
input               asIntN                   1040.2527        0.8785        1.1372

this is 10k runs each call to minimize gleamy_bench/function call overhead)

@hayleigh-dot-dev
Copy link
Member

hayleigh-dot-dev commented Feb 16, 2025

but they are more commonly used for manipulating bits which this proposal seems to make impossible as the results are no longer reliable

Because we cast the operation back down to number anyway isnt it already unreliable to manipulate bits on the JavaScript target? We currently do undocumented lossy truncation of results larger than 64 bits vs a platform-defined truncation of values larger than 32 bits.

@lpil
Copy link
Member

lpil commented Feb 16, 2025

No because integer size is documented. Making is smaller does not change that, would be a breaking change in the language, and repeatedly caused problems in real applications when we did use such small ints.

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

No branches or pull requests

4 participants