From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 22 Mar 2021 15:55:36 +0000 (-0400) Subject: Add new Mono embedding API to consume binary runtimeconfig format (#49740) X-Git-Tag: submit/tizen/20210909.063632~2519 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d318fd1c15f69cd7dd07ec6969daf2a349ed3070;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Add new Mono embedding API to consume binary runtimeconfig format (#49740) * Add new Mono embedding API to consume binary runtimeconfig format * Merge properties * Remove redundant macro * Move string process to the install function * Check if runtime_config_arg exist * Move file processing to install function * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Aleksey Kliger (λgeek) * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Aleksey Kliger (λgeek) * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Aleksey Kliger (λgeek) * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Ryan Lucia * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Ryan Lucia * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Ryan Lucia * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Ryan Lucia * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Ryan Lucia * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Ryan Lucia * Update src/mono/mono/metadata/appdomain.c Co-authored-by: Ryan Lucia * Remove redundant intermediate copy * Remove extra memory allocation * Update src/mono/mono/mini/mono-private-unstable.h Co-authored-by: Ryan Lucia Co-authored-by: Aleksey Kliger (λgeek) Co-authored-by: Ryan Lucia --- diff --git a/src/mono/mono/metadata/appdomain.c b/src/mono/mono/metadata/appdomain.c index 170560c..a8a7c59 100644 --- a/src/mono/mono/metadata/appdomain.c +++ b/src/mono/mono/metadata/appdomain.c @@ -92,8 +92,12 @@ typedef struct static gboolean no_exec = FALSE; static int n_appctx_props; -static gunichar2 **appctx_keys; -static gunichar2 **appctx_values; +static char **appctx_keys; +static char **appctx_values; + +static MonovmRuntimeConfigArguments *runtime_config_arg; +static MonovmRuntimeConfigArgumentsCleanup runtime_config_cleanup_fn; +static gpointer runtime_config_user_data; static const char * mono_check_corlib_version_internal (void); @@ -122,6 +126,12 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht) static void add_assembly_to_alc (MonoAssemblyLoadContext *alc, MonoAssembly *ass); +static const char * +runtimeconfig_json_get_buffer (MonovmRuntimeConfigArguments *arg, MonoFileMap **file_map, gpointer *buf_handle); + +static void +runtimeconfig_json_read_props (const char *ptr, const char **endp, int nprops, gunichar2 **dest_keys, gunichar2 **dest_values); + static MonoLoadFunc load_function = NULL; /* Lazy class loading functions */ @@ -1239,15 +1249,23 @@ void mono_runtime_register_appctx_properties (int nprops, const char **keys, const char **values) { n_appctx_props = nprops; - appctx_keys = g_new0 (gunichar2*, nprops); - appctx_values = g_new0 (gunichar2*, nprops); + appctx_keys = g_new0 (char *, n_appctx_props); + appctx_values = g_new0 (char *, n_appctx_props); for (int i = 0; i < nprops; ++i) { - appctx_keys [i] = g_utf8_to_utf16 (keys [i], strlen (keys [i]), NULL, NULL, NULL); - appctx_values [i] = g_utf8_to_utf16 (values [i], strlen (values [i]), NULL, NULL, NULL); + appctx_keys [i] = g_strdup (keys [i]); + appctx_values [i] = g_strdup (values [i]); } } +void +mono_runtime_register_runtimeconfig_json_properties (MonovmRuntimeConfigArguments *arg, MonovmRuntimeConfigArgumentsCleanup cleanup_fn, void *user_data) +{ + runtime_config_arg = arg; + runtime_config_cleanup_fn = cleanup_fn; + runtime_config_user_data = user_data; +} + static GENERATE_GET_CLASS_WITH_CACHE (appctx, "System", "AppContext") /* Install properties into AppContext */ @@ -1256,27 +1274,121 @@ mono_runtime_install_appctx_properties (void) { ERROR_DECL (error); gpointer args [3]; + int n_runtimeconfig_json_props = 0; + int n_combined_props; + gunichar2 **combined_keys; + gunichar2 **combined_values; + MonoFileMap *runtimeconfig_json_map = NULL; + gpointer runtimeconfig_json_map_handle = NULL; + const char *buffer_start = runtimeconfig_json_get_buffer (runtime_config_arg, &runtimeconfig_json_map, &runtimeconfig_json_map_handle); + const char *buffer = buffer_start; MonoMethod *setup = mono_class_get_method_from_name_checked (mono_class_get_appctx_class (), "Setup", 3, 0, error); g_assert (setup); // FIXME: TRUSTED_PLATFORM_ASSEMBLIES is very large + // Combine and convert properties + if (buffer) + n_runtimeconfig_json_props = mono_metadata_decode_value (buffer, &buffer); + + n_combined_props = n_appctx_props + n_runtimeconfig_json_props; + combined_keys = g_new0 (gunichar2 *, n_combined_props); + combined_values = g_new0 (gunichar2 *, n_combined_props); + + for (int i = 0; i < n_appctx_props; ++i) { + combined_keys [i] = g_utf8_to_utf16 (appctx_keys [i], -1, NULL, NULL, NULL); + combined_values [i] = g_utf8_to_utf16 (appctx_values [i], -1, NULL, NULL, NULL); + } + + runtimeconfig_json_read_props (buffer, &buffer, n_runtimeconfig_json_props, combined_keys + n_appctx_props, combined_values + n_appctx_props); + /* internal static unsafe void Setup(char** pNames, char** pValues, int count) */ - args [0] = appctx_keys; - args [1] = appctx_values; - args [2] = &n_appctx_props; + args [0] = combined_keys; + args [1] = combined_values; + args [2] = &n_combined_props; mono_runtime_invoke_checked (setup, NULL, args, error); mono_error_assert_ok (error); + if (runtimeconfig_json_map != NULL) { + mono_file_unmap ((gpointer)buffer_start, runtimeconfig_json_map_handle); + mono_file_map_close (runtimeconfig_json_map); + } + + // Call user defined cleanup function + if (runtime_config_cleanup_fn) + (*runtime_config_cleanup_fn) (runtime_config_arg, runtime_config_user_data); + /* No longer needed */ + for (int i = 0; i < n_combined_props; ++i) { + g_free (combined_keys [i]); + g_free (combined_values [i]); + } + g_free (combined_keys); + g_free (combined_values); for (int i = 0; i < n_appctx_props; ++i) { g_free (appctx_keys [i]); g_free (appctx_values [i]); } g_free (appctx_keys); g_free (appctx_values); + appctx_keys = NULL; appctx_values = NULL; + if (runtime_config_arg) { + runtime_config_arg = NULL; + runtime_config_cleanup_fn = NULL; + runtime_config_user_data = NULL; + } +} + +static const char * +runtimeconfig_json_get_buffer (MonovmRuntimeConfigArguments *arg, MonoFileMap **file_map, gpointer *buf_handle) +{ + if (arg != NULL) { + switch (arg->kind) { + case 0: { + char *buffer = NULL; + guint64 file_len = 0; + + *file_map = mono_file_map_open (arg->runtimeconfig.name.path); + g_assert (*file_map); + file_len = mono_file_map_size (*file_map); + g_assert (file_len > 0); + buffer = (char *)mono_file_map (file_len, MONO_MMAP_READ|MONO_MMAP_PRIVATE, mono_file_map_fd (*file_map), 0, buf_handle); + g_assert (buffer); + return buffer; + } + case 1: { + *file_map = NULL; + *buf_handle = NULL; + return arg->runtimeconfig.data.data; + } + default: + g_assert_not_reached (); + } + } + + *file_map = NULL; + *buf_handle = NULL; + return NULL; +} + +static void +runtimeconfig_json_read_props (const char *ptr, const char **endp, int nprops, gunichar2 **dest_keys, gunichar2 **dest_values) +{ + for (int i = 0; i < nprops; ++i) { + int str_len; + + str_len = mono_metadata_decode_value (ptr, &ptr); + dest_keys [i] = g_utf8_to_utf16 (ptr, str_len, NULL, NULL, NULL); + ptr += str_len; + + str_len = mono_metadata_decode_value (ptr, &ptr); + dest_values [i] = g_utf8_to_utf16 (ptr, str_len, NULL, NULL, NULL); + ptr += str_len; + } + + *endp = ptr; } diff --git a/src/mono/mono/metadata/domain-internals.h b/src/mono/mono/metadata/domain-internals.h index 9521b9c..fb17d9f 100644 --- a/src/mono/mono/metadata/domain-internals.h +++ b/src/mono/mono/metadata/domain-internals.h @@ -20,6 +20,7 @@ #include #include #include +#include G_BEGIN_DECLS @@ -450,6 +451,9 @@ void mono_runtime_register_appctx_properties (int nprops, const char **keys, const char **values); void +mono_runtime_register_runtimeconfig_json_properties (MonovmRuntimeConfigArguments *arg, MonovmRuntimeConfigArgumentsCleanup cleanup_fn, void *user_data); + +void mono_runtime_install_appctx_properties (void); gboolean diff --git a/src/mono/mono/mini/mono-private-unstable.h b/src/mono/mono/mini/mono-private-unstable.h index 4d746dd..b8e6724 100644 --- a/src/mono/mono/mini/mono-private-unstable.h +++ b/src/mono/mono/mini/mono-private-unstable.h @@ -15,6 +15,21 @@ #include #include +typedef struct { + uint32_t kind; // 0 = Path of runtimeconfig.blob, 1 = pointer to image data, >= 2 undefined + union { + struct { + const char *path; + } name; + struct { + const char *data; + uint32_t data_len; + } data; + } runtimeconfig; +} MonovmRuntimeConfigArguments; + +typedef void (*MonovmRuntimeConfigArgumentsCleanup) (MonovmRuntimeConfigArguments *args, void *user_data); + /* These are used to load the AOT data for aot images compiled with MONO_AOT_FILE_FLAG_SEPARATE_DATA */ /* * Return the AOT data for ASSEMBLY. SIZE is the size of the data. OUT_HANDLE should be set to a handle which is later @@ -29,6 +44,9 @@ mono_install_load_aot_data_hook (MonoLoadAotDataFunc load_func, MonoFreeAotDataF MONO_API int monovm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues); +MONO_API int +monovm_runtimeconfig_initialize (MonovmRuntimeConfigArguments *arg, MonovmRuntimeConfigArgumentsCleanup cleanup_fn, void *user_data); + //#ifdef HOST_WASM typedef void* (*MonoWasmGetNativeToInterpTramp) (MonoMethod *method, void *extra_arg); diff --git a/src/mono/mono/mini/monovm.c b/src/mono/mono/mini/monovm.c index ad6be1c..a993480 100644 --- a/src/mono/mono/mini/monovm.c +++ b/src/mono/mono/mini/monovm.c @@ -226,6 +226,14 @@ monovm_initialize (int propertyCount, const char **propertyKeys, const char **pr return 0; } +// Initialize monovm with properties set by runtimeconfig.json. Primarily used by mobile targets. +int +monovm_runtimeconfig_initialize (MonovmRuntimeConfigArguments *arg, MonovmRuntimeConfigArgumentsCleanup cleanup_fn, void *user_data) +{ + mono_runtime_register_runtimeconfig_json_properties (arg, cleanup_fn, user_data); + return 0; +} + int monovm_execute_assembly (int argc, const char **argv, const char *managedAssemblyPath, unsigned int *exitCode) {