Skip to content

Commit

Permalink
Add new Mono embedding API to consume binary runtimeconfig format (#4…
Browse files Browse the repository at this point in the history
…9740)

* 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) <akliger@gmail.com>

* Update src/mono/mono/metadata/appdomain.c

Co-authored-by: Aleksey Kliger (λgeek) <akliger@gmail.com>

* Update src/mono/mono/metadata/appdomain.c

Co-authored-by: Aleksey Kliger (λgeek) <akliger@gmail.com>

* Update src/mono/mono/metadata/appdomain.c

Co-authored-by: Ryan Lucia <ryan@luciaonline.net>

* Update src/mono/mono/metadata/appdomain.c

Co-authored-by: Ryan Lucia <ryan@luciaonline.net>

* Update src/mono/mono/metadata/appdomain.c

Co-authored-by: Ryan Lucia <ryan@luciaonline.net>

* Update src/mono/mono/metadata/appdomain.c

Co-authored-by: Ryan Lucia <ryan@luciaonline.net>

* Update src/mono/mono/metadata/appdomain.c

Co-authored-by: Ryan Lucia <ryan@luciaonline.net>

* Update src/mono/mono/metadata/appdomain.c

Co-authored-by: Ryan Lucia <ryan@luciaonline.net>

* Update src/mono/mono/metadata/appdomain.c

Co-authored-by: Ryan Lucia <ryan@luciaonline.net>

* Remove redundant intermediate copy

* Remove extra memory allocation

* Update src/mono/mono/mini/mono-private-unstable.h

Co-authored-by: Ryan Lucia <ryan@luciaonline.net>

Co-authored-by: Aleksey Kliger (λgeek) <akliger@gmail.com>
Co-authored-by: Ryan Lucia <ryan@luciaonline.net>
  • Loading branch information
3 people authored Mar 22, 2021
1 parent 9051303 commit d318fd1
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 9 deletions.
130 changes: 121 additions & 9 deletions src/mono/mono/metadata/appdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
}
4 changes: 4 additions & 0 deletions src/mono/mono/metadata/domain-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <mono/metadata/loader-internals.h>
#include <mono/metadata/mempool-internals.h>
#include <mono/metadata/handle-decl.h>
#include <mono/mini/mono-private-unstable.h>

G_BEGIN_DECLS

Expand Down Expand Up @@ -449,6 +450,9 @@ mono_domain_get_assemblies (MonoDomain *domain);
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);

Expand Down
18 changes: 18 additions & 0 deletions src/mono/mono/mini/mono-private-unstable.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@
#include <mono/utils/mono-publib.h>
#include <mono/metadata/image.h>

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
Expand All @@ -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);

Expand Down
8 changes: 8 additions & 0 deletions src/mono/mono/mini/monovm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down

0 comments on commit d318fd1

Please sign in to comment.