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

[mono][wasm] Force interpreter to initialize the pointers #100288

Merged
merged 13 commits into from
Mar 28, 2024
6 changes: 6 additions & 0 deletions src/mono/browser/runtime/pinvoke.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#include "wasm-config.h"
#include "pinvoke.h"
#include <mono/metadata/assembly.h>
#include <mono/utils/mono-error.h>
#include <mono/utils/details/mono-error-types.h>
#include <mono/utils/details/mono-logger-types.h>
#include <mono/metadata/object.h>
#include "runtime.h"

#include <stdint.h>

Expand Down
23 changes: 23 additions & 0 deletions src/mono/browser/runtime/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ int monoeg_g_setenv(const char *variable, const char *value, int overwrite);
int32_t mini_parse_debug_option (const char *option);
char *mono_method_get_full_name (MonoMethod *method);
void mono_trace_init (void);
MonoMethod *mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoGCHandle target_handle, MonoError *error);

/* Not part of public headers */
#define MONO_ICALL_TABLE_CALLBACKS_VERSION 3
Expand Down Expand Up @@ -356,3 +357,25 @@ mono_wasm_assembly_find_method (MonoClass *klass, const char *name, int argument
MONO_EXIT_GC_UNSAFE;
return result;
}

/*
* mono_wasm_marshal_get_managed_wrapper:
* Creates a wrapper for a function pointer to a method marked with
* UnamangedCallersOnlyAttribute.
* This wrapper ensures that the interpreter initializes the pointers.
*/
void
mono_wasm_marshal_get_managed_wrapper (const char* assemblyName, const char* nspace, const char* typeName, const char* methodName, int num_params)
{
MonoError error;
mono_error_init (&error);
MonoAssembly* assembly = mono_wasm_assembly_load (assemblyName);
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
assert (assembly);
MonoClass* class = mono_wasm_assembly_find_class (assembly, nspace, typeName);
assert (class);
MonoMethod* method = mono_wasm_assembly_find_method (class, methodName, num_params);
assert (method);
MonoMethod *managedWrapper = mono_marshal_get_managed_wrapper (method, NULL, 0, &error);
assert (managedWrapper);
mono_compile_method (managedWrapper);
}
3 changes: 3 additions & 0 deletions src/mono/browser/runtime/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
#include <mono/metadata/mono-gc.h>
#include <mono/metadata/object.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/utils/details/mono-logger-types.h>

extern int mono_wasm_enable_gc;

MonoDomain *mono_wasm_load_runtime_common (int debug_level, MonoLogCallback log_callback, const char *interp_opts);
MonoAssembly *mono_wasm_assembly_load (const char *name);
MonoClass *mono_wasm_assembly_find_class (MonoAssembly *assembly, const char *namespace, const char *name);
MonoMethod *mono_wasm_assembly_find_method (MonoClass *klass, const char *name, int arguments);
void mono_wasm_marshal_get_managed_wrapper (const char* assemblyName, const char* nspace, const char* typeName, const char* methodName, int num_params);

#endif
6 changes: 3 additions & 3 deletions src/mono/sample/wasi/native/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public unsafe static int Main(string[] args)
{
Console.WriteLine($"main: {args.Length}");
// workaround to force the interpreter to initialize wasm_native_to_interp_ftndesc for MyExport
if (args.Length > 10000) {
((IntPtr)(delegate* unmanaged<int,int>)&MyExport).ToString();
}
// if (args.Length > 10000) {
// ((IntPtr)(delegate* unmanaged<int,int>)&MyExport).ToString();
// }

MyImport();
return 0;
Expand Down
18 changes: 17 additions & 1 deletion src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,23 @@ private void EmitNativeToInterp(StreamWriter w, List<PInvokeCallback> callbacks)
if (!is_void)
sb.Append($" {MapType(method.ReturnType)} res;\n");

//sb.Append($" printf(\"{entry_name} called\\n\");\n");
sb.Append("#include <stdio.h>\n");
// In case when null force interpreter to initialize the pointers
sb.Append($" if (!(WasmInterpEntrySig_{cb_index})wasm_native_to_interp_ftndescs [{cb_index}].func) {{\n");
sb.Append("#include <mono/utils/details/mono-error-types.h>\n");
sb.Append("#include <mono/metadata/assembly.h>\n");
sb.Append("#include <mono/utils/mono-error.h>\n");
sb.Append("#include <mono/metadata/object.h>\n");
sb.Append("#include <mono/utils/details/mono-logger-types.h>\n");
sb.Append("#include \"runtime.h\"\n");
var assemblyFullName = cb.Method.DeclaringType == null ? "" : cb.Method.DeclaringType.Assembly.FullName;
var assemblyName = assemblyFullName != null && assemblyFullName.Split(',').Length > 0 ? assemblyFullName.Split(',')[0].Trim() : "";
var typeName = cb.Method.DeclaringType == null || cb.Method.DeclaringType.FullName == null ? "" : cb.Method.DeclaringType.FullName;
var methodName = cb.Method.Name;
int numParams = method.GetParameters().Length;
sb.Append($" mono_wasm_marshal_get_managed_wrapper (\"{assemblyName}\", \"{string.Empty}\", \"{typeName}\", \"{methodName}\", {numParams});\n");
mkhamoyan marked this conversation as resolved.
Show resolved Hide resolved
sb.Append($" }}\n");

sb.Append($" ((WasmInterpEntrySig_{cb_index})wasm_native_to_interp_ftndescs [{cb_index}].func) (");
if (!is_void)
{
Expand Down
Loading