-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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 splitI64 so it can be used to send values from JS libraries into wasm #19575
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you need/want this?
src/parseTools.js
Outdated
} | ||
return low + ', ' + high; | ||
return `(${name} | 0), (${name} / (2**32))`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like it should live in src/library_int53.js
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's such a tiny code fragment that I think it can stay in the helper function here? Pulling it out would then mean writing deps for it etc.
I do agree that if we add checking then that would be pulled into a library function, as that is no longer trivial.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a comment saying that this function logically is in the same family as the functions in src/library_int53.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code in library_int53.js uses expanded out numbers rather than 2**32
.
You could do that here by putting the 2**32 part inside a ${}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, why are we expanding them there? It's larger to expand. I think we should 2**32
ify them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well we should at least be consistent. I don't really care which form we use. If you want to use the expanded form in the PR and followup with change to the runtime multiple everywhere that is also fine be me.
Sorry @sbc100 , we discussed this a few days ago but I should have written the context. @jameshu15869 has a few PRs up for WasmFS in which the WasmFS JS API needs to call into wasm, say to do |
I tried using this PR with the
|
After discussion with @tlively and @jameshu15869 , the first thing we need is the signed version actually. I uploaded that now, and also moved the function to the JS library as you requested @sbc100 @jameshu15869 I added a test for -42 here specifically, which now seems to pass. With that said, I had thought the math here was trickier than it turned out when I did it now... so I worry I'm forgetting something. But perhaps the tricky part is to handle things outside of the i53 range, which we don't care about... |
src/library_int53.js
Outdated
global.i53ConversionDeps = [ | ||
'$convertI32PairToI53Checked', | ||
'$sendI53BitsLow', | ||
'$sendI53BitsHigh', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this since the latter two will very rarely be used.. unlike the first one which is basically used everywhere.
src/library_int53.js
Outdated
// TODO: assert on num being in the valid i53 range | ||
num = Math.floor(num / 4294967296); | ||
return num | 0; | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not make make a single I53 split function that returns the high/low pair?
Now that I think of that I remember there is an existing splitI64
in parseTools.js.. maybe we don't want to keep both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah for now maybe just use splitI64
and we can think of simplifying it later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that method is large and complex because (1) it handles non-i53 values and (2) it isn't clear on whether the input is signed or unsigned, and I think it tries to handle both. This PR's method assumes the input is a signed i53 which simplifies things a lot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the purposes of the change in question isn't splitI64
OK though? If you want to add an alternative to splitI64
maybe just add splitI53
alongside it with a comment as to why its different? Perhaps we don't need splitI64
anymore at all? I'd like to avoid duplicating its functionality though.. maybe this is good change to clean things up.
How about this:
- Land the current wasmfs changes using the existing splitI64
- Look into optimizing/removing/refactoring splitI64 as a followup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, if you prefer that I don't feel strongly. I changed it to that.
When we look at code size for WasmFS perhaps we can get back to this.
src/library_int53.js
Outdated
$sendI53BitsHigh: function(num) { | ||
// TODO: assert on num being in the valid i53 range | ||
num = Math.floor(num / 4294967296); | ||
return num | 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we use the send
and receive
naming still widely? I always thought those terms confusing, since from static reading of an individual function, it is not clear where the data is supposed to be flowing, and what side should be considered the sender, and which one should be regarded the receiver.
I know there is a comment there to explain, but it seems like the name choice makes the comment mandatory?
It would be nice to avoid send and receive terms if possible. Maybe these could be named getLowI32Part(num)
and getHighI32Part(num)
instead?
The impl could read Math.floor(num / 4294967296) | 0;
without loss on readability?
For the TODO, maybe expanding the comment with
// You can use assert(Number.isSafeInteger(num)); to verify that a given number
// can be converted without precision loss.
could be used, so the caller can emit or not emit such an assert, depending on their use case whether they accept lossy conversion or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback! Meanwhile though I just removed all this code for now. But we may get back to it as an optimization later.
I do agree the names are ambiguous. Perhaps forCallToWasm
or such would make it more clear..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whats wrong with just splitI53
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with PR title and description updated.
When a JS library calls into wasm and the function has an i64 argument, we must
legalize into two 32-bit integers if we lack BigInt support.
Note that we may be able to do more efficient things than
splitI64
(assumingthe input uses only 53 bits, and is signed, can help simplify things a lot), but we
leave that for optimization later.
This removes the old/unused
sendI64Argument
.