Skip to content
Merged
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);
assert (assembly);
MonoClass* class = mono_wasm_assembly_find_class (assembly, nspace, typeName);
Comment thread
lewing marked this conversation as resolved.
Outdated
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);
}
2 changes: 2 additions & 0 deletions src/mono/browser/runtime/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ 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
5 changes: 0 additions & 5 deletions src/mono/sample/wasi/native/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ public static int MyExport(int number)
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();
}

MyImport();
return 0;
}
Expand Down
19 changes: 18 additions & 1 deletion src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,14 @@ private void EmitNativeToInterp(StreamWriter w, List<PInvokeCallback> callbacks)
// Only blittable parameter/return types are supposed.
int cb_index = 0;

w.Write(@"#include <mono/utils/details/mono-error-types.h>
#include <mono/metadata/assembly.h>
#include <mono/utils/mono-error.h>
#include <mono/metadata/object.h>
#include <mono/utils/details/mono-logger-types.h>
#include ""runtime.h""
");

// Arguments to interp entry functions in the runtime
w.WriteLine($"InterpFtnDesc wasm_native_to_interp_ftndescs[{callbacks.Count}] = {{}};");

Expand Down Expand Up @@ -371,7 +379,16 @@ 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");
// 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");
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");
Comment thread
mkhamoyan marked this conversation as resolved.
Outdated
sb.Append($" }}\n");

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