X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fobject.c;h=9db69581fbcc77704b0230f94bf300466255d509;hb=76b32f3ee38e7b29cdbaa657a4826b65579f4e93;hp=7e4c9dc4e062b84777f32afaf1ab51e5ddd3ea04;hpb=b2cf7bbf8497fcae37d2fe8290b25c04adda8e4e;p=mono.git diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 7e4c9dc4e06..9db69581fbc 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -329,6 +330,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) MonoNativeThreadId tid; int do_initialization = 0; MonoDomain *last_domain = NULL; + MonoException * pending_tae = NULL; mono_error_init (error); @@ -431,14 +433,22 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) if (do_initialization) { MonoException *exc = NULL; + + mono_threads_begin_abort_protected_block (); mono_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, error); - if (exc != NULL && mono_error_ok (error)) { - mono_error_set_exception_instance (error, exc); - } + mono_threads_end_abort_protected_block (); + + //exception extracted, error will be set to the right value later + if (exc == NULL && !mono_error_ok (error))//invoking failed but exc was not set + exc = mono_error_convert_to_exception (error); + else + mono_error_cleanup (error); + + mono_error_init (error); /* If the initialization failed, mark the class as unusable. */ /* Avoid infinite loops */ - if (!(mono_error_ok(error) || + if (!(!exc || (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "TypeInitializationException")))) { @@ -451,15 +461,9 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) MonoException *exc_to_throw = mono_get_exception_type_initialization_checked (full_name, exc, error); g_free (full_name); - return_val_if_nok (error, FALSE); - mono_error_set_exception_instance (error, exc_to_throw); + mono_error_assert_ok (error); //We can't recover from this, no way to fail a type we can't alloc a failure. - MonoException *exc_to_store = mono_error_convert_to_exception (error); - /* What we really want to do here is clone the error object and store one copy in the - * domain's exception hash and use the other one to error out here. */ - mono_error_init (error); - mono_error_set_exception_instance (error, exc_to_store); /* * Store the exception object so it could be thrown on subsequent * accesses. @@ -467,7 +471,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) mono_domain_lock (domain); if (!domain->type_init_exception_hash) domain->type_init_exception_hash = mono_g_hash_table_new_type (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "type initialization exceptions table"); - mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_store); + mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_throw); mono_domain_unlock (domain); } @@ -475,6 +479,11 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) mono_domain_set (last_domain, TRUE); lock->done = TRUE; mono_type_init_unlock (lock); + if (exc && mono_object_class (exc) == mono_defaults.threadabortexception_class) + pending_tae = exc; + //TAEs are blocked around .cctors, they must escape as soon as no cctor is left to run. + if (!pending_tae) + pending_tae = mono_thread_try_resume_interruption (); } else { /* this just blocks until the initializing thread is done */ mono_type_init_lock (lock); @@ -495,7 +504,10 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) vtable->initialized = 1; mono_type_initialization_unlock (); - if (vtable->init_failed) { + //TAE wins over TIE + if (pending_tae) + mono_error_set_exception_instance (error, pending_tae); + else if (vtable->init_failed) { /* Either we were the initializing thread or we waited for the initialization */ mono_error_set_exception_instance (error, get_type_init_exception_for_vtable (vtable)); return FALSE; @@ -560,8 +572,8 @@ default_delegate_trampoline (MonoDomain *domain, MonoClass *klass) } static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline; -static MonoImtThunkBuilder imt_thunk_builder; -static gboolean always_build_imt_thunks; +static MonoImtTrampolineBuilder imt_trampoline_builder; +static gboolean always_build_imt_trampolines; #if (MONO_IMT_SIZE > 32) #error "MONO_IMT_SIZE cannot be larger than 32" @@ -594,14 +606,15 @@ mono_install_delegate_trampoline (MonoDelegateTrampoline func) } void -mono_install_imt_thunk_builder (MonoImtThunkBuilder func) { - imt_thunk_builder = func; +mono_install_imt_trampoline_builder (MonoImtTrampolineBuilder func) +{ + imt_trampoline_builder = func; } void -mono_set_always_build_imt_thunks (gboolean value) +mono_set_always_build_imt_trampolines (gboolean value) { - always_build_imt_thunks = value; + always_build_imt_trampolines = value; } /** @@ -1195,7 +1208,7 @@ mono_method_get_imt_slot (MonoMethod *method) break; } - free (hashes_start); + g_free (hashes_start); /* Report the result */ return c % MONO_IMT_SIZE; } @@ -1323,7 +1336,7 @@ imt_sort_slot_entries (MonoImtBuilderEntry *entries) { imt_emit_ir (sorted_array, 0, number_of_entries, result); - free (sorted_array); + g_free (sorted_array); return result; } @@ -1333,15 +1346,15 @@ initialize_imt_slot (MonoVTable *vtable, MonoDomain *domain, MonoImtBuilderEntry MONO_REQ_GC_NEUTRAL_MODE; if (imt_builder_entry != NULL) { - if (imt_builder_entry->children == 0 && !fail_tramp && !always_build_imt_thunks) { + if (imt_builder_entry->children == 0 && !fail_tramp && !always_build_imt_trampolines) { /* No collision, return the vtable slot contents */ return vtable->vtable [imt_builder_entry->value.vtable_slot]; } else { - /* Collision, build the thunk */ + /* Collision, build the trampoline */ GPtrArray *imt_ir = imt_sort_slot_entries (imt_builder_entry); gpointer result; int i; - result = imt_thunk_builder (vtable, domain, + result = imt_trampoline_builder (vtable, domain, (MonoIMTCheckItem**)imt_ir->pdata, imt_ir->len, fail_tramp); for (i = 0; i < imt_ir->len; ++i) g_free (g_ptr_array_index (imt_ir, i)); @@ -1463,12 +1476,12 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* if (has_generic_virtual || has_variant_iface) { /* - * There might be collisions later when the the thunk is expanded. + * There might be collisions later when the the trampoline is expanded. */ imt_collisions_bitmap |= (1 << i); /* - * The IMT thunk might be called with an instance of one of the + * The IMT trampoline might be called with an instance of one of the * generic virtual methods, so has to fallback to the IMT trampoline. */ imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], callbacks.get_imt_trampoline (vt, i)); @@ -1503,7 +1516,7 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* entry = next; } } - free (imt_builder); + g_free (imt_builder); /* we OR the bitmap since we may build just a single imt slot at a time */ vt->imt_collisions_bitmap |= imt_collisions_bitmap; } @@ -1521,7 +1534,7 @@ build_imt (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* imt, * @imt_slot: slot in the IMT table * * Fill the given @imt_slot in the IMT table of @vtable with - * a trampoline or a thunk for the case of collisions. + * a trampoline or a trampoline for the case of collisions. * This is part of the internal mono API. * * LOCKING: Take the domain lock. @@ -1549,167 +1562,35 @@ mono_vtable_build_imt_slot (MonoVTable* vtable, int imt_slot) mono_loader_unlock (); } - -/* - * The first two free list entries both belong to the wait list: The - * first entry is the pointer to the head of the list and the second - * entry points to the last element. That way appending and removing - * the first element are both O(1) operations. - */ -#ifdef MONO_SMALL_CONFIG -#define NUM_FREE_LISTS 6 -#else -#define NUM_FREE_LISTS 12 -#endif -#define FIRST_FREE_LIST_SIZE 64 -#define MAX_WAIT_LENGTH 50 #define THUNK_THRESHOLD 10 -/* - * LOCKING: The domain lock must be held. - */ -static void -init_thunk_free_lists (MonoDomain *domain) -{ - MONO_REQ_GC_NEUTRAL_MODE; - - if (domain->thunk_free_lists) - return; - domain->thunk_free_lists = (MonoThunkFreeList **)mono_domain_alloc0 (domain, sizeof (gpointer) * NUM_FREE_LISTS); -} - -static int -list_index_for_size (int item_size) -{ - int i = 2; - int size = FIRST_FREE_LIST_SIZE; - - while (item_size > size && i < NUM_FREE_LISTS - 1) { - i++; - size <<= 1; - } - - return i; -} - /** - * mono_method_alloc_generic_virtual_thunk: + * mono_method_alloc_generic_virtual_trampoline: * @domain: a domain * @size: size in bytes * * Allocs size bytes to be used for the code of a generic virtual - * thunk. It's either allocated from the domain's code manager or + * trampoline. It's either allocated from the domain's code manager or * reused from a previously invalidated piece. * * LOCKING: The domain lock must be held. */ gpointer -mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size) +mono_method_alloc_generic_virtual_trampoline (MonoDomain *domain, int size) { MONO_REQ_GC_NEUTRAL_MODE; static gboolean inited = FALSE; - static int generic_virtual_thunks_size = 0; + static int generic_virtual_trampolines_size = 0; - guint32 *p; - int i; - MonoThunkFreeList **l; - - init_thunk_free_lists (domain); - - size += sizeof (guint32); - if (size < sizeof (MonoThunkFreeList)) - size = sizeof (MonoThunkFreeList); - - i = list_index_for_size (size); - for (l = &domain->thunk_free_lists [i]; *l; l = &(*l)->next) { - if ((*l)->size >= size) { - MonoThunkFreeList *item = *l; - *l = item->next; - return ((guint32*)item) + 1; - } - } - - /* no suitable item found - search lists of larger sizes */ - while (++i < NUM_FREE_LISTS) { - MonoThunkFreeList *item = domain->thunk_free_lists [i]; - if (!item) - continue; - g_assert (item->size > size); - domain->thunk_free_lists [i] = item->next; - return ((guint32*)item) + 1; - } - - /* still nothing found - allocate it */ if (!inited) { - mono_counters_register ("Generic virtual thunk bytes", - MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &generic_virtual_thunks_size); + mono_counters_register ("Generic virtual trampoline bytes", + MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &generic_virtual_trampolines_size); inited = TRUE; } - generic_virtual_thunks_size += size; - - p = (guint32 *)mono_domain_code_reserve (domain, size); - *p = size; - - mono_domain_lock (domain); - if (!domain->generic_virtual_thunks) - domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL); - g_hash_table_insert (domain->generic_virtual_thunks, p, p); - mono_domain_unlock (domain); + generic_virtual_trampolines_size += size; - return p + 1; -} - -/* - * LOCKING: The domain lock must be held. - */ -static void -invalidate_generic_virtual_thunk (MonoDomain *domain, gpointer code) -{ - MONO_REQ_GC_NEUTRAL_MODE; - - guint32 *p = (guint32 *)code; - MonoThunkFreeList *l = (MonoThunkFreeList*)(p - 1); - gboolean found = FALSE; - - mono_domain_lock (domain); - if (!domain->generic_virtual_thunks) - domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL); - if (g_hash_table_lookup (domain->generic_virtual_thunks, l)) - found = TRUE; - mono_domain_unlock (domain); - - if (!found) - /* Not allocated by mono_method_alloc_generic_virtual_thunk (), i.e. AOT */ - return; - init_thunk_free_lists (domain); - - while (domain->thunk_free_lists [0] && domain->thunk_free_lists [0]->length >= MAX_WAIT_LENGTH) { - MonoThunkFreeList *item = domain->thunk_free_lists [0]; - int length = item->length; - int i; - - /* unlink the first item from the wait list */ - domain->thunk_free_lists [0] = item->next; - domain->thunk_free_lists [0]->length = length - 1; - - i = list_index_for_size (item->size); - - /* put it in the free list */ - item->next = domain->thunk_free_lists [i]; - domain->thunk_free_lists [i] = item; - } - - l->next = NULL; - if (domain->thunk_free_lists [1]) { - domain->thunk_free_lists [1] = domain->thunk_free_lists [1]->next = l; - domain->thunk_free_lists [0]->length++; - } else { - g_assert (!domain->thunk_free_lists [0]); - - domain->thunk_free_lists [0] = domain->thunk_free_lists [1] = l; - domain->thunk_free_lists [0]->length = 1; - } + return mono_domain_code_reserve (domain, size); } typedef struct _GenericVirtualCase { @@ -1773,7 +1654,7 @@ get_generic_virtual_entries (MonoDomain *domain, gpointer *vtable_slot) * Registers a call via unmanaged code to a generic virtual method * instantiation or variant interface method. If the number of calls reaches a threshold * (THUNK_THRESHOLD), the method is added to the vtable slot's generic - * virtual method thunk. + * virtual method trampoline. */ void mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtable, @@ -1784,6 +1665,7 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab static gboolean inited = FALSE; static int num_added = 0; + static int num_freed = 0; GenericVirtualCase *gvc, *list; MonoImtBuilderEntry *entries; @@ -1794,6 +1676,12 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab if (!domain->generic_virtual_cases) domain->generic_virtual_cases = g_hash_table_new (mono_aligned_addr_hash, NULL); + if (!inited) { + mono_counters_register ("Generic virtual cases", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_added); + mono_counters_register ("Freed IMT trampolines", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_freed); + inited = TRUE; + } + /* Check whether the case was already added */ list = (GenericVirtualCase *)g_hash_table_lookup (domain->generic_virtual_cases, vtable_slot); gvc = list; @@ -1813,10 +1701,6 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab g_hash_table_insert (domain->generic_virtual_cases, vtable_slot, gvc); - if (!inited) { - mono_counters_register ("Generic virtual cases", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_added); - inited = TRUE; - } num_added++; } @@ -1829,7 +1713,7 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab int displacement = (gpointer*)vtable_slot - (gpointer*)vtable; int imt_slot = MONO_IMT_SIZE + displacement; - /* Force the rebuild of the thunk at the next call */ + /* Force the rebuild of the trampoline at the next call */ imt_trampoline = callbacks.get_imt_trampoline (vtable, imt_slot); *vtable_slot = imt_trampoline; } else { @@ -1839,8 +1723,8 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab sorted = imt_sort_slot_entries (entries); - *vtable_slot = imt_thunk_builder (NULL, domain, (MonoIMTCheckItem**)sorted->pdata, sorted->len, - vtable_trampoline); + *vtable_slot = imt_trampoline_builder (NULL, domain, (MonoIMTCheckItem**)sorted->pdata, sorted->len, + vtable_trampoline); while (entries) { MonoImtBuilderEntry *next = entries->next; @@ -1851,14 +1735,10 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab for (i = 0; i < sorted->len; ++i) g_free (g_ptr_array_index (sorted, i)); g_ptr_array_free (sorted, TRUE); - } -#ifndef __native_client__ - /* We don't re-use any thunks as there is a lot of overhead */ - /* to deleting and re-using code in Native Client. */ - if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline) - invalidate_generic_virtual_thunk (domain, old_thunk); -#endif + if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline) + num_freed ++; + } } mono_domain_unlock (domain); @@ -4289,11 +4169,7 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[], MonoArray *args = prepare_run_main (method, argc, argv); int res; if (exc) { - res = mono_runtime_try_exec_main (method, args, exc, &error); - if (*exc == NULL && !is_ok (&error)) - *exc = (MonoObject*) mono_error_convert_to_exception (&error); - else - mono_error_cleanup (&error); + res = mono_runtime_try_exec_main (method, args, exc); } else { res = mono_runtime_exec_main_checked (method, args, &error); mono_error_raise_exception (&error); /* OK to throw, external only without a better alternative */ @@ -4340,12 +4216,11 @@ mono_runtime_run_main_checked (MonoMethod *method, int argc, char* argv[], */ int mono_runtime_try_run_main (MonoMethod *method, int argc, char* argv[], - MonoObject **exc, MonoError *error) + MonoObject **exc) { g_assert (exc); - mono_error_init (error); MonoArray *args = prepare_run_main (method, argc, argv); - return mono_runtime_try_exec_main (method, args, exc, error); + return mono_runtime_try_exec_main (method, args, exc); } @@ -4665,10 +4540,13 @@ mono_unhandled_exception (MonoObject *exc) if (!current_appdomain_delegate && !root_appdomain_delegate) { mono_print_unhandled_exception (exc); } 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); + mono_threads_end_abort_protected_block (); } /* set exitcode only if we will abort the process */ @@ -4780,27 +4658,20 @@ do_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error) if (is_ok (error)) rval = 0; else { - /* If the return type of Main is void, only - * set the exitcode if an exception was thrown - * (we don't want to blow away an - * explicitly-set exit code) - */ rval = -1; - mono_environment_exitcode_set (rval); } } return rval; } static int -do_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc, MonoError *error) +do_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc) { MONO_REQ_GC_UNSAFE_MODE; gpointer pa [1]; int rval; - mono_error_init (error); g_assert (args); g_assert (exc); @@ -4808,12 +4679,13 @@ do_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc, MonoErr /* FIXME: check signature of method */ if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) { + MonoError inner_error; MonoObject *res; - res = mono_runtime_try_invoke (method, NULL, pa, exc, error); - if (*exc == NULL && !mono_error_ok (error)) - *exc = (MonoObject*) mono_error_convert_to_exception (error); + res = mono_runtime_try_invoke (method, NULL, pa, exc, &inner_error); + if (*exc == NULL && !mono_error_ok (&inner_error)) + *exc = (MonoObject*) mono_error_convert_to_exception (&inner_error); else - mono_error_cleanup (error); + mono_error_cleanup (&inner_error); if (*exc == NULL) rval = *(guint32 *)((char *)res + sizeof (MonoObject)); @@ -4822,11 +4694,12 @@ do_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc, MonoErr mono_environment_exitcode_set (rval); } else { - mono_runtime_try_invoke (method, NULL, pa, exc, error); - if (*exc == NULL && !mono_error_ok (error)) - *exc = (MonoObject*) mono_error_convert_to_exception (error); + MonoError inner_error; + mono_runtime_try_invoke (method, NULL, pa, exc, &inner_error); + if (*exc == NULL && !mono_error_ok (&inner_error)) + *exc = (MonoObject*) mono_error_convert_to_exception (&inner_error); else - mono_error_cleanup (error); + mono_error_cleanup (&inner_error); if (*exc == NULL) rval = 0; @@ -4854,11 +4727,7 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc) MonoError error; prepare_thread_to_exec_main (mono_object_domain (args), method); if (exc) { - int rval = do_try_exec_main (method, args, exc, &error); - if (*exc == NULL && !is_ok (&error)) - *exc = (MonoObject*) mono_error_convert_to_exception (&error); - else - mono_error_cleanup (&error); + int rval = do_try_exec_main (method, args, exc); return rval; } else { int rval = do_exec_main_checked (method, args, &error); @@ -4888,11 +4757,10 @@ mono_runtime_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError * * On failure sets @error if Main couldn't be executed, or @exc if it threw an exception. */ int -mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc, MonoError *error) +mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc) { - mono_error_init (error); prepare_thread_to_exec_main (mono_object_domain (args), method); - return do_try_exec_main (method, args, exc, error); + return do_try_exec_main (method, args, exc); } @@ -7547,9 +7415,19 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult gpointer wait_event = NULL; ac->msg->exc = NULL; + res = mono_message_invoke (ares->async_delegate, ac->msg, &ac->msg->exc, &ac->out_args, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; + + /* The exit side of the invoke must not be aborted as it would leave the runtime in an undefined state */ + mono_threads_begin_abort_protected_block (); + + if (!ac->msg->exc) { + MonoException *ex = mono_error_convert_to_exception (&error); + ac->msg->exc = (MonoObject *)ex; + } else { + mono_error_cleanup (&error); + } + MONO_OBJECT_SETREF (ac, res, res); mono_monitor_enter ((MonoObject*) ares); @@ -7559,13 +7437,16 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult mono_monitor_exit ((MonoObject*) ares); if (wait_event != NULL) - SetEvent (wait_event); + mono_w32event_set (wait_event); - if (ac->cb_method) { + mono_error_init (&error); //the else branch would leave it in an undefined state + if (ac->cb_method) mono_runtime_invoke_checked (ac->cb_method, ac->cb_target, (gpointer*) &ares, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; - } + + mono_threads_end_abort_protected_block (); + + if (mono_error_set_pending_exception (&error)) + return NULL; } return res; @@ -7580,88 +7461,24 @@ mono_message_init (MonoDomain *domain, { MONO_REQ_GC_UNSAFE_MODE; - static MonoClass *object_array_klass; - static MonoClass *byte_array_klass; - static MonoClass *string_array_klass; - mono_error_init (error); - MonoMethodSignature *sig = mono_method_signature (method->method); - MonoString *name; - MonoArray *arr; - int i, j; - char **names; - guint8 arg_type; - - if (!object_array_klass) { - MonoClass *klass; - - klass = mono_array_class_get (mono_defaults.byte_class, 1); - g_assert (klass); - byte_array_klass = klass; - - klass = mono_array_class_get (mono_defaults.string_class, 1); - g_assert (klass); - string_array_klass = klass; + static MonoMethod *init_message_method = NULL; - klass = mono_array_class_get (mono_defaults.object_class, 1); - g_assert (klass); - - mono_atomic_store_release (&object_array_klass, klass); + if (!init_message_method) { + init_message_method = mono_class_get_method_from_name (mono_defaults.mono_method_message_class, "InitMessage", 2); + g_assert (init_message_method != NULL); } - MONO_OBJECT_SETREF (this_obj, method, method); - - arr = mono_array_new_specific_checked (mono_class_vtable (domain, object_array_klass), sig->param_count, error); - return_val_if_nok (error, FALSE); - - MONO_OBJECT_SETREF (this_obj, args, arr); - - arr = mono_array_new_specific_checked (mono_class_vtable (domain, byte_array_klass), sig->param_count, error); - return_val_if_nok (error, FALSE); - - MONO_OBJECT_SETREF (this_obj, arg_types, arr); - - this_obj->async_result = NULL; - this_obj->call_type = CallType_Sync; - - names = g_new (char *, sig->param_count); - mono_method_get_param_names (method->method, (const char **) names); - - arr = mono_array_new_specific_checked (mono_class_vtable (domain, string_array_klass), sig->param_count, error); - if (!is_ok (error)) - goto fail; - - MONO_OBJECT_SETREF (this_obj, names, arr); + mono_error_init (error); + /* FIXME set domain instead? */ + g_assert (domain == mono_domain_get ()); - for (i = 0; i < sig->param_count; i++) { - name = mono_string_new_checked (domain, names [i], error); - if (!is_ok (error)) - goto fail; - mono_array_setref (this_obj->names, i, name); - } + gpointer args[2]; - g_free (names); - for (i = 0, j = 0; i < sig->param_count; i++) { - if (sig->params [i]->byref) { - if (out_args) { - MonoObject* arg = (MonoObject *)mono_array_get (out_args, gpointer, j); - mono_array_setref (this_obj->args, i, arg); - j++; - } - arg_type = 2; - if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT)) - arg_type |= 1; - } else { - arg_type = 1; - if (sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT) - arg_type |= 4; - } - mono_array_set (this_obj->arg_types, guint8, i, arg_type); - } + args[0] = method; + args[1] = out_args; - return TRUE; -fail: - g_free (names); - return FALSE; + mono_runtime_invoke_checked (init_message_method, this_obj, args, error); + return is_ok (error); } #ifndef DISABLE_REMOTING @@ -8287,28 +8104,6 @@ mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFie return result; } -/** - * mono_load_remote_field_new_icall: - * @this: pointer to an object - * @klass: klass of the object containing @field - * @field: the field to load - * - * This method is called by the runtime on attempts to load fields of - * transparent proxy objects. @this points to such TP, @klass is the class of - * the object containing @field. - * - * Returns: a freshly allocated object containing the value of the - * field. On failure returns NULL and throws an exception. - */ -MonoObject * -mono_load_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field) -{ - MonoError error; - MonoObject *result = mono_load_remote_field_new_checked (this_obj, klass, field, &error); - mono_error_set_pending_exception (&error); - return result; -} - /** * mono_load_remote_field_new_checked: * @this: pointer to an object @@ -8329,69 +8124,25 @@ mono_load_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, Mono mono_error_init (error); - static MonoMethod *getter = NULL; - MonoDomain *domain = mono_domain_get (); - MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj; - MonoClass *field_class; - MonoMethodMessage *msg; - MonoArray *out_args; - MonoObject *exc, *res; - char* full_name; + static MonoMethod *tp_load = NULL; g_assert (mono_object_is_transparent_proxy (this_obj)); - field_class = mono_class_from_mono_type (field->type); - - if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) { - gpointer val; - if (field_class->valuetype) { - res = mono_object_new_checked (domain, field_class, error); - return_val_if_nok (error, NULL); - val = ((gchar *) res) + sizeof (MonoObject); - } else { - val = &res; - } - mono_field_get_value (tp->rp->unwrapped_server, field, val); - return res; - } - - if (!getter) { - getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1); - if (!getter) { + if (!tp_load) { + tp_load = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "LoadRemoteFieldNew", -1); + if (!tp_load) { mono_error_set_not_supported (error, "Linked away."); return NULL; } } - msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error); - return_val_if_nok (error, NULL); - out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, error); - return_val_if_nok (error, NULL); + /* MonoType *type = mono_class_get_type (klass); */ - MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, error); - return_val_if_nok (error, NULL); - mono_message_init (domain, msg, rm, out_args, error); - 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))); - g_free (full_name); + gpointer args[2]; + args [0] = &klass; + args [1] = &field; - mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error); - return_val_if_nok (error, NULL); - - if (exc) { - mono_error_set_exception_instance (error, (MonoException *)exc); - return NULL; - } - - if (mono_array_length (out_args) == 0) - res = NULL; - else - res = mono_array_get (out_args, MonoObject *, 0); - - return res; + return mono_runtime_invoke_checked (tp_load, this_obj, args, error); } /** @@ -8433,65 +8184,24 @@ mono_store_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoCla MONO_REQ_GC_UNSAFE_MODE; - static MonoMethod *setter = NULL; + mono_error_init (error); MonoDomain *domain = mono_domain_get (); - MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj; MonoClass *field_class; - MonoMethodMessage *msg; - MonoArray *out_args; - MonoObject *exc; MonoObject *arg; - char* full_name; - - mono_error_init (error); g_assert (mono_object_is_transparent_proxy (this_obj)); field_class = mono_class_from_mono_type (field->type); - if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) { - if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val); - else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val)); - return TRUE; - } - - if (!setter) { - setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1); - if (!setter) { - mono_error_set_not_supported (error, "Linked away."); - return FALSE; - } - } - if (field_class->valuetype) { arg = mono_value_box_checked (domain, field_class, val, error); return_val_if_nok (error, FALSE); - } else - arg = *((MonoObject **)val); - - - msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error); - return_val_if_nok (error, FALSE); - MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, error); - return_val_if_nok (error, FALSE); - mono_message_init (domain, msg, rm, NULL, error); - return_val_if_nok (error, FALSE); - - 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))); - mono_array_setref (msg->args, 2, arg); - g_free (full_name); - - mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error); - return_val_if_nok (error, FALSE); - - if (exc) { - mono_error_set_exception_instance (error, (MonoException *)exc); - return FALSE; + } else { + arg = *((MonoObject**)val); } - return TRUE; + + return mono_store_remote_field_new_checked (this_obj, klass, field, arg, error); } /** @@ -8511,23 +8221,6 @@ mono_store_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFi mono_error_cleanup (&error); } -/** - * mono_store_remote_field_new_icall: - * @this_obj: - * @klass: - * @field: - * @arg: - * - * Missing documentation - */ -void -mono_store_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg) -{ - MonoError error; - (void) mono_store_remote_field_new_checked (this_obj, klass, field, arg, &error); - mono_error_set_pending_exception (&error); -} - /** * mono_store_remote_field_new_checked: * @this_obj: @@ -8543,56 +8236,27 @@ mono_store_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, Mon { MONO_REQ_GC_UNSAFE_MODE; - static MonoMethod *setter = NULL; - MonoDomain *domain = mono_domain_get (); - MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj; - MonoClass *field_class; - MonoMethodMessage *msg; - MonoArray *out_args; - MonoObject *exc; - char* full_name; + static MonoMethod *tp_store = NULL; mono_error_init (error); g_assert (mono_object_is_transparent_proxy (this_obj)); - field_class = mono_class_from_mono_type (field->type); - - if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) { - if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject)); - else mono_field_set_value (tp->rp->unwrapped_server, field, arg); - return TRUE; - } - - if (!setter) { - setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1); - if (!setter) { + if (!tp_store) { + tp_store = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "StoreRemoteField", -1); + if (!tp_store) { mono_error_set_not_supported (error, "Linked away."); return FALSE; } } - msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error); - return_val_if_nok (error, FALSE); - MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, error); - return_val_if_nok (error, FALSE); - mono_message_init (domain, msg, rm, NULL, error); - return_val_if_nok (error, FALSE); - - 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))); - mono_array_setref (msg->args, 2, arg); - g_free (full_name); + gpointer args[3]; + args [0] = &klass; + args [1] = &field; + args [2] = arg; - mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error); - return_val_if_nok (error, FALSE); - - if (exc) { - mono_error_set_exception_instance (error, (MonoException *)exc); - return FALSE; - } - return TRUE; + mono_runtime_invoke_checked (tp_store, this_obj, args, error); + return is_ok (error); } #endif