corert
corert copied to clipboard
How to implement Random.NextDouble for wasm
I want to create some c# that ultimately goes to JS Math.random to implement some thing like NextDouble in the Random class. I see when I compile HelloWorld to asm.js calls to clock() declared as:
[DllImport("*")]
private static unsafe extern long clock();
are translated into some predifined js, but how does that happen and is there a list of symbols that can be imported like this. I though it might be symbols from libc but trying to extern rand()
[DllImport("*")]
private static unsafe extern long rand();
Just causes a trap to be generated. Following on from this would be the question, is this the right direction to take if System.Random was to be implemented for wasm target?
rand returns int not long so answering the first part myself, if you get the import wrong then naturally things don't work. Curious about the second part though, what would be the right approach for System.Random under wasm?
cc @morganbr
@yowl, there are several parts to this question:
-
Q: How do libc calls work? A: Emscripten has a miniature implementation of libc, partially in wasm and partially in JavaScript. When it sees calls for those, it generates the appropriate glue code.
-
Q: How do other calls to JavaScript work? A: We haven't built any of those yet, but we'll almost certainly need them for things like cryptography and networking. Emscripten seems to provide a couple of ways to do it, using EM_JS/EM_ASM or with embind. Eventually, we'll probably want some way for C# developers to write a P/Invoke equivalent to JavaScript. I think the Mono wasm implementation has a tool for this, but I don't know much about it.
-
Q: How should we factor calls from Framework assemblies to JavaScript? A: This probably depends a bit on the exact answer to the previous question, but my initial guess is that wasm should follow the C++ PAL factoring that we use for *Nix (where the framework P/Invokes into some C++ code that makes the call). That helps us in a couple ways: a. It lets us reuse large portions of the existing *Nix PAL where Emscripten already provides an implementation of whatever we're calling. b. It looks like the facilities Emscripten provides are intended to be used from C++ (though perhaps we could do it with LLVM bitcode somehow).
-
Q: What do I do if I want a random number right now? A: Probably what you've already done: P/Invoke
rand()and coerce it to a double.
Thanks, so the current stack for Random.NextDouble ends with
_SystemNative_GetNonCryptographicallySecureRandomBytes@http://localhost:6931/HelloWasm.js:2012:98
_S_P_CoreLib_Interop__GetRandomBytes@http://localhost:6931/HelloWasm.js:1055203:1
_S_P_CoreLib_System_Random__GenerateGlobalSeed@http://localhost:6931/HelloWasm.js:755763:1
_S_P_CoreLib_System_Random___cctor@http://localhost:6931/HelloWasm.js:755461:1
_S_P_CoreLib_System_Runtime_CompilerServices_ClassConstructorRunner__Call_Int32_@http://localhost:6931/HelloWasm.js:530215:1
_S_P_CoreLib_System_Runtime_CompilerServices_ClassConstructorRunner__EnsureClassConstructorRun@http://localhost:6931/HelloWasm.js:497362:1
_S_P_CoreLib_System_Random__GenerateSeed@http://localhost:6931/HelloWasm.js:751509:1
_S_P_CoreLib_System_Random___ctor@http://localhost:6931/HelloWasm.js:725094:1
And if you look in Interop.GetRandomBytes you see
internal unsafe partial class Sys
{
[DllImport(Interop.Libraries.SystemNative, EntryPoint = "SystemNative_GetNonCryptographicallySecureRandomBytes")]
internal static extern unsafe void GetNonCryptographicallySecureRandomBytes(byte* buffer, int length);
}
To implement this properly for wasm, at what point should it break out into wasm specific code and how is that done, with #if or something more sophisticated? Anything similar in terms of wasm specific implementations of the framework that can be learned from?
@yowl, thought you might be interested in https://github.com/dotnet/runtime/pull/37408. With the next <RuntimeLibrariesVersion bump in CoreRT, it might unblock this issue.
@am11 thanks for the heads up. Looks like that will do the trick here also.