-
Notifications
You must be signed in to change notification settings - Fork 199
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
[NativeAOT-LLVM] Delegates marshalling is broken in some scenarios #2624
Comments
This was also discussed on Discord as the problem hit on Avalonia bring-up. I have since looked into what it would take to implement the thunk pool on Browser. It is possible in principle, but it doesn't fit into the shape of the existing code well because we need to know the exact signatures for Emscripten's Not that we shouldn't implement it, of course. |
A solution with these properties is not very compatible with native aot design principles. |
Indeed. Perhaps, what we could do instead is:
The advantage is that instantiating a module does not require a lot of resources in the engine, since the compiled code is shared between instantiations (in .NET terms, modules are 'domain-neutral' 😄). The disadvantage of the scheme as detailed above is that if we need only one kind of thunk signature a lot, the module with all of the signatures will be repeatedly instantiated. I don't know if the instantiation cost scales with the code size of the module (it obviously does scale with the size of the data unique to the module). If it turns out to be a problem, we can instead have one module per one signature (and thus export). That would lead to more modules instantiated in the usual case, however. |
I would say that the libraries have to convert to use function pointers if they want to use native AOT w/ wasm. It is not that hard to do and guaranteed to have the desired perf characteristics. Mono does not implement full delegate marshalling for wasm either. Is that correct? |
Yes. It implements enough for a certain narrow scenario - open static delegate pointing to an adorned method - to work. Here's the change implementing this happy path: dotnet/runtime#38932. The PI table task generates a statically-sized number of native functions that are, though a couple of layers, returned by typedef void (*WasmInterpEntrySig_3) (int*, int*, int*, int*, int*, int*, int*, int*);
int32_t wasm_native_to_interp_System_Private_CoreLib_ComponentActivator_GetFunctionPointer (void * arg0, void * arg1, void * arg2, void * arg3, void * arg4, void * arg5) {
int32_t res;
if (!(WasmInterpEntrySig_3)wasm_native_to_interp_ftndescs [3].func) {
mono_wasm_marshal_get_managed_wrapper ("System.Private.CoreLib", "Internal.Runtime.InteropServices.ComponentActivator", "GetFunctionPointer", 6);
}
((WasmInterpEntrySig_3)wasm_native_to_interp_ftndescs [3].func) ((int*)&res, (int*)&arg0, (int*)&arg1, (int*)&arg2, (int*)&arg3, (int*)&arg4, (int*)&arg5, wasm_native_to_interp_ftndescs [3].arg);
return res;
}
typedef void (*WasmInterpEntrySig_4) (int*, int*, int*);
void wasm_native_to_interp_System_Private_CoreLib_CalendarData_EnumCalendarInfoCallback (void * arg0, void * arg1) {
if (!(WasmInterpEntrySig_4)wasm_native_to_interp_ftndescs [4].func) {
mono_wasm_marshal_get_managed_wrapper ("System.Private.CoreLib", "System.Globalization.CalendarData", "EnumCalendarInfoCallback", 2);
}
((WasmInterpEntrySig_4)wasm_native_to_interp_ftndescs [4].func) ((int*)&arg0, (int*)&arg1, wasm_native_to_interp_ftndescs [4].arg);
}
typedef void (*WasmInterpEntrySig_5) (int*);
void wasm_native_to_interp_System_Private_CoreLib_ThreadPool_BackgroundJobHandler () {
if (!(WasmInterpEntrySig_5)wasm_native_to_interp_ftndescs [5].func) {
mono_wasm_marshal_get_managed_wrapper ("System.Private.CoreLib", "System.Threading.ThreadPool", "BackgroundJobHandler", 0);
}
((WasmInterpEntrySig_5)wasm_native_to_interp_ftndescs [5].func) (wasm_native_to_interp_ftndescs [5].arg);
} |
These examples are actually |
More or less. The delegate part of this scenario is enabled via |
Running SkiaSharp from NativeAOT-LLVM I noticed that it always fails on DllImports with managed delegates.
And more stacktrace:
The same delegates are properly marshalled with plain NativeAOT on desktop, as well as Mono WASM. This issue might be or might not be related to mono/SkiaSharp#1931.
Workaround - rewrite SkiaSharp to use function pointers instead (I am working on it right now).
Minimal repro (only SkiaSharp Bitmap decoding + HttpClient for demo):
naot-llvm-demo.zip
The text was updated successfully, but these errors were encountered: