From 9aa19cb3ec2793a7f9e4373b7be7aeeabd0dc760 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Wed, 25 Jan 2017 13:53:46 -0500 Subject: [PATCH] [appdomain] Use coop handles for most methods in System.AppDomain (#4286) * [runtime] Use coop handles for ves_icall_System_AppDomain_GetData * [runtime] Add mono_string_new_utf16_handle function that returns a MonoStringHandle * [runtime] Use coop handles for ves_icall_System_AppDomain_InternalGetProcessGuid * [runtime] Use coop handles for System.AppDomain icalls - ves_icall_System_AppDomain_InternalIsFinalizingForUnload - ves_icall_System_AppDomain_InternalPushDomainRef - ves_icall_System_AppDomain_InternalPushDomainRefByID (This one is slightly non-trivial because we switch from MonoException to MonoError) - ves_icall_System_AppDomain_InternalPopDomainRef - ves_icall_System_AppDomain_InternalSetDomainByID * [runtime] Use coop handles for ves_icall_System_AppDomain_InternalSetDomain * [runtime] Use coop handles for ves_icall_System_AppDomain_SetData * [runtime] Coop handles for some AppDomain icalls - ves_icall_System_AppDomain_getCurDomain - ves_icall_System_AppDomain_getFriendlyName - ves_icall_System_AppDomain_getRootDomain - ves_icall_System_AppDomain_getSetup * [coop handles] Add mono_string_handle_length function * [marshal] Add mono_marshal_xdomain_copy_value_handle * [coop handles] Add mono_aray_new_full_handle * [appdomain] Use handles in mono_array_clone_in_domain * [runtime] Use coop handles for ves_icall_System_AppDomain_createDomain * [appdomain] Use coop handles for ves_icall_System_AppDomain_InternalUnload --- mono/metadata/appdomain-icalls.h | 62 +++-- mono/metadata/appdomain.c | 424 ++++++++++++++++++------------ mono/metadata/appdomain.h | 1 + mono/metadata/handle.c | 6 + mono/metadata/handle.h | 3 + mono/metadata/icall-def.h | 30 +-- mono/metadata/marshal-internals.h | 3 + mono/metadata/object-internals.h | 13 +- mono/metadata/object.c | 131 +++++---- mono/metadata/remoting.c | 104 ++++++-- 10 files changed, 487 insertions(+), 290 deletions(-) diff --git a/mono/metadata/appdomain-icalls.h b/mono/metadata/appdomain-icalls.h index a0687a43c0c..63e17e2dded 100644 --- a/mono/metadata/appdomain-icalls.h +++ b/mono/metadata/appdomain-icalls.h @@ -11,19 +11,21 @@ #include #include -MonoAppDomain * -ves_icall_System_AppDomain_getCurDomain (void); +MonoAppDomainHandle +ves_icall_System_AppDomain_getCurDomain (MonoError *error); -MonoAppDomain * -ves_icall_System_AppDomain_getRootDomain (void); +MonoAppDomainHandle +ves_icall_System_AppDomain_getRootDomain (MonoError *error); -MonoAppDomain * -ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, - MonoAppDomainSetup *setup); +MonoAppDomainHandle +ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name, + MonoAppDomainSetupHandle setup, + MonoError *error); -MonoObject * -ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, - MonoString *name); +MonoObjectHandle +ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad, + MonoStringHandle name, + MonoError* error); MonoReflectionAssemblyHandle ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad, @@ -34,15 +36,18 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad, MonoError *error); void -ves_icall_System_AppDomain_SetData (MonoAppDomain *ad, - MonoString *name, - MonoObject *data); +ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad, + MonoStringHandle name, + MonoObjectHandle data, + MonoError *error); -MonoAppDomainSetup * -ves_icall_System_AppDomain_getSetup (MonoAppDomain *ad); +MonoAppDomainSetupHandle +ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad, + MonoError *error); -MonoString * -ves_icall_System_AppDomain_getFriendlyName (MonoAppDomain *ad); +MonoStringHandle +ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad, + MonoError *error); MonoArrayHandle ves_icall_System_AppDomain_GetAssemblies (MonoAppDomainHandle ad, @@ -62,10 +67,11 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomainHandle ad, MonoError *error); gboolean -ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id); +ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, MonoError *error); void -ves_icall_System_AppDomain_InternalUnload (gint32 domain_id); +ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, + MonoError *error); void ves_icall_System_AppDomain_DoUnhandledException (MonoException *exc); @@ -76,20 +82,20 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomainHandle ad, MonoArrayHandle args, MonoError *error); -MonoAppDomain * -ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomain *ad); +MonoAppDomainHandle +ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad, MonoError *error); -MonoAppDomain * -ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid); +MonoAppDomainHandle +ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid, MonoError *error); void -ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomain *ad); +ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad, MonoError *error); void -ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id); +ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id, MonoError *error); void -ves_icall_System_AppDomain_InternalPopDomainRef (void); +ves_icall_System_AppDomain_InternalPopDomainRef (MonoError *error); MonoAppContext * ves_icall_System_AppDomain_InternalGetContext (void); @@ -103,8 +109,8 @@ ves_icall_System_AppDomain_InternalSetContext (MonoAppContext *mc); gint32 ves_icall_System_AppDomain_GetIDFromDomain (MonoAppDomain * ad); -MonoString * -ves_icall_System_AppDomain_InternalGetProcessGuid (MonoString* newguid); +MonoStringHandle +ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, MonoError *error); MonoBoolean ves_icall_System_CLRConfig_CheckThrowUnobservedTaskExceptions (void); diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index dc17ecc71c0..d7abbb593f3 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -117,8 +118,12 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data); static void add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *hash); -static MonoAppDomain * -mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetup *setup, MonoError *error); +static MonoAppDomainHandle +mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error); + +static MonoDomain * +mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error); + static char * get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error); @@ -130,6 +135,15 @@ static GENERATE_GET_CLASS_WITH_CACHE (assembly, System.Reflection, Assembly); static GENERATE_GET_CLASS_WITH_CACHE (appdomain, System, AppDomain); +static MonoDomain * +mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain); + +static void +mono_error_set_appdomain_unloaded (MonoError *error) +{ + mono_error_set_generic_error (error, "System", "AppDomainUnloadedException", ""); +} + void mono_install_runtime_load (MonoLoadFunc func) { @@ -446,25 +460,49 @@ mono_runtime_quit () MonoDomain * mono_domain_create_appdomain (char *friendly_name, char *configuration_file) { + HANDLE_FUNCTION_ENTER (); MonoError error; - MonoAppDomain *ad; - MonoAppDomainSetup *setup; - MonoClass *klass; + MonoDomain *domain = mono_domain_create_appdomain_checked (friendly_name, configuration_file, &error); + mono_error_cleanup (&error); + HANDLE_FUNCTION_RETURN_VAL (domain); +} - klass = mono_class_load_from_name (mono_defaults.corlib, "System", "AppDomainSetup"); - setup = (MonoAppDomainSetup *) mono_object_new_checked (mono_domain_get (), klass, &error); - if (!is_ok (&error)) - goto fail; - setup->configuration_file = configuration_file != NULL ? mono_string_new (mono_domain_get (), configuration_file) : NULL; +/** + * mono_domain_create_appdomain_checked: + * @friendly_name: The friendly name of the appdomain to create + * @configuration_file: The configuration file to initialize the appdomain with + * @error: Set on error. + * + * Returns a MonoDomain initialized with the appdomain. On failure sets @error and returns NULL. + */ +MonoDomain * +mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error) +{ + HANDLE_FUNCTION_ENTER (); + mono_error_init (error); + MonoDomain *result = NULL; - ad = mono_domain_create_appdomain_internal (friendly_name, setup, &error); - if (!is_ok (&error)) - goto fail; + MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System", "AppDomainSetup"); + MonoAppDomainSetupHandle setup = MONO_HANDLE_NEW (MonoAppDomainSetup, mono_object_new_checked (mono_domain_get (), klass, error)); + if (!is_ok (error)) + goto leave; + MonoStringHandle config_file; + if (configuration_file != NULL) { + config_file = mono_string_new_handle (mono_domain_get (), configuration_file, error); + if (!is_ok (error)) + goto leave; + } else { + config_file = MONO_HANDLE_NEW (MonoString, NULL); + } + MONO_HANDLE_SET (setup, configuration_file, config_file); - return mono_domain_from_appdomain (ad); -fail: - mono_error_cleanup (&error); - return NULL; + MonoAppDomainHandle ad = mono_domain_create_appdomain_internal (friendly_name, setup, error); + if (!is_ok (error)) + goto leave; + + result = mono_domain_from_appdomain_handle (ad); +leave: + HANDLE_FUNCTION_RETURN_VAL (result); } /** @@ -486,65 +524,77 @@ mono_domain_set_config (MonoDomain *domain, const char *base_dir, const char *co MONO_OBJECT_SETREF (domain->setup, configuration_file, mono_string_new (domain, config_file_name)); } -static MonoAppDomainSetup* -copy_app_domain_setup (MonoDomain *domain, MonoAppDomainSetup *setup, MonoError *error) +static MonoAppDomainSetupHandle +copy_app_domain_setup (MonoDomain *domain, MonoAppDomainSetupHandle setup, MonoError *error) { + HANDLE_FUNCTION_ENTER (); MonoDomain *caller_domain; MonoClass *ads_class; - MonoAppDomainSetup *copy; + MonoAppDomainSetupHandle result = MONO_HANDLE_NEW (MonoAppDomainSetup, NULL); mono_error_init (error); caller_domain = mono_domain_get (); ads_class = mono_class_load_from_name (mono_defaults.corlib, "System", "AppDomainSetup"); - copy = (MonoAppDomainSetup*)mono_object_new_checked (domain, ads_class, error); - return_val_if_nok (error, NULL); + MonoAppDomainSetupHandle copy = MONO_HANDLE_NEW (MonoAppDomainSetup, mono_object_new_checked (domain, ads_class, error)); + if (!is_ok (error)) + goto leave; mono_domain_set_internal (domain); -#define XCOPY_FIELD(dst,field,src,error) \ +#define XCOPY_FIELD(dst,field,src,error) \ do { \ - MonoObject *copied_val = mono_marshal_xdomain_copy_value ((MonoObject*)(src), error); \ - return_val_if_nok (error, NULL); \ - MONO_OBJECT_SETREF ((dst),field,copied_val); \ + MonoObjectHandle src_val = MONO_HANDLE_NEW_GET (MonoObject, (src), field); \ + MonoObjectHandle copied_val = mono_marshal_xdomain_copy_value_handle (src_val, error); \ + if (!is_ok (error)) \ + goto leave; \ + MONO_HANDLE_SET ((dst),field,copied_val); \ } while (0) - XCOPY_FIELD (copy, application_base, setup->application_base, error); - XCOPY_FIELD (copy, application_name, setup->application_name, error); - XCOPY_FIELD (copy, cache_path, setup->cache_path, error); - XCOPY_FIELD (copy, configuration_file, setup->configuration_file, error); - XCOPY_FIELD (copy, dynamic_base, setup->dynamic_base, error); - XCOPY_FIELD (copy, license_file, setup->license_file, error); - XCOPY_FIELD (copy, private_bin_path, setup->private_bin_path, error); - XCOPY_FIELD (copy, private_bin_path_probe, setup->private_bin_path_probe, error); - XCOPY_FIELD (copy, shadow_copy_directories, setup->shadow_copy_directories, error); - XCOPY_FIELD (copy, shadow_copy_files, setup->shadow_copy_files, error); - copy->publisher_policy = setup->publisher_policy; - copy->path_changed = setup->path_changed; - copy->loader_optimization = setup->loader_optimization; - copy->disallow_binding_redirects = setup->disallow_binding_redirects; - copy->disallow_code_downloads = setup->disallow_code_downloads; - XCOPY_FIELD (copy, domain_initializer_args, setup->domain_initializer_args, error); - copy->disallow_appbase_probe = setup->disallow_appbase_probe; - XCOPY_FIELD (copy, application_trust, setup->application_trust, error); - XCOPY_FIELD (copy, configuration_bytes, setup->configuration_bytes, error); - XCOPY_FIELD (copy, serialized_non_primitives, setup->serialized_non_primitives, error); - -#undef COPY_FIELD +#define COPY_VAL(dst,field,type,src) \ + do { \ + MONO_HANDLE_SETVAL ((dst), field, type, MONO_HANDLE_GETVAL ((src),field)); \ + } while (0) + + XCOPY_FIELD (copy, application_base, setup, error); + XCOPY_FIELD (copy, application_name, setup, error); + XCOPY_FIELD (copy, cache_path, setup, error); + XCOPY_FIELD (copy, configuration_file, setup, error); + XCOPY_FIELD (copy, dynamic_base, setup, error); + XCOPY_FIELD (copy, license_file, setup, error); + XCOPY_FIELD (copy, private_bin_path, setup, error); + XCOPY_FIELD (copy, private_bin_path_probe, setup, error); + XCOPY_FIELD (copy, shadow_copy_directories, setup, error); + XCOPY_FIELD (copy, shadow_copy_files, setup, error); + COPY_VAL (copy, publisher_policy, MonoBoolean, setup); + COPY_VAL (copy, path_changed, MonoBoolean, setup); + COPY_VAL (copy, loader_optimization, int, setup); + COPY_VAL (copy, disallow_binding_redirects, MonoBoolean, setup); + COPY_VAL (copy, disallow_code_downloads, MonoBoolean, setup); + XCOPY_FIELD (copy, domain_initializer_args, setup, error); + COPY_VAL (copy, disallow_appbase_probe, MonoBoolean, setup); + XCOPY_FIELD (copy, application_trust, setup, error); + XCOPY_FIELD (copy, configuration_bytes, setup, error); + XCOPY_FIELD (copy, serialized_non_primitives, setup, error); + +#undef XCOPY_FIELD +#undef COPY_VAL mono_domain_set_internal (caller_domain); - return copy; + MONO_HANDLE_ASSIGN (result, copy); +leave: + HANDLE_FUNCTION_RETURN_REF (MonoAppDomainSetup, result); } -static MonoAppDomain * -mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetup *setup, MonoError *error) +static MonoAppDomainHandle +mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error) { + HANDLE_FUNCTION_ENTER (); + MonoAppDomainHandle result = MONO_HANDLE_NEW (MonoAppDomain, NULL); MonoClass *adclass; - MonoAppDomain *ad; MonoDomain *data; - char *shadow_location; mono_error_init (error); @@ -553,31 +603,42 @@ mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetup * /* FIXME: pin all those objects */ data = mono_domain_create(); - ad = (MonoAppDomain *) mono_object_new_checked (data, adclass, error); - return_val_if_nok (error, NULL); - ad->data = data; - data->domain = ad; + MonoAppDomainHandle ad = MONO_HANDLE_NEW (MonoAppDomain, mono_object_new_checked (data, adclass, error)); + if (!is_ok (error)) + goto leave; + MONO_HANDLE_SETVAL (ad, data, MonoDomain*, data); + data->domain = MONO_HANDLE_RAW (ad); data->friendly_name = g_strdup (friendly_name); mono_profiler_appdomain_name (data, data->friendly_name); - if (!setup->application_base) { + MonoStringHandle app_base = MONO_HANDLE_NEW_GET (MonoString, setup, application_base); + if (MONO_HANDLE_IS_NULL (app_base)) { /* Inherit from the root domain since MS.NET does this */ MonoDomain *root = mono_get_root_domain (); - if (root->setup->application_base) { - MonoString *s = mono_string_new_utf16_checked (data, mono_string_chars (root->setup->application_base), mono_string_length (root->setup->application_base), error); - mono_error_assert_ok (error); /* FIXME don't swallow the error */ - MONO_OBJECT_SETREF (setup, application_base, s); + MonoAppDomainSetupHandle root_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, root->setup); + MonoStringHandle root_app_base = MONO_HANDLE_NEW_GET (MonoString, root_setup, application_base); + if (!MONO_HANDLE_IS_NULL (root_app_base)) { + /* N.B. new string is in the new domain */ + uint32_t gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, root_app_base), TRUE); + MonoStringHandle s = mono_string_new_utf16_handle (data, mono_string_chars (MONO_HANDLE_RAW (root_app_base)), mono_string_handle_length (root_app_base), error); + mono_gchandle_free (gchandle); + if (!is_ok (error)) { + g_free (data->friendly_name); + goto leave; + } + MONO_HANDLE_SET (setup, application_base, s); } } mono_context_init_checked (data, error); - return_val_if_nok (error, NULL); + if (!is_ok (error)) + goto leave; - data->setup = copy_app_domain_setup (data, setup, error); + data->setup = MONO_HANDLE_RAW (copy_app_domain_setup (data, setup, error)); if (!mono_error_ok (error)) { g_free (data->friendly_name); - return NULL; + goto leave; } mono_domain_set_options_from_config (data); @@ -585,10 +646,10 @@ mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetup * #ifndef DISABLE_SHADOW_COPY /*FIXME, guard this for when the debugger is not running */ - shadow_location = get_shadow_assembly_location_base (data, error); + char *shadow_location = get_shadow_assembly_location_base (data, error); if (!mono_error_ok (error)) { g_free (data->friendly_name); - return NULL; + goto leave; } g_free (shadow_location); @@ -596,7 +657,9 @@ mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetup * create_domain_objects (data); - return ad; + MONO_HANDLE_ASSIGN (result, ad); +leave: + HANDLE_FUNCTION_RETURN_REF (MonoAppDomain, result); } /** @@ -717,106 +780,113 @@ mono_domain_set (MonoDomain *domain, gboolean force) return TRUE; } -MonoObject * -ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name) +MonoObjectHandle +ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoError *error) { - MonoError error; - MonoDomain *add; - MonoObject *o; - char *str; + mono_error_init (error); - MONO_CHECK_ARG_NULL (name, NULL); + if (MONO_HANDLE_IS_NULL (name)) { + mono_error_set_argument_null (error, "name", ""); + return NULL_HANDLE; + } - g_assert (ad); - add = ad->data; + g_assert (!MONO_HANDLE_IS_NULL (ad)); + MonoDomain *add = MONO_HANDLE_GETVAL (ad, data); g_assert (add); - str = mono_string_to_utf8_checked (name, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; + char *str = mono_string_handle_to_utf8 (name, error); + return_val_if_nok (error, NULL_HANDLE); mono_domain_lock (add); + MonoAppDomainSetupHandle ad_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, add->setup); + MonoStringHandle o; if (!strcmp (str, "APPBASE")) - o = (MonoObject *)add->setup->application_base; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_base); else if (!strcmp (str, "APP_CONFIG_FILE")) - o = (MonoObject *)add->setup->configuration_file; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, configuration_file); else if (!strcmp (str, "DYNAMIC_BASE")) - o = (MonoObject *)add->setup->dynamic_base; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, dynamic_base); else if (!strcmp (str, "APP_NAME")) - o = (MonoObject *)add->setup->application_name; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_name); else if (!strcmp (str, "CACHE_BASE")) - o = (MonoObject *)add->setup->cache_path; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, cache_path); else if (!strcmp (str, "PRIVATE_BINPATH")) - o = (MonoObject *)add->setup->private_bin_path; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path); else if (!strcmp (str, "BINPATH_PROBE_ONLY")) - o = (MonoObject *)add->setup->private_bin_path_probe; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path_probe); else if (!strcmp (str, "SHADOW_COPY_DIRS")) - o = (MonoObject *)add->setup->shadow_copy_directories; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_directories); else if (!strcmp (str, "FORCE_CACHE_INSTALL")) - o = (MonoObject *)add->setup->shadow_copy_files; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_files); else - o = (MonoObject *)mono_g_hash_table_lookup (add->env, name); + o = MONO_HANDLE_NEW (MonoString, mono_g_hash_table_lookup (add->env, MONO_HANDLE_RAW (name))); mono_domain_unlock (add); g_free (str); - if (!o) - return NULL; - - return o; + return MONO_HANDLE_CAST (MonoObject, o); } void -ves_icall_System_AppDomain_SetData (MonoAppDomain *ad, MonoString *name, MonoObject *data) +ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoObjectHandle data, MonoError *error) { - MonoDomain *add; + mono_error_init (error); - MONO_CHECK_ARG_NULL (name,); + if (MONO_HANDLE_IS_NULL (name)) { + mono_error_set_argument_null (error, "name", ""); + return; + } - g_assert (ad); - add = ad->data; + g_assert (!MONO_HANDLE_IS_NULL (ad)); + MonoDomain *add = MONO_HANDLE_GETVAL (ad, data); g_assert (add); mono_domain_lock (add); - mono_g_hash_table_insert (add->env, name, data); + mono_g_hash_table_insert (add->env, MONO_HANDLE_RAW (name), MONO_HANDLE_RAW (data)); mono_domain_unlock (add); } -MonoAppDomainSetup * -ves_icall_System_AppDomain_getSetup (MonoAppDomain *ad) +MonoAppDomainSetupHandle +ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad, MonoError *error) { - g_assert (ad); - g_assert (ad->data); + mono_error_init (error); + g_assert (!MONO_HANDLE_IS_NULL (ad)); + MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); + g_assert (domain); - return ad->data->setup; + return MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup); } -MonoString * -ves_icall_System_AppDomain_getFriendlyName (MonoAppDomain *ad) +MonoStringHandle +ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad, MonoError *error) { - g_assert (ad); - g_assert (ad->data); + mono_error_init (error); + g_assert (!MONO_HANDLE_IS_NULL (ad)); + MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); + g_assert (domain); - return mono_string_new (ad->data, ad->data->friendly_name); + return mono_string_new_handle (domain, domain->friendly_name, error); } -MonoAppDomain * -ves_icall_System_AppDomain_getCurDomain () +MonoAppDomainHandle +ves_icall_System_AppDomain_getCurDomain (MonoError *error) { + mono_error_init (error); MonoDomain *add = mono_domain_get (); - return add->domain; + return MONO_HANDLE_NEW (MonoAppDomain, add->domain); } -MonoAppDomain * -ves_icall_System_AppDomain_getRootDomain () +MonoAppDomainHandle +ves_icall_System_AppDomain_getRootDomain (MonoError *error) { + mono_error_init (error); MonoDomain *root = mono_get_root_domain (); - return root->domain; + return MONO_HANDLE_NEW (MonoAppDomain, root->domain); } MonoBoolean @@ -966,26 +1036,22 @@ mono_domain_set_options_from_config (MonoDomain *domain) g_free (config_file_path); } -MonoAppDomain * -ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomainSetup *setup) +MonoAppDomainHandle +ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name, MonoAppDomainSetupHandle setup, MonoError *error) { - MonoError error; - MonoAppDomain *ad = NULL; + mono_error_init (error); + MonoAppDomainHandle ad = MONO_HANDLE_NEW (MonoAppDomain, NULL); #ifdef DISABLE_APPDOMAINS - mono_error_init (&error); - mono_error_set_not_supported (&error, "AppDomain creation is not supported on this runtime."); + mono_error_set_not_supported (error, "AppDomain creation is not supported on this runtime."); #else char *fname; - fname = mono_string_to_utf8_checked (friendly_name, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; - ad = mono_domain_create_appdomain_internal (fname, setup, &error); - + fname = mono_string_handle_to_utf8 (friendly_name, error); + return_val_if_nok (error, ad); + ad = mono_domain_create_appdomain_internal (fname, setup, error); g_free (fname); #endif - mono_error_set_pending_exception (&error); return ad; } @@ -1805,19 +1871,35 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror) #endif /* DISABLE_SHADOW_COPY */ MonoDomain * -mono_domain_from_appdomain (MonoAppDomain *appdomain) +mono_domain_from_appdomain (MonoAppDomain *appdomain_raw) { - if (appdomain == NULL) - return NULL; + HANDLE_FUNCTION_ENTER (); + MONO_HANDLE_DCL (MonoAppDomain, appdomain); + MonoDomain *result = mono_domain_from_appdomain_handle (appdomain); + HANDLE_FUNCTION_RETURN_VAL (result); +} - if (mono_object_is_transparent_proxy (&appdomain->mbr.obj)) { - MonoTransparentProxy *tp = (MonoTransparentProxy*)appdomain; - return mono_domain_get_by_id (tp->rp->target_domain_id); - } - - return appdomain->data; +MonoDomain * +mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain) +{ + HANDLE_FUNCTION_ENTER (); + MonoDomain *dom = NULL; + if (MONO_HANDLE_IS_NULL (appdomain)) + goto leave; + + if (mono_class_is_transparent_proxy (mono_handle_class (appdomain))) { + MonoTransparentProxyHandle tp = MONO_HANDLE_CAST (MonoTransparentProxy, appdomain); + MonoRealProxyHandle rp = MONO_HANDLE_NEW_GET (MonoRealProxy, tp, rp); + + dom = mono_domain_get_by_id (MONO_HANDLE_GETVAL (rp, target_domain_id)); + } else + dom = MONO_HANDLE_GETVAL (appdomain, data); + +leave: + HANDLE_FUNCTION_RETURN_VAL (dom); } + static gboolean try_load_from (MonoAssembly **assembly, const gchar *path1, const gchar *path2, const gchar *path3, const gchar *path4, @@ -2108,19 +2190,18 @@ fail: } void -ves_icall_System_AppDomain_InternalUnload (gint32 domain_id) +ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error) { - MonoException *exc = NULL; + mono_error_init (error); MonoDomain * domain = mono_domain_get_by_id (domain_id); if (NULL == domain) { - mono_get_exception_execution_engine ("Failed to unload domain, domain id not found"); - mono_set_pending_exception (exc); + mono_error_set_execution_engine (error, "Failed to unload domain, domain id not found"); return; } if (domain == mono_get_root_domain ()) { - mono_set_pending_exception (mono_get_exception_cannot_unload_appdomain ("The default appdomain can not be unloaded.")); + mono_error_set_generic_error (error, "System", "CannotUnloadAppDomainException", "The default appdomain can not be unloaded."); return; } @@ -2134,14 +2215,16 @@ ves_icall_System_AppDomain_InternalUnload (gint32 domain_id) return; #endif + MonoException *exc = NULL; mono_domain_try_unload (domain, (MonoObject**)&exc); if (exc) - mono_set_pending_exception (exc); + mono_error_set_exception_instance (error, exc); } gboolean -ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id) +ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, MonoError *error) { + mono_error_init (error); MonoDomain *domain = mono_domain_get_by_id (domain_id); if (!domain) @@ -2191,42 +2274,45 @@ ves_icall_System_AppDomain_GetIDFromDomain (MonoAppDomain * ad) return ad->data->domain_id; } -MonoAppDomain * -ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomain *ad) +MonoAppDomainHandle +ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad, MonoError* error) { - MonoDomain *old_domain = mono_domain_get(); + mono_error_init (error); + MonoDomain *old_domain = mono_domain_get (); - if (!mono_domain_set (ad->data, FALSE)) { - mono_set_pending_exception (mono_get_exception_appdomain_unloaded ()); - return NULL; + if (!mono_domain_set (MONO_HANDLE_GETVAL (ad, data), FALSE)) { + mono_error_set_appdomain_unloaded (error); + return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE); } - return old_domain->domain; + return MONO_HANDLE_NEW (MonoAppDomain, old_domain->domain); } -MonoAppDomain * -ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid) +MonoAppDomainHandle +ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid, MonoError *error) { MonoDomain *current_domain = mono_domain_get (); MonoDomain *domain = mono_domain_get_by_id (domainid); if (!domain || !mono_domain_set (domain, FALSE)) { - mono_set_pending_exception (mono_get_exception_appdomain_unloaded ()); - return NULL; + mono_error_set_appdomain_unloaded (error); + return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE); } - return current_domain->domain; + return MONO_HANDLE_NEW (MonoAppDomain, current_domain->domain); } void -ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomain *ad) +ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad, MonoError *error) { - mono_thread_push_appdomain_ref (ad->data); + mono_error_init (error); + mono_thread_push_appdomain_ref (MONO_HANDLE_GETVAL (ad, data)); } void -ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id) +ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id, MonoError *error) { + mono_error_init (error); MonoDomain *domain = mono_domain_get_by_id (domain_id); if (!domain) { @@ -2234,7 +2320,7 @@ ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id) * Raise an exception to prevent the managed code from executing a pop * later. */ - mono_set_pending_exception (mono_get_exception_appdomain_unloaded ()); + mono_error_set_appdomain_unloaded (error); return; } @@ -2242,8 +2328,9 @@ ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id) } void -ves_icall_System_AppDomain_InternalPopDomainRef (void) +ves_icall_System_AppDomain_InternalPopDomainRef (MonoError *error) { + mono_error_init (error); mono_thread_pop_appdomain_ref (); } @@ -2269,20 +2356,19 @@ ves_icall_System_AppDomain_InternalSetContext (MonoAppContext *mc) return old_context; } -MonoString * -ves_icall_System_AppDomain_InternalGetProcessGuid (MonoString* newguid) +MonoStringHandle +ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, MonoError *error) { + mono_error_init (error); MonoDomain* mono_root_domain = mono_get_root_domain (); mono_domain_lock (mono_root_domain); if (process_guid_set) { mono_domain_unlock (mono_root_domain); - MonoError error; - MonoString *res = NULL; - res = mono_string_new_utf16_checked (mono_domain_get (), process_guid, sizeof(process_guid)/2, &error); - mono_error_set_pending_exception (&error); - return res; + return mono_string_new_utf16_handle (mono_domain_get (), process_guid, sizeof(process_guid)/2, error); } - memcpy (process_guid, mono_string_chars(newguid), sizeof(process_guid)); + uint32_t gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, newguid), TRUE); + memcpy (process_guid, mono_string_chars(MONO_HANDLE_RAW (newguid)), sizeof(process_guid)); + mono_gchandle_free (gchandle); process_guid_set = TRUE; mono_domain_unlock (mono_root_domain); return newguid; diff --git a/mono/metadata/appdomain.h b/mono/metadata/appdomain.h index ebf94234bb2..3a4286c1319 100644 --- a/mono/metadata/appdomain.h +++ b/mono/metadata/appdomain.h @@ -99,6 +99,7 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc); MONO_API mono_bool mono_domain_is_unloading (MonoDomain *domain); +MONO_RT_EXTERNAL_ONLY MONO_API MonoDomain * mono_domain_from_appdomain (MonoAppDomain *appdomain); diff --git a/mono/metadata/handle.c b/mono/metadata/handle.c index 7df0184a31f..d49e2456d41 100644 --- a/mono/metadata/handle.c +++ b/mono/metadata/handle.c @@ -239,6 +239,12 @@ mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoE return MONO_HANDLE_NEW (MonoArray, mono_array_new_checked (domain, eclass, n, error)); } +MonoArrayHandle +mono_array_new_full_handle (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds, MonoError *error) +{ + return MONO_HANDLE_NEW (MonoArray, mono_array_new_full_checked (domain, array_class, lengths, lower_bounds, error)); +} + #ifdef ENABLE_CHECKED_BUILD /* Checked build helpers */ void diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 1271fad7518..01ded7c4fe8 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -379,6 +379,9 @@ mono_handle_assign (MonoObjectHandleOut dest, MonoObjectHandle src) //FIXME this should go somewhere else MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error); MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error); +MonoArrayHandle +mono_array_new_full_handle (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds, MonoError *error); + uintptr_t mono_array_handle_length (MonoArrayHandle arr); diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index e6ec1e4a21d..ebf717d1fdd 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -117,26 +117,26 @@ ICALL_TYPE(APPDOM, "System.AppDomain", APPDOM_23) ICALL(APPDOM_23, "DoUnhandledException", ves_icall_System_AppDomain_DoUnhandledException) HANDLES(ICALL(APPDOM_1, "ExecuteAssembly", ves_icall_System_AppDomain_ExecuteAssembly)) HANDLES(ICALL(APPDOM_2, "GetAssemblies", ves_icall_System_AppDomain_GetAssemblies)) -ICALL(APPDOM_3, "GetData", ves_icall_System_AppDomain_GetData) +HANDLES(ICALL(APPDOM_3, "GetData", ves_icall_System_AppDomain_GetData)) ICALL(APPDOM_4, "InternalGetContext", ves_icall_System_AppDomain_InternalGetContext) ICALL(APPDOM_5, "InternalGetDefaultContext", ves_icall_System_AppDomain_InternalGetDefaultContext) -ICALL(APPDOM_6, "InternalGetProcessGuid", ves_icall_System_AppDomain_InternalGetProcessGuid) -ICALL(APPDOM_7, "InternalIsFinalizingForUnload", ves_icall_System_AppDomain_InternalIsFinalizingForUnload) -ICALL(APPDOM_8, "InternalPopDomainRef", ves_icall_System_AppDomain_InternalPopDomainRef) -ICALL(APPDOM_9, "InternalPushDomainRef", ves_icall_System_AppDomain_InternalPushDomainRef) -ICALL(APPDOM_10, "InternalPushDomainRefByID", ves_icall_System_AppDomain_InternalPushDomainRefByID) +HANDLES(ICALL(APPDOM_6, "InternalGetProcessGuid", ves_icall_System_AppDomain_InternalGetProcessGuid)) +HANDLES(ICALL(APPDOM_7, "InternalIsFinalizingForUnload", ves_icall_System_AppDomain_InternalIsFinalizingForUnload)) +HANDLES(ICALL(APPDOM_8, "InternalPopDomainRef", ves_icall_System_AppDomain_InternalPopDomainRef)) +HANDLES(ICALL(APPDOM_9, "InternalPushDomainRef", ves_icall_System_AppDomain_InternalPushDomainRef)) +HANDLES(ICALL(APPDOM_10, "InternalPushDomainRefByID", ves_icall_System_AppDomain_InternalPushDomainRefByID)) ICALL(APPDOM_11, "InternalSetContext", ves_icall_System_AppDomain_InternalSetContext) -ICALL(APPDOM_12, "InternalSetDomain", ves_icall_System_AppDomain_InternalSetDomain) -ICALL(APPDOM_13, "InternalSetDomainByID", ves_icall_System_AppDomain_InternalSetDomainByID) -ICALL(APPDOM_14, "InternalUnload", ves_icall_System_AppDomain_InternalUnload) +HANDLES(ICALL(APPDOM_12, "InternalSetDomain", ves_icall_System_AppDomain_InternalSetDomain)) +HANDLES(ICALL(APPDOM_13, "InternalSetDomainByID", ves_icall_System_AppDomain_InternalSetDomainByID)) +HANDLES(ICALL(APPDOM_14, "InternalUnload", ves_icall_System_AppDomain_InternalUnload)) HANDLES(ICALL(APPDOM_15, "LoadAssembly", ves_icall_System_AppDomain_LoadAssembly)) HANDLES(ICALL(APPDOM_16, "LoadAssemblyRaw", ves_icall_System_AppDomain_LoadAssemblyRaw)) -ICALL(APPDOM_17, "SetData", ves_icall_System_AppDomain_SetData) -ICALL(APPDOM_18, "createDomain", ves_icall_System_AppDomain_createDomain) -ICALL(APPDOM_19, "getCurDomain", ves_icall_System_AppDomain_getCurDomain) -ICALL(APPDOM_20, "getFriendlyName", ves_icall_System_AppDomain_getFriendlyName) -ICALL(APPDOM_21, "getRootDomain", ves_icall_System_AppDomain_getRootDomain) -ICALL(APPDOM_22, "getSetup", ves_icall_System_AppDomain_getSetup) +HANDLES(ICALL(APPDOM_17, "SetData", ves_icall_System_AppDomain_SetData)) +HANDLES(ICALL(APPDOM_18, "createDomain", ves_icall_System_AppDomain_createDomain)) +HANDLES(ICALL(APPDOM_19, "getCurDomain", ves_icall_System_AppDomain_getCurDomain)) +HANDLES(ICALL(APPDOM_20, "getFriendlyName", ves_icall_System_AppDomain_getFriendlyName)) +HANDLES(ICALL(APPDOM_21, "getRootDomain", ves_icall_System_AppDomain_getRootDomain)) +HANDLES(ICALL(APPDOM_22, "getSetup", ves_icall_System_AppDomain_getSetup)) ICALL_TYPE(ARGI, "System.ArgIterator", ARGI_1) ICALL(ARGI_1, "IntGetNextArg()", mono_ArgIterator_IntGetNextArg) diff --git a/mono/metadata/marshal-internals.h b/mono/metadata/marshal-internals.h index 1b4ff57b84b..ea210b5fb2b 100644 --- a/mono/metadata/marshal-internals.h +++ b/mono/metadata/marshal-internals.h @@ -9,6 +9,9 @@ #include #include +MonoObjectHandle +mono_marshal_xdomain_copy_value_handle (MonoObjectHandle val, MonoError *error); + // On Windows platform implementation of bellow methods are hosted in separate source file // masrshal-windows.c or marshal-windows-*.c. On other platforms the implementation is still keept // in marshal.c still declared as static and in some places even inlined. diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index 2c4780ac233..e766126d255 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -171,6 +171,9 @@ struct _MonoAppDomain { /* Safely access System.AppDomain from native code */ TYPED_HANDLE_DECL (MonoAppDomain); +/* Safely access System.AppDomainSetup from native code. (struct is in domain-internals.h) */ +TYPED_HANDLE_DECL (MonoAppDomainSetup); + typedef struct _MonoStringBuilder MonoStringBuilder; struct _MonoStringBuilder { @@ -1480,6 +1483,9 @@ mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const void mono_release_type_locks (MonoInternalThread *thread); +int +mono_string_handle_length (MonoStringHandle s); + char * mono_string_handle_to_utf8 (MonoStringHandle s, MonoError *error); @@ -1490,8 +1496,8 @@ char * mono_string_to_utf8_image (MonoImage *image, MonoStringHandle s, MonoError *error); -MonoArray* -mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array, MonoError *error); +MonoArrayHandle +mono_array_clone_in_domain (MonoDomain *domain, MonoArrayHandle array, MonoError *error); MonoArray* mono_array_clone_checked (MonoArray *array, MonoError *error); @@ -1784,6 +1790,9 @@ mono_string_new_checked (MonoDomain *domain, const char *text, MonoError *merror MonoString * mono_string_new_utf16_checked (MonoDomain *domain, const guint16 *text, gint32 len, MonoError *error); +MonoStringHandle +mono_string_new_utf16_handle (MonoDomain *domain, const guint16 *text, gint32 len, MonoError *error); + MonoString * mono_string_from_utf16_checked (mono_unichar2 *data, MonoError *error); diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 086d22d546a..382eb9fa03e 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -64,6 +64,9 @@ free_main_args (void); static char * mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error); +static void +array_full_copy_unchecked_size (MonoArray *src, MonoArray *dest, MonoClass *klass, uintptr_t size); + static MonoMethod* class_get_virtual_method (MonoClass *klass, MonoMethod *method, gboolean is_proxy, MonoError *error); @@ -5603,6 +5606,13 @@ mono_array_full_copy (MonoArray *src, MonoArray *dest) size = mono_array_length (src); g_assert (size == mono_array_length (dest)); size *= mono_array_element_size (klass); + + array_full_copy_unchecked_size (src, dest, klass, size); +} + +static void +array_full_copy_unchecked_size (MonoArray *src, MonoArray *dest, MonoClass *klass, uintptr_t size) +{ #ifdef HAVE_SGEN_GC if (klass->element_class->valuetype) { if (klass->element_class->has_references) @@ -5626,62 +5636,51 @@ mono_array_full_copy (MonoArray *src, MonoArray *dest) * This routine returns a copy of the array that is hosted on the * specified MonoDomain. On failure returns NULL and sets @error. */ -MonoArray* -mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array, MonoError *error) +MonoArrayHandle +mono_array_clone_in_domain (MonoDomain *domain, MonoArrayHandle array_handle, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; - MonoArray *o; - uintptr_t size, i; - uintptr_t *sizes; - MonoClass *klass = array->obj.vtable->klass; + MonoArrayHandle result = MONO_HANDLE_NEW (MonoArray, NULL); + uintptr_t size = 0; + MonoClass *klass = mono_handle_class (array_handle); mono_error_init (error); - if (array->bounds == NULL) { - size = mono_array_length (array); - o = mono_array_new_full_checked (domain, klass, &size, NULL, error); - return_val_if_nok (error, NULL); - - size *= mono_array_element_size (klass); -#ifdef HAVE_SGEN_GC - if (klass->element_class->valuetype) { - if (klass->element_class->has_references) - mono_value_copy_array (o, 0, mono_array_addr_with_size_fast (array, 0, 0), mono_array_length (array)); - else - mono_gc_memmove_atomic (&o->vector, &array->vector, size); - } else { - mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array)); - } -#else - mono_gc_memmove_atomic (&o->vector, &array->vector, size); -#endif - return o; - } + /* Pin source array here - if bounds is non-NULL, it's a pointer into the object data */ + uint32_t src_handle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, array_handle), TRUE); - sizes = (uintptr_t *)alloca (klass->rank * sizeof(intptr_t) * 2); - size = mono_array_element_size (klass); - for (i = 0; i < klass->rank; ++i) { - sizes [i] = array->bounds [i].length; - size *= array->bounds [i].length; - sizes [i + klass->rank] = array->bounds [i].lower_bound; - } - o = mono_array_new_full_checked (domain, klass, sizes, (intptr_t*)sizes + klass->rank, error); - return_val_if_nok (error, NULL); -#ifdef HAVE_SGEN_GC - if (klass->element_class->valuetype) { - if (klass->element_class->has_references) - mono_value_copy_array (o, 0, mono_array_addr_with_size_fast (array, 0, 0), mono_array_length (array)); - else - mono_gc_memmove_atomic (&o->vector, &array->vector, size); + MonoArrayBounds *array_bounds = MONO_HANDLE_GETVAL (array_handle, bounds); + MonoArrayHandle o; + if (array_bounds == NULL) { + size = mono_array_handle_length (array_handle); + o = mono_array_new_full_handle (domain, klass, &size, NULL, error); + if (!is_ok (error)) + goto leave; + size *= mono_array_element_size (klass); } else { - mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array)); + uintptr_t *sizes = (uintptr_t *)alloca (klass->rank * sizeof (uintptr_t)); + intptr_t *lower_bounds = (intptr_t *)alloca (klass->rank * sizeof (intptr_t)); + size = mono_array_element_size (klass); + for (int i = 0; i < klass->rank; ++i) { + sizes [i] = array_bounds [i].length; + size *= array_bounds [i].length; + lower_bounds [i] = array_bounds [i].lower_bound; + } + o = mono_array_new_full_handle (domain, klass, sizes, lower_bounds, error); + if (!is_ok (error)) + goto leave; } -#else - mono_gc_memmove_atomic (&o->vector, &array->vector, size); -#endif - return o; + uint32_t dst_handle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, o), TRUE); + array_full_copy_unchecked_size (MONO_HANDLE_RAW (array_handle), MONO_HANDLE_RAW (o), klass, size); + mono_gchandle_free (dst_handle); + + MONO_HANDLE_ASSIGN (result, o); + +leave: + mono_gchandle_free (src_handle); + return result; } /** @@ -5710,11 +5709,15 @@ mono_array_clone (MonoArray *array) * failure returns NULL and sets @error. */ MonoArray* -mono_array_clone_checked (MonoArray *array, MonoError *error) +mono_array_clone_checked (MonoArray *array_raw, MonoError *error) { - MONO_REQ_GC_UNSAFE_MODE; - return mono_array_clone_in_domain (((MonoObject *)array)->vtable->domain, array, error); + HANDLE_FUNCTION_ENTER (); + /* FIXME: callers of mono_array_clone_checked should use handles */ + mono_error_init (error); + MONO_HANDLE_DCL (MonoArray, array); + MonoArrayHandle result = mono_array_clone_in_domain (MONO_HANDLE_DOMAIN (array), array, error); + HANDLE_FUNCTION_RETURN_OBJ (result); } /* helper macros to check for overflow when calculating the size of arrays */ @@ -6051,6 +6054,21 @@ mono_string_new_utf16_checked (MonoDomain *domain, const guint16 *text, gint32 l return s; } +/** + * mono_string_new_utf16_handle: + * @text: a pointer to an utf16 string + * @len: the length of the string + * @error: written on error. + * + * Returns: A newly created string object which contains @text. + * On error, returns NULL and sets @error. + */ +MonoStringHandle +mono_string_new_utf16_handle (MonoDomain *domain, const guint16 *text, gint32 len, MonoError *error) +{ + return MONO_HANDLE_NEW (MonoString, mono_string_new_utf16_checked (domain, text, len, error)); +} + /** * mono_string_new_utf32: * @text: a pointer to an utf32 string @@ -8428,6 +8446,21 @@ mono_string_length (MonoString *s) return s->length; } +/** + * mono_string_handle_length: + * @s: MonoString + * + * Returns the lenght in characters of the string + */ +int +mono_string_handle_length (MonoStringHandle s) +{ + MONO_REQ_GC_UNSAFE_MODE; + + return MONO_HANDLE_GETVAL (s, length); +} + + /** * mono_array_length: * @array: a MonoArray* diff --git a/mono/metadata/remoting.c b/mono/metadata/remoting.c index 2963b62681f..c2e040dfc06 100644 --- a/mono/metadata/remoting.c +++ b/mono/metadata/remoting.c @@ -10,8 +10,10 @@ #include "config.h" +#include "mono/metadata/handle.h" #include "mono/metadata/remoting.h" #include "mono/metadata/marshal.h" +#include "mono/metadata/marshal-internals.h" #include "mono/metadata/abi-details.h" #include "mono/metadata/cominterop.h" #include "mono/metadata/tabledefs.h" @@ -1910,19 +1912,44 @@ mono_get_xdomain_marshal_type (MonoType *t) return MONO_MARSHAL_SERIALIZE; } -/* mono_marshal_xdomain_copy_value - * Makes a copy of "val" suitable for the current domain. +/* Replace the given array element by a copy in the current domain */ +static gboolean +xdomain_copy_array_element_inplace (MonoArrayHandle arr, int i, MonoError *error) +{ + HANDLE_FUNCTION_ENTER (); + mono_error_init (error); + MonoObjectHandle item = MONO_HANDLE_NEW (MonoObject, NULL); + MONO_HANDLE_ARRAY_GETREF (item, arr, i); + + MonoObjectHandle item_copy = mono_marshal_xdomain_copy_value_handle (item, error); + if (!is_ok (error)) + goto leave; + MONO_HANDLE_ARRAY_SETREF (arr, i, item_copy); +leave: + HANDLE_FUNCTION_RETURN_VAL (is_ok (error)); +} + +/** + * mono_marshal_xdomain_copy_value_handle: + * @val: The value to copy. + * @error: set on failure. + * + * Makes a copy of @val suitable for the current domain. + * On failure returns NULL and sets @error. */ -MonoObject * -mono_marshal_xdomain_copy_value (MonoObject *val, MonoError *error) +MonoObjectHandle +mono_marshal_xdomain_copy_value_handle (MonoObjectHandle val, MonoError *error) { mono_error_init (error); - MonoDomain *domain; - if (val == NULL) return NULL; + MonoObjectHandle result = MONO_HANDLE_NEW (MonoObject, NULL); + if (MONO_HANDLE_IS_NULL (val)) + goto leave; - domain = mono_domain_get (); + MonoDomain *domain = mono_domain_get (); - switch (mono_object_class (val)->byval_arg.type) { + MonoClass *klass = mono_handle_class (val); + + switch (klass->byval_arg.type) { case MONO_TYPE_VOID: g_assert_not_reached (); break; @@ -1938,40 +1965,63 @@ mono_marshal_xdomain_copy_value (MonoObject *val, MonoError *error) case MONO_TYPE_U8: case MONO_TYPE_R4: case MONO_TYPE_R8: { - MonoObject *res = mono_value_box_checked (domain, mono_object_class (val), ((char*)val) + sizeof(MonoObject), error); - return res; - + uint32_t gchandle = mono_gchandle_from_handle (val, TRUE); + MonoObjectHandle res = MONO_HANDLE_NEW (MonoObject, mono_value_box_checked (domain, klass, ((char*)val) + sizeof(MonoObject), error)); /* FIXME use handles in mono_value_box_checked */ + mono_gchandle_free (gchandle); + if (!is_ok (error)) + goto leave; + MONO_HANDLE_ASSIGN (result, res); + break; } case MONO_TYPE_STRING: { - MonoString *str = (MonoString *) val; - MonoObject *res = NULL; - res = (MonoObject *) mono_string_new_utf16_checked (domain, mono_string_chars (str), mono_string_length (str), error); - return res; + MonoStringHandle str = MONO_HANDLE_CAST (MonoString, val); + uint32_t gchandle = mono_gchandle_from_handle (val, TRUE); + MonoStringHandle res = mono_string_new_utf16_handle (domain, mono_string_chars (MONO_HANDLE_RAW (str)), mono_string_handle_length (str), error); + mono_gchandle_free (gchandle); + if (!is_ok (error)) + goto leave; + MONO_HANDLE_ASSIGN (result, res); + break; } case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: { - MonoArray *acopy; - MonoXDomainMarshalType mt = mono_get_xdomain_marshal_type (&(mono_object_class (val)->element_class->byval_arg)); - if (mt == MONO_MARSHAL_SERIALIZE) return NULL; - acopy = mono_array_clone_in_domain (domain, (MonoArray *) val, error); - return_val_if_nok (error, NULL); + MonoArrayHandle arr = MONO_HANDLE_CAST (MonoArray, val); + MonoXDomainMarshalType mt = mono_get_xdomain_marshal_type (&klass->element_class->byval_arg); + if (mt == MONO_MARSHAL_SERIALIZE) + goto leave; + MonoArrayHandle acopy = mono_array_clone_in_domain (domain, arr, error); + if (!is_ok (error)) + goto leave; if (mt == MONO_MARSHAL_COPY) { - int i, len = mono_array_length (acopy); + int i, len = mono_array_handle_length (acopy); for (i = 0; i < len; i++) { - MonoObject *item = (MonoObject *)mono_array_get (acopy, gpointer, i); - MonoObject *item_copy = mono_marshal_xdomain_copy_value (item, error); - return_val_if_nok (error, NULL); - mono_array_setref (acopy, i, item_copy); + if (!xdomain_copy_array_element_inplace (acopy, i, error)) + goto leave; } } - return (MonoObject *) acopy; + MONO_HANDLE_ASSIGN (result, acopy); + break; } default: break; } - return NULL; +leave: + return result; +} + +/* mono_marshal_xdomain_copy_value + * Makes a copy of "val" suitable for the current domain. + */ +MonoObject* +mono_marshal_xdomain_copy_value (MonoObject* val_raw, MonoError *error) +{ + HANDLE_FUNCTION_ENTER (); + /* FIXME callers of mono_marshal_xdomain_copy_value should use handles */ + MONO_HANDLE_DCL (MonoObject, val); + MonoObjectHandle result = mono_marshal_xdomain_copy_value_handle (val, error); + HANDLE_FUNCTION_RETURN_OBJ (result); } /* mono_marshal_xdomain_copy_value -- 2.25.1