X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fobject.c;h=457c50e02cc115b4deeeaa547ff0453ef9df24c5;hb=HEAD;hp=132cea1250aee04feb850feb60e53e975e14ee17;hpb=dd398d3481dd5edce3008133a7d38484868dd438;p=mono.git diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 132cea1250a..457c50e02cc 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -49,6 +49,7 @@ #include #include "cominterop.h" #include +#include static void get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value, MonoError *error); @@ -202,7 +203,7 @@ static MonoRuntimeCallbacks callbacks; * mono_thread_set_main: * \param thread thread to set as the main thread * This function can be used to instruct the runtime to treat \p thread - * as the main thread, ie, the thread that would normally execute the Main() + * as the main thread, ie, the thread that would normally execute the \c Main * method. This basically means that at the end of \p thread, the runtime will * wait for the existing foreground threads to quit and other such details. */ @@ -221,6 +222,9 @@ mono_thread_set_main (MonoThread *thread) main_thread = thread; } +/** + * mono_thread_get_main: + */ MonoThread* mono_thread_get_main (void) { @@ -236,6 +240,7 @@ mono_type_initialization_init (void) type_initialization_hash = g_hash_table_new (NULL, NULL); blocked_thread_hash = g_hash_table_new (NULL, NULL); mono_os_mutex_init_recursive (&ldstr_section); + mono_register_jit_icall (ves_icall_string_alloc, "ves_icall_string_alloc", mono_create_icall_signature ("object int"), FALSE); } void @@ -298,11 +303,10 @@ get_type_init_exception_for_vtable (MonoVTable *vtable) return ex; } -/* +/** * mono_runtime_class_init: - * @vtable: vtable that needs to be initialized - * - * This routine calls the class constructor for @vtable. + * \param vtable vtable that needs to be initialized + * This routine calls the class constructor for \p vtable. */ void mono_runtime_class_init (MonoVTable *vtable) @@ -740,14 +744,12 @@ compute_class_bitmap (MonoClass *klass, gsize *bitmap, int size, int offset, int size = max_size; } -#ifdef HAVE_SGEN_GC - /*An Ephemeron cannot be marked by sgen*/ - if (!static_fields && klass->image == mono_defaults.corlib && !strcmp ("Ephemeron", klass->name)) { + /* An Ephemeron cannot be marked by sgen */ + if (mono_gc_is_moving () && !static_fields && klass->image == mono_defaults.corlib && !strcmp ("Ephemeron", klass->name)) { *max_set = 0; memset (bitmap, 0, size / 8); return bitmap; } -#endif for (p = klass; p != NULL; p = p->parent) { gpointer iter = NULL; @@ -1008,19 +1010,8 @@ mono_class_compute_gc_descriptor (MonoClass *klass) int max_set = 0; gsize *bitmap; gsize default_bitmap [4] = {0}; - static gboolean gcj_inited = FALSE; MonoGCDescriptor gc_descr; - if (!gcj_inited) { - mono_loader_lock (); - - mono_register_jit_icall (ves_icall_object_new_fast, "ves_icall_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE); - mono_register_jit_icall (ves_icall_string_alloc, "ves_icall_string_alloc", mono_create_icall_signature ("object int"), FALSE); - - gcj_inited = TRUE; - mono_loader_unlock (); - } - if (!klass->inited) mono_class_init (klass); @@ -1158,7 +1149,7 @@ mono_method_get_imt_slot (MonoMethod *method) sig = mono_method_signature (method); hashes_count = sig->param_count + 4; - hashes_start = (guint32 *)malloc (hashes_count * sizeof (guint32)); + hashes_start = (guint32 *)g_malloc (hashes_count * sizeof (guint32)); hashes = hashes_start; if (! MONO_CLASS_IS_INTERFACE (method->klass)) { @@ -1227,12 +1218,12 @@ add_imt_builder_entry (MonoImtBuilderEntry **imt_builder, MonoMethod *method, gu if (imt_builder [imt_slot] != NULL) { entry->children = imt_builder [imt_slot]->children + 1; if (entry->children == 1) { - mono_stats.imt_slots_with_collisions++; + UnlockedIncrement (&mono_stats.imt_slots_with_collisions); *imt_collisions_bitmap |= (1 << imt_slot); } } else { entry->children = 0; - mono_stats.imt_used_slots++; + UnlockedIncrement (&mono_stats.imt_used_slots); } imt_builder [imt_slot] = entry; #if DEBUG_IMT @@ -1310,7 +1301,7 @@ imt_sort_slot_entries (MonoImtBuilderEntry *entries) { MONO_REQ_GC_NEUTRAL_MODE; int number_of_entries = entries->children + 1; - MonoImtBuilderEntry **sorted_array = (MonoImtBuilderEntry **)malloc (sizeof (MonoImtBuilderEntry*) * number_of_entries); + MonoImtBuilderEntry **sorted_array = (MonoImtBuilderEntry **)g_malloc (sizeof (MonoImtBuilderEntry*) * number_of_entries); GPtrArray *result = g_ptr_array_new (); MonoImtBuilderEntry *current_entry; int i; @@ -1375,7 +1366,7 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* int i; GSList *list_item; guint32 imt_collisions_bitmap = 0; - MonoImtBuilderEntry **imt_builder = (MonoImtBuilderEntry **)calloc (MONO_IMT_SIZE, sizeof (MonoImtBuilderEntry*)); + MonoImtBuilderEntry **imt_builder = (MonoImtBuilderEntry **)g_calloc (MONO_IMT_SIZE, sizeof (MonoImtBuilderEntry*)); int method_count = 0; gboolean record_method_count_for_max_collisions = FALSE; gboolean has_generic_virtual = FALSE, has_variant_iface = FALSE; @@ -1487,17 +1478,17 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* if (imt_builder [i] != NULL) { int methods_in_slot = imt_builder [i]->children + 1; - if (methods_in_slot > mono_stats.imt_max_collisions_in_slot) { - mono_stats.imt_max_collisions_in_slot = methods_in_slot; + if (methods_in_slot > UnlockedRead (&mono_stats.imt_max_collisions_in_slot)) { + UnlockedWrite (&mono_stats.imt_max_collisions_in_slot, methods_in_slot); record_method_count_for_max_collisions = TRUE; } method_count += methods_in_slot; } } - mono_stats.imt_number_of_methods += method_count; + UnlockedAdd (&mono_stats.imt_number_of_methods, method_count); if (record_method_count_for_max_collisions) { - mono_stats.imt_method_count_when_max_collisions = method_count; + UnlockedWrite (&mono_stats.imt_method_count_when_max_collisions, method_count); } for (i = 0; i < MONO_IMT_SIZE; i++) { @@ -1910,16 +1901,16 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro if (klass->interface_offsets_count) { imt_table_bytes = sizeof (gpointer) * (MONO_IMT_SIZE); - mono_stats.imt_number_of_tables++; - mono_stats.imt_tables_size += imt_table_bytes; + UnlockedIncrement (&mono_stats.imt_number_of_tables); + UnlockedAdd (&mono_stats.imt_tables_size, imt_table_bytes); } else { imt_table_bytes = 0; } vtable_size = imt_table_bytes + MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer); - mono_stats.used_class_count++; - mono_stats.class_vtable_size += vtable_size; + UnlockedIncrement (&mono_stats.used_class_count); + UnlockedAdd (&mono_stats.class_vtable_size, vtable_size); interface_offsets = alloc_vtable (domain, vtable_size, imt_table_bytes); vt = (MonoVTable*) ((char*)interface_offsets + imt_table_bytes); @@ -1930,23 +1921,22 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro vt->domain = domain; mono_class_compute_gc_descriptor (klass); - /* - * We can't use typed allocation in the non-root domains, since the - * collector needs the GC descriptor stored in the vtable even after - * the mempool containing the vtable is destroyed when the domain is - * unloaded. An alternative might be to allocate vtables in the GC - * heap, but this does not seem to work (it leads to crashes inside - * libgc). If that approach is tried, two gc descriptors need to be - * allocated for each class: one for the root domain, and one for all - * other domains. The second descriptor should contain a bit for the - * vtable field in MonoObject, since we can no longer assume the - * vtable is reachable by other roots after the appdomain is unloaded. - */ -#ifdef HAVE_BOEHM_GC - if (domain != mono_get_root_domain () && !mono_dont_free_domains) + /* + * For Boehm: + * We can't use typed allocation in the non-root domains, since the + * collector needs the GC descriptor stored in the vtable even after + * the mempool containing the vtable is destroyed when the domain is + * unloaded. An alternative might be to allocate vtables in the GC + * heap, but this does not seem to work (it leads to crashes inside + * libgc). If that approach is tried, two gc descriptors need to be + * allocated for each class: one for the root domain, and one for all + * other domains. The second descriptor should contain a bit for the + * vtable field in MonoObject, since we can no longer assume the + * vtable is reachable by other roots after the appdomain is unloaded. + */ + if (!mono_gc_is_moving () && domain != mono_get_root_domain () && !mono_dont_free_domains) vt->gc_descr = MONO_GC_DESCRIPTOR_NULL; else -#endif vt->gc_descr = klass->gc_descr; gc_bits = mono_gc_get_vtable_bits (klass); @@ -1966,14 +1956,13 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro /*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], klass->name_space, klass->name, class_size);*/ statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set + 1); vt->vtable [klass->vtable_size] = mono_gc_alloc_fixed (class_size, statics_gc_descr, MONO_ROOT_SOURCE_STATIC, "managed static variables"); - mono_domain_add_class_static_data (domain, klass, vt->vtable [klass->vtable_size], NULL); if (bitmap != default_bitmap) g_free (bitmap); } else { vt->vtable [klass->vtable_size] = mono_domain_alloc0 (domain, class_size); } vt->has_static_fields = TRUE; - mono_stats.class_static_data_size += class_size; + UnlockedAdd (&mono_stats.class_static_data_size, class_size); } iter = NULL; @@ -2167,6 +2156,22 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro } #ifndef DISABLE_REMOTING +/** + * mono_remote_class_is_interface_proxy: + * \param remote_class + * + * Returns TRUE if the given remote class is a proxying an interface (as + * opposed to a class deriving from MarshalByRefObject). + */ +gboolean +mono_remote_class_is_interface_proxy (MonoRemoteClass *remote_class) +{ + /* This if condition is taking advantage of how mono_remote_class () + * works: if that code changes, this needs to change too. */ + return (remote_class->interface_count >= 1 && + remote_class->proxy_class == mono_defaults.marshalbyrefobject_class); +} + /** * mono_class_proxy_vtable: * \param domain the application domain @@ -2244,12 +2249,12 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono } imt_table_bytes = sizeof (gpointer) * MONO_IMT_SIZE; - mono_stats.imt_number_of_tables++; - mono_stats.imt_tables_size += imt_table_bytes; + UnlockedIncrement (&mono_stats.imt_number_of_tables); + UnlockedAdd (&mono_stats.imt_tables_size, imt_table_bytes); vtsize = imt_table_bytes + MONO_SIZEOF_VTABLE + klass->vtable_size * sizeof (gpointer); - mono_stats.class_vtable_size += vtsize + extra_interface_vtsize; + UnlockedAdd (&mono_stats.class_vtable_size, vtsize + extra_interface_vtsize); interface_offsets = alloc_vtable (domain, vtsize + extra_interface_vtsize, imt_table_bytes); pvt = (MonoVTable*) ((char*)interface_offsets + imt_table_bytes); @@ -2261,6 +2266,18 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono /* we need to keep the GC descriptor for a transparent proxy or we confuse the precise GC */ pvt->gc_descr = mono_defaults.transparent_proxy_class->gc_descr; + if (mono_remote_class_is_interface_proxy (remote_class)) { + /* If it's a transparent proxy for an interface, set the + * MonoVTable:type to the interface type, not the placeholder + * MarshalByRefObject class. This is used when mini JITs calls + * to Object.GetType () + */ + MonoType *itf_proxy_type = &remote_class->interfaces[0]->byval_arg; + pvt->type = mono_type_get_object_checked (domain, itf_proxy_type, error); + if (!is_ok (error)) + goto failure; + } + /* initialize vtable */ mono_class_setup_vtable (klass); for (i = 0; i < klass->vtable_size; ++i) { @@ -2528,6 +2545,12 @@ mono_remote_class (MonoDomain *domain, MonoStringHandle class_name, MonoClass *p key = mp_key; if (mono_class_is_interface (proxy_class)) { + /* If we need to proxy an interface, we use this stylized + * representation (interface_count >= 1, proxy_class is + * MarshalByRefObject). The code in + * mono_remote_class_is_interface_proxy () depends on being + * able to detect that we're doing this, so if this + * representation changes, change GetType, too. */ rc = (MonoRemoteClass *)mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*)); rc->interface_count = 1; rc->interfaces [0] = proxy_class; @@ -2542,7 +2565,7 @@ mono_remote_class (MonoDomain *domain, MonoStringHandle class_name, MonoClass *p rc->xdomain_vtable = NULL; rc->proxy_class_name = name; #ifndef DISABLE_PERFCOUNTERS - mono_perfcounters->loader_bytes += mono_string_length (MONO_HANDLE_RAW (class_name)) + 1; + InterlockedAdd (&mono_perfcounters->loader_bytes, mono_string_length (MONO_HANDLE_RAW (class_name)) + 1); #endif g_hash_table_insert (domain->proxy_vtable_hash, key, rc); @@ -2821,13 +2844,11 @@ do_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **ex error_init (error); - if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS) - mono_profiler_method_start_invoke (method); + MONO_PROFILER_RAISE (method_begin_invoke, (method)); result = callbacks.runtime_invoke (method, obj, params, exc, error); - if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS) - mono_profiler_method_end_invoke (method); + MONO_PROFILER_RAISE (method_end_invoke, (method)); if (!mono_error_ok (error)) return NULL; @@ -3757,6 +3778,49 @@ mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass) } } +/* + * mono_nullable_init_from_handle: + * @buf: The nullable structure to initialize. + * @value: the value to initialize from + * @klass: the type for the object + * + * Initialize the nullable structure pointed to by @buf from @value which + * should be a boxed value type. The size of @buf should be able to hold + * as much data as the @klass->instance_size (which is the number of bytes + * that will be copies). + * + * Since Nullables have variable structure, we can not define a C + * structure for them. + */ +void +mono_nullable_init_from_handle (guint8 *buf, MonoObjectHandle value, MonoClass *klass) +{ + MONO_REQ_GC_UNSAFE_MODE; + + MonoClass *param_class = klass->cast_class; + + mono_class_setup_fields (klass); + g_assert (klass->fields_inited); + + g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class); + g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class); + + *(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject)) = MONO_HANDLE_IS_NULL (value) ? 0 : 1; + if (!MONO_HANDLE_IS_NULL (value)) { + uint32_t value_gchandle = 0; + gpointer src = mono_object_handle_pin_unbox (value, &value_gchandle); + if (param_class->has_references) + mono_gc_wbarrier_value_copy (buf + klass->fields [0].offset - sizeof (MonoObject), src, 1, param_class); + else + mono_gc_memmove_atomic (buf + klass->fields [0].offset - sizeof (MonoObject), src, mono_class_value_size (param_class, NULL)); + mono_gchandle_free (value_gchandle); + } else { + mono_gc_bzero_atomic (buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL)); + } +} + + + /** * mono_nullable_box: * \param buf The buffer representing the data to be boxed @@ -3947,8 +4011,7 @@ static int num_main_args = 0; /** * mono_runtime_get_main_args: - * - * Returns: a MonoArray with the arguments passed to the main program + * \returns A \c MonoArray with the arguments passed to the main program */ MonoArray* mono_runtime_get_main_args (void) @@ -3978,8 +4041,11 @@ mono_runtime_get_main_args_checked (MonoError *error) res = (MonoArray*)mono_array_new_checked (domain, mono_defaults.string_class, num_main_args, error); return_val_if_nok (error, NULL); - for (i = 0; i < num_main_args; ++i) - mono_array_setref (res, i, mono_string_new (domain, main_args [i])); + for (i = 0; i < num_main_args; ++i) { + MonoString *arg = mono_string_new_checked (domain, main_args [i], error); + return_val_if_nok (error, NULL); + mono_array_setref (res, i, arg); + } return res; } @@ -4119,7 +4185,8 @@ prepare_run_main (MonoMethod *method, int argc, char *argv[]) * main_args array. */ gchar *str = mono_utf8_from_external (argv [i]); - MonoString *arg = mono_string_new (domain, str); + MonoString *arg = mono_string_new_checked (domain, str, &error); + mono_error_assert_ok (&error); mono_array_setref (args, i, arg); g_free (str); } @@ -4135,7 +4202,7 @@ prepare_run_main (MonoMethod *method, int argc, char *argv[]) /** * mono_runtime_run_main: - * \param method the method to start the application with (usually \c Main) + * \param method the method to start the application with (usually Main) * \param argc number of arguments from the command line * \param argv array of strings from the command line * \param exc excetption results @@ -4486,16 +4553,48 @@ mono_runtime_unhandled_exception_policy_get (void) { * a warning to the console */ void -mono_unhandled_exception (MonoObject *exc) +mono_unhandled_exception (MonoObject *exc_raw) +{ + MonoError error; + HANDLE_FUNCTION_ENTER (); + MONO_HANDLE_DCL (MonoObject, exc); + error_init (&error); + mono_unhandled_exception_checked (exc, &error); + mono_error_assert_ok (&error); + HANDLE_FUNCTION_RETURN (); +} + +/** + * mono_unhandled_exception: + * @exc: exception thrown + * + * This is a VM internal routine. + * + * We call this function when we detect an unhandled exception + * in the default domain. + * + * It invokes the * UnhandledException event in AppDomain or prints + * a warning to the console + */ +void +mono_unhandled_exception_checked (MonoObjectHandle exc, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; - MonoError error; + error_init (error); MonoClassField *field; MonoDomain *current_domain, *root_domain; - MonoObject *current_appdomain_delegate = NULL, *root_appdomain_delegate = NULL; + MonoObjectHandle current_appdomain_delegate = MONO_HANDLE_NEW (MonoObject, NULL); - if (mono_class_has_parent (exc->vtable->klass, mono_defaults.threadabortexception_class)) + MonoClass *klass = mono_handle_class (exc); + /* + * AppDomainUnloadedException don't behave like unhandled exceptions unless thrown from + * a thread started in unmanaged world. + * https://msdn.microsoft.com/en-us/library/system.appdomainunloadedexception(v=vs.110).aspx#Anchor_6 + */ + if (klass == mono_defaults.threadabortexception_class || + (klass == mono_class_get_appdomain_unloaded_exception_class () && + mono_thread_info_current ()->runtime_thread)) return; field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "UnhandledException"); @@ -4504,22 +4603,22 @@ mono_unhandled_exception (MonoObject *exc) current_domain = mono_domain_get (); root_domain = mono_get_root_domain (); - root_appdomain_delegate = mono_field_get_value_object_checked (root_domain, field, (MonoObject*) root_domain->domain, &error); - mono_error_assert_ok (&error); + MonoObjectHandle root_appdomain_delegate = MONO_HANDLE_NEW (MonoObject, mono_field_get_value_object_checked (root_domain, field, (MonoObject*) root_domain->domain, error)); /* FIXME use handles for mono_field_get_value_object_checked */ + return_if_nok (error); if (current_domain != root_domain) { - current_appdomain_delegate = mono_field_get_value_object_checked (current_domain, field, (MonoObject*) current_domain->domain, &error); - mono_error_assert_ok (&error); + MONO_HANDLE_ASSIGN (current_appdomain_delegate, MONO_HANDLE_NEW (MonoObject, mono_field_get_value_object_checked (current_domain, field, (MonoObject*) current_domain->domain, error))); /* FIXME use handles for mono_field_get_value_object_checked */ + return_if_nok (error); } - if (!current_appdomain_delegate && !root_appdomain_delegate) { - mono_print_unhandled_exception (exc); + if (MONO_HANDLE_IS_NULL (current_appdomain_delegate) && MONO_HANDLE_IS_NULL (root_appdomain_delegate)) { + mono_print_unhandled_exception (MONO_HANDLE_RAW (exc)); /* FIXME use handles for mono_print_unhandled_exception */ } else { /* unhandled exception callbacks must not be aborted */ mono_threads_begin_abort_protected_block (); - if (root_appdomain_delegate) - call_unhandled_exception_delegate (root_domain, root_appdomain_delegate, exc); - if (current_appdomain_delegate) - call_unhandled_exception_delegate (current_domain, current_appdomain_delegate, exc); + if (!MONO_HANDLE_IS_NULL (root_appdomain_delegate)) + call_unhandled_exception_delegate (root_domain, MONO_HANDLE_RAW (root_appdomain_delegate), MONO_HANDLE_RAW (exc)); /* FIXME use handles in call_unhandled_exception_delegate */ + if (!MONO_HANDLE_IS_NULL (current_appdomain_delegate)) + call_unhandled_exception_delegate (current_domain, MONO_HANDLE_RAW (current_appdomain_delegate), MONO_HANDLE_RAW (exc)); mono_threads_end_abort_protected_block (); } @@ -4567,18 +4666,23 @@ prepare_thread_to_exec_main (MonoDomain *domain, MonoMethod *method) if (!domain->entry_assembly) { gchar *str; + MonoError error; MonoAssembly *assembly; assembly = method->klass->image->assembly; domain->entry_assembly = assembly; /* Domains created from another domain already have application_base and configuration_file set */ if (domain->setup->application_base == NULL) { - MONO_OBJECT_SETREF (domain->setup, application_base, mono_string_new (domain, assembly->basedir)); + MonoString *basedir = mono_string_new_checked (domain, assembly->basedir, &error); + mono_error_assert_ok (&error); + MONO_OBJECT_SETREF (domain->setup, application_base, basedir); } if (domain->setup->configuration_file == NULL) { str = g_strconcat (assembly->image->name, ".config", NULL); - MONO_OBJECT_SETREF (domain->setup, configuration_file, mono_string_new (domain, str)); + MonoString *config_file = mono_string_new_checked (domain, str, &error); + mono_error_assert_ok (&error); + MONO_OBJECT_SETREF (domain->setup, configuration_file, config_file); g_free (str); mono_domain_set_options_from_config (domain); } @@ -5160,8 +5264,9 @@ mono_object_new_checked (MonoDomain *domain, MonoClass *klass, MonoError *error) MonoVTable *vtable; - vtable = mono_class_vtable (domain, klass); - g_assert (vtable); /* FIXME don't swallow the error */ + vtable = mono_class_vtable_full (domain, klass, error); + if (!is_ok (error)) + return NULL; MonoObject *o = mono_object_new_specific_checked (vtable, error); return o; @@ -5380,16 +5485,6 @@ mono_object_new_fast_checked (MonoVTable *vtable, MonoError *error) return o; } -MonoObject * -ves_icall_object_new_fast (MonoVTable *vtable) -{ - MonoError error; - MonoObject *o = mono_object_new_fast_checked (vtable, &error); - mono_error_set_pending_exception (&error); - - return o; -} - MonoObject* mono_object_new_mature (MonoVTable *vtable, MonoError *error) { @@ -5409,44 +5504,6 @@ mono_object_new_mature (MonoVTable *vtable, MonoError *error) return o; } -/** - * mono_class_get_allocation_ftn: - * \param vtable vtable - * \param for_box the object will be used for boxing - * \param pass_size_in_words Unused - * \returns the allocation function appropriate for the given class. - */ -void* -mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *pass_size_in_words) -{ - MONO_REQ_GC_NEUTRAL_MODE; - - *pass_size_in_words = FALSE; - - if (mono_class_has_finalizer (vtable->klass) || mono_class_is_marshalbyref (vtable->klass)) - return ves_icall_object_new_specific; - - if (vtable->gc_descr != MONO_GC_DESCRIPTOR_NULL) { - - return ves_icall_object_new_fast; - - /* - * FIXME: This is actually slower than ves_icall_object_new_fast, because - * of the overhead of parameter passing. - */ - /* - *pass_size_in_words = TRUE; -#ifdef GC_REDIRECT_TO_LOCAL - return GC_local_gcj_fast_malloc; -#else - return GC_gcj_fast_malloc; -#endif - */ - } - - return ves_icall_object_new_specific; -} - /** * mono_object_new_from_token: * \param image Context where the type_token is hosted @@ -5545,18 +5602,18 @@ mono_array_full_copy (MonoArray *src, MonoArray *dest) 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) - mono_value_copy_array (dest, 0, mono_array_addr_with_size_fast (src, 0, 0), mono_array_length (src)); - else - mono_gc_memmove_atomic (&dest->vector, &src->vector, size); + if (mono_gc_is_moving ()) { + if (klass->element_class->valuetype) { + if (klass->element_class->has_references) + mono_value_copy_array (dest, 0, mono_array_addr_with_size_fast (src, 0, 0), mono_array_length (src)); + else + mono_gc_memmove_atomic (&dest->vector, &src->vector, size); + } else { + mono_array_memcpy_refs (dest, 0, src, 0, mono_array_length (src)); + } } else { - mono_array_memcpy_refs (dest, 0, src, 0, mono_array_length (src)); + mono_gc_memmove_atomic (&dest->vector, &src->vector, size); } -#else - mono_gc_memmove_atomic (&dest->vector, &src->vector, size); -#endif } /** @@ -6169,24 +6226,25 @@ mono_string_new_checked (MonoDomain *domain, const char *text, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; - GError *eg_error = NULL; - MonoString *o = NULL; - guint16 *ut; - glong items_written; - int l; - - error_init (error); - - l = strlen (text); - - ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &eg_error); - - if (!eg_error) - o = mono_string_new_utf16_checked (domain, ut, items_written, error); - else - g_error_free (eg_error); + GError *eg_error = NULL; + MonoString *o = NULL; + guint16 *ut; + glong items_written; + int l; - g_free (ut); + error_init (error); + + l = strlen (text); + + ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &eg_error); + + if (!eg_error) { + o = mono_string_new_utf16_checked (domain, ut, items_written, error); + } else { + mono_error_set_execution_engine (error, "String conversion error: %s", eg_error->message); + } + + g_free (ut); /*FIXME g_utf8_get_char, g_utf8_next_char and g_utf8_validate are not part of eglib.*/ #if 0 @@ -6228,8 +6286,12 @@ mono_string_new_wrapper (const char *text) MonoDomain *domain = mono_domain_get (); - if (text) - return mono_string_new (domain, text); + if (text) { + MonoError error; + MonoString *result = mono_string_new_checked (domain, text, &error); + mono_error_assert_ok (&error); + return result; + } return NULL; } @@ -6281,31 +6343,31 @@ mono_value_box_checked (MonoDomain *domain, MonoClass *klass, gpointer value, Mo size = size - sizeof (MonoObject); -#ifdef HAVE_SGEN_GC - g_assert (size == mono_class_value_size (klass, NULL)); - mono_gc_wbarrier_value_copy ((char *)res + sizeof (MonoObject), value, 1, klass); -#else + if (mono_gc_is_moving ()) { + g_assert (size == mono_class_value_size (klass, NULL)); + mono_gc_wbarrier_value_copy ((char *)res + sizeof (MonoObject), value, 1, klass); + } else { #if NO_UNALIGNED_ACCESS - mono_gc_memmove_atomic ((char *)res + sizeof (MonoObject), value, size); -#else - switch (size) { - case 1: - *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value; - break; - case 2: - *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value; - break; - case 4: - *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value; - break; - case 8: - *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value; - break; - default: mono_gc_memmove_atomic ((char *)res + sizeof (MonoObject), value, size); - } -#endif +#else + switch (size) { + case 1: + *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value; + break; + case 2: + *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value; + break; + case 4: + *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value; + break; + case 8: + *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value; + break; + default: + mono_gc_memmove_atomic ((char *)res + sizeof (MonoObject), value, size); + } #endif + } if (klass->has_finalize) { mono_object_register_finalizer (res); return_val_if_nok (error, NULL); @@ -6577,7 +6639,7 @@ mono_object_handle_isinst_mbyref (MonoObjectHandle obj, MonoClass *klass, MonoEr pa [0] = MONO_HANDLE_RAW (reftype); pa [1] = MONO_HANDLE_RAW (obj); - MonoObject *res = mono_runtime_invoke_checked (im, rp, pa, error); + MonoObject *res = mono_runtime_invoke_checked (im, MONO_HANDLE_RAW (rp), pa, error); if (!is_ok (error)) goto leave; @@ -7035,7 +7097,7 @@ mono_string_to_utf8_mp_ignore (MonoMemPool *mp, MonoString *s) * mono_string_to_utf16: * \param s a \c MonoString * \returns a null-terminated array of the UTF-16 chars - * contained in \param s. The result must be freed with \c g_free(). + * contained in \p s. The result must be freed with \c g_free(). * This is a temporary helper until our string implementation * is reworked to always include the null-terminating char. */ @@ -7269,6 +7331,25 @@ mono_raise_exception (MonoException *ex) eh_callbacks.mono_raise_exception (ex); } +/** + * mono_raise_exception: + * \param ex exception object + * Signal the runtime that the exception \p ex has been raised in unmanaged code. + */ +void +mono_reraise_exception (MonoException *ex) +{ + MONO_REQ_GC_UNSAFE_MODE; + + /* + * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since + * that will cause gcc to omit the function epilog, causing problems when + * the JIT tries to walk the stack, since the return address on the stack + * will point into the next function in the executable, not this one. + */ + eh_callbacks.mono_reraise_exception (ex); +} + void mono_raise_exception_with_context (MonoException *ex, MonoContext *ctx) { @@ -7329,6 +7410,9 @@ mono_wait_handle_get_handle (MonoWaitHandle *handle) static MonoObject* mono_runtime_capture_context (MonoDomain *domain, MonoError *error) { +#ifdef HOST_WASM + return mono_runtime_invoke_checked (mono_get_context_capture_method (), NULL, NULL, error); +#else MONO_REQ_GC_UNSAFE_MODE; RuntimeInvokeFunction runtime_invoke; @@ -7350,6 +7434,7 @@ mono_runtime_capture_context (MonoDomain *domain, MonoError *error) runtime_invoke = (RuntimeInvokeFunction)domain->capture_context_runtime_invoke; return runtime_invoke (NULL, NULL, NULL, domain->capture_context_method); +#endif } /** * mono_async_result_new: @@ -7778,43 +7863,44 @@ mono_print_unhandled_exception (MonoObject *exc) * On failure returns FALSE and sets \p error. */ gboolean -mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoMethod *method, MonoError *error) +mono_delegate_ctor_with_method (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; error_init (error); - MonoDelegate *delegate = (MonoDelegate *)this_obj; + MonoDelegateHandle delegate = MONO_HANDLE_CAST (MonoDelegate, this_obj); - g_assert (this_obj); + g_assert (!MONO_HANDLE_IS_NULL (this_obj)); g_assert (addr); - g_assert (mono_class_has_parent (mono_object_class (this_obj), mono_defaults.multicastdelegate_class)); + MonoClass *klass = mono_handle_class (this_obj); + g_assert (mono_class_has_parent (klass, mono_defaults.multicastdelegate_class)); if (method) - delegate->method = method; + MONO_HANDLE_SETVAL (delegate, method, MonoMethod*, method); - mono_stats.delegate_creations++; + UnlockedIncrement (&mono_stats.delegate_creations); #ifndef DISABLE_REMOTING - if (target && mono_object_is_transparent_proxy (target)) { + if (!MONO_HANDLE_IS_NULL (target) && mono_class_is_transparent_proxy (mono_handle_class (target))) { g_assert (method); method = mono_marshal_get_remoting_invoke (method); #ifdef ENABLE_INTERPRETER - g_error ("need RuntimeMethod in method_ptr when using interpreter"); + //g_error ("need RuntimeMethod in method_ptr when using interpreter"); #endif - delegate->method_ptr = mono_compile_method_checked (method, error); + MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, mono_compile_method_checked (method, error)); return_val_if_nok (error, FALSE); - MONO_OBJECT_SETREF (delegate, target, target); + MONO_HANDLE_SET (delegate, target, target); } else #endif { - delegate->method_ptr = addr; - MONO_OBJECT_SETREF (delegate, target, target); + MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, addr); + MONO_HANDLE_SET (delegate, target, target); } - delegate->invoke_impl = callbacks.create_delegate_trampoline (delegate->object.vtable->domain, delegate->object.vtable->klass); + MONO_HANDLE_SETVAL (delegate, invoke_impl, gpointer, callbacks.create_delegate_trampoline (MONO_HANDLE_DOMAIN (delegate), mono_handle_class (delegate))); if (callbacks.init_delegate) - callbacks.init_delegate (delegate); + callbacks.init_delegate (MONO_HANDLE_RAW (delegate)); /* FIXME: update init_delegate callback to take a MonoDelegateHandle */ return TRUE; } @@ -7828,7 +7914,7 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint * On failure returns FALSE and sets \p error. */ gboolean -mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoError *error) +mono_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; @@ -8060,9 +8146,13 @@ mono_load_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClas return_val_if_nok (error, NULL); full_name = mono_type_get_full_name (klass); - mono_array_setref (msg->args, 0, mono_string_new (domain, full_name)); - mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field))); + MonoString *full_name_str = mono_string_new_checked (domain, full_name, error); g_free (full_name); + return_val_if_nok (error, NULL); + mono_array_setref (msg->args, 0, full_name_str); + MonoString *field_name = mono_string_new_checked (domain, mono_field_get_name (field), error); + return_val_if_nok (error, NULL); + mono_array_setref (msg->args, 1, field_name); mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error); return_val_if_nok (error, NULL);