2 * object.c: Object creation for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001-2004 Ximian, Inc.
15 #include <mono/metadata/mono-endian.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/metadata/tokentype.h>
18 #include <mono/metadata/loader.h>
19 #include <mono/metadata/object.h>
20 #include <mono/metadata/gc-internal.h>
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/domain-internals.h>
23 #include "mono/metadata/metadata-internals.h"
24 #include "mono/metadata/class-internals.h"
25 #include <mono/metadata/assembly.h>
26 #include <mono/metadata/threadpool.h>
27 #include <mono/metadata/marshal.h>
28 #include "mono/metadata/debug-helpers.h"
29 #include "mono/metadata/marshal.h"
30 #include <mono/metadata/threads.h>
31 #include <mono/metadata/threads-types.h>
32 #include <mono/metadata/environment.h>
33 #include "mono/metadata/profiler-private.h"
34 #include "mono/metadata/security-manager.h"
35 #include "mono/metadata/mono-debug-debugger.h"
36 #include <mono/os/gc_wrapper.h>
37 #include <mono/utils/strenc.h>
40 #define NEED_TO_ZERO_PTRFREE 1
41 #define ALLOC_PTRFREE(obj,vt,size) do { (obj) = GC_MALLOC_ATOMIC ((size)); (obj)->vtable = (vt); (obj)->synchronisation = NULL;} while (0)
42 #define ALLOC_OBJECT(obj,vt,size) do { (obj) = GC_MALLOC ((size)); (obj)->vtable = (vt);} while (0)
43 #ifdef HAVE_GC_GCJ_MALLOC
44 #define CREATION_SPEEDUP 1
45 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
46 #define ALLOC_TYPED(dest,size,type) do { (dest) = GC_GCJ_MALLOC ((size),(type)); } while (0)
47 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) GC_make_descriptor((GC_bitmap)(bitmap),(sz))
48 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) GC_make_descriptor((GC_bitmap)(bitmap),(sz))
50 #define GC_NO_DESCRIPTOR (NULL)
51 #define ALLOC_TYPED(dest,size,type) do { (dest) = GC_MALLOC ((size)); *(gpointer*)dest = (type);} while (0)
52 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) NULL
53 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) NULL
57 #define GC_NO_DESCRIPTOR (NULL)
58 #define ALLOC_PTRFREE(obj,vt,size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0)
59 #define ALLOC_OBJECT(obj,vt,size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0)
60 #define ALLOC_TYPED(dest,size,type) do { (dest) = mono_gc_alloc_obj (type, size);} while (0)
61 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) mono_gc_make_descr_for_string ()
62 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) mono_gc_make_descr_for_object ((bitmap), (sz), (objsize))
64 #define NEED_TO_ZERO_PTRFREE 1
65 #define GC_NO_DESCRIPTOR (NULL)
66 #define ALLOC_PTRFREE(obj,vt,size) do { (obj) = malloc ((size)); (obj)->vtable = (vt); (obj)->synchronisation = NULL;} while (0)
67 #define ALLOC_OBJECT(obj,vt,size) do { (obj) = calloc (1, (size)); (obj)->vtable = (vt);} while (0)
68 #define ALLOC_TYPED(dest,size,type) do { (dest) = calloc (1, (size)); *(gpointer*)dest = (type);} while (0)
69 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) NULL
70 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) NULL
74 static MonoObject* mono_object_new_ptrfree (MonoVTable *vtable);
75 static MonoObject* mono_object_new_ptrfree_box (MonoVTable *vtable);
78 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value);
81 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig);
83 #define ldstr_lock() EnterCriticalSection (&ldstr_section)
84 #define ldstr_unlock() LeaveCriticalSection (&ldstr_section)
85 static CRITICAL_SECTION ldstr_section;
88 mono_runtime_object_init (MonoObject *this)
90 MonoMethod *method = NULL;
91 MonoClass *klass = this->vtable->klass;
93 method = mono_class_get_method_from_name (klass, ".ctor", 0);
96 if (method->klass->valuetype)
97 this = mono_object_unbox (this);
98 mono_runtime_invoke (method, this, NULL, NULL);
101 /* The pseudo algorithm for type initialization from the spec
102 Note it doesn't say anything about domains - only threads.
104 2. If the type is initialized you are done.
105 2.1. If the type is not yet initialized, try to take an
107 2.2. If successful, record this thread as responsible for
108 initializing the type and proceed to step 2.3.
109 2.2.1. If not, see whether this thread or any thread
110 waiting for this thread to complete already holds the lock.
111 2.2.2. If so, return since blocking would create a deadlock. This thread
112 will now see an incompletely initialized state for the type,
113 but no deadlock will arise.
114 2.2.3 If not, block until the type is initialized then return.
115 2.3 Initialize the parent type and then all interfaces implemented
117 2.4 Execute the type initialization code for this type.
118 2.5 Mark the type as initialized, release the initialization lock,
119 awaken any threads waiting for this type to be initialized,
126 guint32 initializing_tid;
127 guint32 waiting_count;
129 CRITICAL_SECTION initialization_section;
130 } TypeInitializationLock;
132 /* for locking access to type_initialization_hash and blocked_thread_hash */
133 #define mono_type_initialization_lock() EnterCriticalSection (&type_initialization_section)
134 #define mono_type_initialization_unlock() LeaveCriticalSection (&type_initialization_section)
135 static CRITICAL_SECTION type_initialization_section;
137 /* from vtable to lock */
138 static GHashTable *type_initialization_hash;
140 /* from thread id to thread id being waited on */
141 static GHashTable *blocked_thread_hash;
144 static MonoThread *main_thread;
147 * mono_thread_set_main:
148 * @thread: thread to set as the main thread
150 * This function can be used to instruct the runtime to treat @thread
151 * as the main thread, ie, the thread that would normally execute the Main()
152 * method. This basically means that at the end of @thread, the runtime will
153 * wait for the existing foreground threads to quit and other such details.
156 mono_thread_set_main (MonoThread *thread)
158 main_thread = thread;
162 mono_thread_get_main (void)
168 mono_type_initialization_init (void)
170 InitializeCriticalSection (&type_initialization_section);
171 type_initialization_hash = g_hash_table_new (NULL, NULL);
172 blocked_thread_hash = g_hash_table_new (NULL, NULL);
173 InitializeCriticalSection (&ldstr_section);
177 mono_type_initialization_cleanup (void)
180 /* This is causing race conditions with
181 * mono_release_type_locks
183 DeleteCriticalSection (&type_initialization_section);
185 DeleteCriticalSection (&ldstr_section);
189 * get_type_init_exception_for_vtable:
191 * Return the stored type initialization exception for VTABLE.
193 static MonoException*
194 get_type_init_exception_for_vtable (MonoVTable *vtable)
196 MonoDomain *domain = vtable->domain;
197 MonoClass *klass = vtable->klass;
201 g_assert (vtable->init_failed);
204 * If the initializing thread was rudely aborted, the exception is not stored
208 mono_domain_lock (domain);
209 if (domain->type_init_exception_hash)
210 ex = mono_g_hash_table_lookup (domain->type_init_exception_hash, klass);
211 mono_domain_unlock (domain);
214 if (klass->name_space && *klass->name_space)
215 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
217 full_name = g_strdup (klass->name);
218 ex = mono_get_exception_type_initialization (full_name, NULL);
226 * mono_runtime_class_init:
227 * @vtable: vtable that needs to be initialized
229 * This routine calls the class constructor for @vtable.
232 mono_runtime_class_init (MonoVTable *vtable)
235 MonoException *exc_to_throw;
236 MonoMethod *method = NULL;
242 if (vtable->initialized)
246 klass = vtable->klass;
248 method = mono_class_get_cctor (klass);
251 MonoDomain *domain = vtable->domain;
252 TypeInitializationLock *lock;
253 guint32 tid = GetCurrentThreadId();
254 int do_initialization = 0;
255 MonoDomain *last_domain = NULL;
257 mono_type_initialization_lock ();
258 /* double check... */
259 if (vtable->initialized) {
260 mono_type_initialization_unlock ();
263 if (vtable->init_failed) {
264 mono_type_initialization_unlock ();
266 /* The type initialization already failed once, rethrow the same exception */
267 mono_raise_exception (get_type_init_exception_for_vtable (vtable));
270 lock = g_hash_table_lookup (type_initialization_hash, vtable);
272 /* This thread will get to do the initialization */
273 if (mono_domain_get () != domain) {
274 /* Transfer into the target domain */
275 last_domain = mono_domain_get ();
276 if (!mono_domain_set (domain, FALSE)) {
277 vtable->initialized = 1;
278 mono_type_initialization_unlock ();
279 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
282 lock = g_malloc (sizeof(TypeInitializationLock));
283 InitializeCriticalSection (&lock->initialization_section);
284 lock->initializing_tid = tid;
285 lock->waiting_count = 1;
287 /* grab the vtable lock while this thread still owns type_initialization_section */
288 EnterCriticalSection (&lock->initialization_section);
289 g_hash_table_insert (type_initialization_hash, vtable, lock);
290 do_initialization = 1;
293 TypeInitializationLock *pending_lock;
295 if (lock->initializing_tid == tid || lock->done) {
296 mono_type_initialization_unlock ();
299 /* see if the thread doing the initialization is already blocked on this thread */
300 blocked = GUINT_TO_POINTER (lock->initializing_tid);
301 while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) {
302 if (pending_lock->initializing_tid == tid) {
303 if (!pending_lock->done) {
304 mono_type_initialization_unlock ();
307 /* the thread doing the initialization is blocked on this thread,
308 but on a lock that has already been freed. It just hasn't got
313 blocked = GUINT_TO_POINTER (pending_lock->initializing_tid);
315 ++lock->waiting_count;
316 /* record the fact that we are waiting on the initializing thread */
317 g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
319 mono_type_initialization_unlock ();
321 if (do_initialization) {
322 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
324 /* If the initialization failed, mark the class as unusable. */
325 /* Avoid infinite loops */
327 (klass->image == mono_defaults.corlib &&
328 !strcmp (klass->name_space, "System") &&
329 !strcmp (klass->name, "TypeInitializationException")))) {
330 vtable->init_failed = 1;
332 if (klass->name_space && *klass->name_space)
333 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
335 full_name = g_strdup (klass->name);
336 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
340 * Store the exception object so it could be thrown on subsequent
343 mono_domain_lock (domain);
344 if (!domain->type_init_exception_hash)
345 domain->type_init_exception_hash = mono_g_hash_table_new_type (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC);
346 mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_throw);
347 mono_domain_unlock (domain);
351 mono_domain_set (last_domain, TRUE);
353 LeaveCriticalSection (&lock->initialization_section);
355 /* this just blocks until the initializing thread is done */
356 EnterCriticalSection (&lock->initialization_section);
357 LeaveCriticalSection (&lock->initialization_section);
360 mono_type_initialization_lock ();
361 if (lock->initializing_tid != tid)
362 g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
363 --lock->waiting_count;
364 if (lock->waiting_count == 0) {
365 DeleteCriticalSection (&lock->initialization_section);
366 g_hash_table_remove (type_initialization_hash, vtable);
369 if (!vtable->init_failed)
370 vtable->initialized = 1;
371 mono_type_initialization_unlock ();
373 if (vtable->init_failed) {
374 /* Either we were the initializing thread or we waited for the initialization */
375 mono_raise_exception (get_type_init_exception_for_vtable (vtable));
378 vtable->initialized = 1;
384 gboolean release_type_locks (gpointer key, gpointer value, gpointer user)
386 MonoVTable *vtable = (MonoVTable*)key;
388 TypeInitializationLock *lock = (TypeInitializationLock*) value;
389 if (lock->initializing_tid == GPOINTER_TO_UINT (user) && !lock->done) {
392 * Have to set this since it cannot be set by the normal code in
393 * mono_runtime_class_init (). In this case, the exception object is not stored,
394 * and get_type_init_exception_for_class () needs to be aware of this.
396 vtable->init_failed = 1;
397 LeaveCriticalSection (&lock->initialization_section);
398 --lock->waiting_count;
399 if (lock->waiting_count == 0) {
400 DeleteCriticalSection (&lock->initialization_section);
409 mono_release_type_locks (MonoThread *thread)
411 mono_type_initialization_lock ();
412 g_hash_table_foreach_remove (type_initialization_hash, release_type_locks, (gpointer)(gsize)(thread->tid));
413 mono_type_initialization_unlock ();
417 default_trampoline (MonoMethod *method)
423 default_remoting_trampoline (MonoMethod *method, MonoRemotingTarget target)
425 g_error ("remoting not installed");
430 default_delegate_trampoline (MonoMethod *method, gpointer addr)
432 g_assert_not_reached ();
436 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
437 static MonoRemotingTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
438 static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline;
441 mono_install_trampoline (MonoTrampoline func)
443 arch_create_jit_trampoline = func? func: default_trampoline;
447 mono_install_remoting_trampoline (MonoRemotingTrampoline func)
449 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
453 mono_install_delegate_trampoline (MonoDelegateTrampoline func)
455 arch_create_delegate_trampoline = func? func: default_delegate_trampoline;
458 static MonoCompileFunc default_mono_compile_method = NULL;
461 * mono_install_compile_method:
462 * @func: function to install
464 * This is a VM internal routine
467 mono_install_compile_method (MonoCompileFunc func)
469 default_mono_compile_method = func;
473 * mono_compile_method:
474 * @method: The method to compile.
476 * This JIT-compiles the method, and returns the pointer to the native code
480 mono_compile_method (MonoMethod *method)
482 if (!default_mono_compile_method) {
483 g_error ("compile method called on uninitialized runtime");
486 return default_mono_compile_method (method);
489 static MonoFreeMethodFunc default_mono_free_method = NULL;
492 * mono_install_free_method:
493 * @func: pointer to the MonoFreeMethodFunc used to release a method
495 * This is an internal VM routine, it is used for the engines to
496 * register a handler to release the resources associated with a method.
498 * Methods are freed when no more references to the delegate that holds
502 mono_install_free_method (MonoFreeMethodFunc func)
504 default_mono_free_method = func;
508 * mono_runtime_free_method:
509 * @domain; domain where the method is hosted
510 * @method: method to release
512 * This routine is invoked to free the resources associated with
513 * a method that has been JIT compiled. This is used to discard
514 * methods that were used only temporarily (for example, used in marshalling)
518 mono_runtime_free_method (MonoDomain *domain, MonoMethod *method)
520 if (default_mono_free_method != NULL)
521 default_mono_free_method (domain, method);
523 mono_free_method (method);
526 static MonoInitVTableFunc init_vtable_func = NULL;
529 * mono_install_init_vtable:
530 * @func: pointer to the function to be installed
532 * Register a function which will be called by the runtime to initialize the
533 * method pointers inside a vtable. The JIT can use this function to load the
534 * vtable from the AOT file for example.
537 mono_install_init_vtable (MonoInitVTableFunc func)
539 init_vtable_func = func;
543 * The vtables in the root appdomain are assumed to be reachable by other
544 * roots, and we don't use typed allocation in the other domains.
547 /* The sync block is no longer a GC pointer */
548 #define GC_HEADER_BITMAP (0)
550 #define BITMAP_EL_SIZE (sizeof (gsize) * 8)
553 compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set, gboolean static_fields)
555 MonoClassField *field;
561 max_size = mono_class_data_size (class) / sizeof (gpointer);
563 max_size = class->instance_size / sizeof (gpointer);
564 if (max_size > size) {
565 bitmap = g_malloc0 (sizeof (gsize) * ((max_size) + 1));
568 for (p = class; p != NULL; p = p->parent) {
569 gpointer iter = NULL;
570 while ((field = mono_class_get_fields (p, &iter))) {
574 if (!(field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA)))
577 if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
580 /* FIXME: should not happen, flag as type load error */
581 if (field->type->byref)
584 pos = field->offset / sizeof (gpointer);
587 type = mono_type_get_underlying_type (field->type);
588 switch (type->type) {
589 /* FIXME: _I and _U and _PTR should be removed eventually */
593 case MONO_TYPE_FNPTR:
597 case MONO_TYPE_STRING:
598 case MONO_TYPE_SZARRAY:
599 case MONO_TYPE_CLASS:
600 case MONO_TYPE_OBJECT:
601 case MONO_TYPE_ARRAY:
602 g_assert ((field->offset % sizeof(gpointer)) == 0);
604 bitmap [pos / BITMAP_EL_SIZE] |= ((gsize)1) << (pos % BITMAP_EL_SIZE);
605 *max_set = MAX (*max_set, pos);
607 case MONO_TYPE_GENERICINST:
608 if (!mono_type_generic_inst_is_valuetype (type)) {
609 g_assert ((field->offset % sizeof(gpointer)) == 0);
611 bitmap [pos / BITMAP_EL_SIZE] |= ((gsize)1) << (pos % BITMAP_EL_SIZE);
612 *max_set = MAX (*max_set, pos);
617 case MONO_TYPE_VALUETYPE: {
618 MonoClass *fclass = mono_class_from_mono_type (field->type);
619 if (fclass->has_references) {
620 /* remove the object header */
621 compute_class_bitmap (fclass, bitmap, size, pos - (sizeof (MonoObject) / sizeof (gpointer)), max_set, FALSE);
635 case MONO_TYPE_BOOLEAN:
639 g_assert_not_reached ();
650 mono_class_compute_gc_descriptor (MonoClass *class)
654 gsize default_bitmap [4] = {0};
655 static gboolean gcj_inited = FALSE;
660 mono_register_jit_icall (mono_object_new_ptrfree, "mono_object_new_ptrfree", mono_create_icall_signature ("object ptr"), FALSE);
661 mono_register_jit_icall (mono_object_new_ptrfree_box, "mono_object_new_ptrfree_box", mono_create_icall_signature ("object ptr"), FALSE);
662 mono_register_jit_icall (mono_object_new_fast, "mono_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE);
664 #ifdef HAVE_GC_GCJ_MALLOC
666 GC_init_gcj_malloc (5, NULL);
668 #ifdef GC_REDIRECT_TO_LOCAL
669 mono_register_jit_icall (GC_local_gcj_malloc, "GC_local_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
670 mono_register_jit_icall (GC_local_gcj_fast_malloc, "GC_local_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
672 mono_register_jit_icall (GC_gcj_malloc, "GC_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
673 mono_register_jit_icall (GC_gcj_fast_malloc, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
676 mono_loader_unlock ();
680 mono_class_init (class);
682 if (class->gc_descr_inited)
685 class->gc_descr_inited = TRUE;
686 class->gc_descr = GC_NO_DESCRIPTOR;
688 bitmap = default_bitmap;
689 if (class == mono_defaults.string_class) {
690 class->gc_descr = (gpointer)MAKE_STRING_DESCRIPTOR (bitmap, 2);
691 } else if (class->rank) {
692 mono_class_compute_gc_descriptor (class->element_class);
694 /* libgc has no usable support for arrays... */
695 if (!class->element_class->valuetype) {
697 class->gc_descr = mono_gc_make_descr_for_array (TRUE, &abm, 1, sizeof (gpointer));
698 /*printf ("new array descriptor: 0x%x for %s.%s\n", class->gc_descr,
699 class->name_space, class->name);*/
701 /* remove the object header */
702 bitmap = compute_class_bitmap (class->element_class, default_bitmap, sizeof (default_bitmap) * 8, - (sizeof (MonoObject) / sizeof (gpointer)), &max_set, FALSE);
703 class->gc_descr = mono_gc_make_descr_for_array (TRUE, bitmap, mono_array_element_size (class) / sizeof (gpointer), mono_array_element_size (class));
704 /*printf ("new vt array descriptor: 0x%x for %s.%s\n", class->gc_descr,
705 class->name_space, class->name);*/
706 if (bitmap != default_bitmap)
711 /*static int count = 0;
714 bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, FALSE);
716 /* It seems there are issues when the bitmap doesn't fit: play it safe */
718 /*g_print ("disabling typed alloc (%d) for %s.%s\n", max_set, class->name_space, class->name);*/
719 if (bitmap != default_bitmap)
724 class->gc_descr = (gpointer)MAKE_DESCRIPTOR (bitmap, max_set + 1, class->instance_size);
725 /*printf ("new descriptor: %p 0x%x for %s.%s\n", class->gc_descr, bitmap [0], class->name_space, class->name);*/
726 if (bitmap != default_bitmap)
732 * field_is_special_static:
733 * @fklass: The MonoClass to look up.
734 * @field: The MonoClassField describing the field.
736 * Returns: SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
737 * SPECIAL_STATIC_NONE otherwise.
740 field_is_special_static (MonoClass *fklass, MonoClassField *field)
742 MonoCustomAttrInfo *ainfo;
744 ainfo = mono_custom_attrs_from_field (fklass, field);
747 for (i = 0; i < ainfo->num_attrs; ++i) {
748 MonoClass *klass = ainfo->attrs [i].ctor->klass;
749 if (klass->image == mono_defaults.corlib) {
750 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
751 mono_custom_attrs_free (ainfo);
752 return SPECIAL_STATIC_THREAD;
754 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
755 mono_custom_attrs_free (ainfo);
756 return SPECIAL_STATIC_CONTEXT;
760 mono_custom_attrs_free (ainfo);
761 return SPECIAL_STATIC_NONE;
764 static MonoVTable *mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class);
768 * @domain: the application domain
769 * @class: the class to initialize
771 * VTables are domain specific because we create domain specific code, and
772 * they contain the domain specific static class data.
775 mono_class_vtable (MonoDomain *domain, MonoClass *class)
777 MonoClassRuntimeInfo *runtime_info;
781 /* this check can be inlined in jitted code, too */
782 runtime_info = class->runtime_info;
783 if (runtime_info && runtime_info->max_domain >= domain->domain_id && runtime_info->domain_vtables [domain->domain_id])
784 return runtime_info->domain_vtables [domain->domain_id];
785 return mono_class_create_runtime_vtable (domain, class);
789 mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
792 MonoClassRuntimeInfo *runtime_info, *old_info;
793 MonoClassField *field;
796 gboolean inited = FALSE;
797 guint32 vtable_size, class_size;
799 guint32 constant_cols [MONO_CONSTANT_SIZE];
801 gpointer *interface_offsets;
803 mono_domain_lock (domain);
804 runtime_info = class->runtime_info;
805 if (runtime_info && runtime_info->max_domain >= domain->domain_id && runtime_info->domain_vtables [domain->domain_id]) {
806 mono_domain_unlock (domain);
807 return runtime_info->domain_vtables [domain->domain_id];
809 if (!class->inited || class->exception_type) {
810 if (!mono_class_init (class) || class->exception_type){
812 mono_domain_unlock (domain);
813 exc = mono_class_get_exception_for_failure (class);
815 mono_raise_exception (exc);
819 mono_class_init (class);
821 /* FIXME: This should be done by mono_class_init () for dynamic classes as well */
822 if (class->image->dynamic)
823 mono_class_setup_vtable (class);
825 vtable_size = sizeof (gpointer) * (class->max_interface_id + 1) +
826 sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
828 mono_stats.used_class_count++;
829 mono_stats.class_vtable_size += vtable_size;
830 interface_offsets = mono_mempool_alloc0 (domain->mp, vtable_size);
832 vt = (MonoVTable*) (interface_offsets + class->max_interface_id + 1);
834 vt->rank = class->rank;
837 mono_class_compute_gc_descriptor (class);
839 * We can't use typed allocation in the non-root domains, since the
840 * collector needs the GC descriptor stored in the vtable even after
841 * the mempool containing the vtable is destroyed when the domain is
842 * unloaded. An alternative might be to allocate vtables in the GC
843 * heap, but this does not seem to work (it leads to crashes inside
844 * libgc). If that approach is tried, two gc descriptors need to be
845 * allocated for each class: one for the root domain, and one for all
846 * other domains. The second descriptor should contain a bit for the
847 * vtable field in MonoObject, since we can no longer assume the
848 * vtable is reachable by other roots after the appdomain is unloaded.
851 if (domain != mono_get_root_domain ())
852 vt->gc_descr = GC_NO_DESCRIPTOR;
855 vt->gc_descr = class->gc_descr;
857 if ((class_size = mono_class_data_size (class))) {
858 if (class->has_static_refs) {
859 gpointer statics_gc_descr;
861 gsize default_bitmap [4] = {0};
864 bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, TRUE);
865 /*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class_size);*/
866 statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set? max_set + 1: 0);
867 vt->data = mono_gc_alloc_fixed (class_size, statics_gc_descr);
868 mono_domain_add_class_static_data (domain, class, vt->data, NULL);
869 if (bitmap != default_bitmap)
872 vt->data = mono_mempool_alloc0 (domain->mp, class_size);
874 mono_stats.class_static_data_size += class_size;
879 while ((field = mono_class_get_fields (class, &iter))) {
880 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
882 if (mono_field_is_deleted (field))
884 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
885 gint32 special_static = class->no_special_static_fields ? SPECIAL_STATIC_NONE : field_is_special_static (class, field);
886 if (special_static != SPECIAL_STATIC_NONE) {
887 guint32 size, offset;
889 size = mono_type_size (field->type, &align);
890 offset = mono_alloc_special_static_data (special_static, size, align);
891 if (!domain->special_static_fields)
892 domain->special_static_fields = g_hash_table_new (NULL, NULL);
893 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
897 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
898 MonoClass *fklass = mono_class_from_mono_type (field->type);
899 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT));
900 t = (char*)vt->data + field->offset;
901 if (fklass->valuetype) {
902 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
904 /* it's a pointer type: add check */
905 g_assert ((fklass->byval_arg.type == MONO_TYPE_PTR) || (fklass->byval_arg.type == MONO_TYPE_FNPTR));
906 *t = *(char *)field->data;
910 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
913 /* later do this only on demand if needed */
915 cindex = mono_metadata_get_constant_index (class->image, mono_class_get_field_token (field), cindex + 1);
917 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
919 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
920 field->def_type = constant_cols [MONO_CONSTANT_TYPE];
921 field->data = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
926 vt->max_interface_id = class->max_interface_id;
928 /* initialize interface offsets */
929 for (i = 0; i <= class->max_interface_id; ++i) {
930 int slot = class->interface_offsets [i];
932 interface_offsets [class->max_interface_id - i] = &(vt->vtable [slot]);
936 * arch_create_jit_trampoline () can recursively call this function again
937 * because it compiles icall methods right away.
939 /* FIXME: class_vtable_hash is basically obsolete now: remove as soon
940 * as we change the code in appdomain.c to invalidate vtables by
941 * looking at the possible MonoClasses created for the domain.
943 g_hash_table_insert (domain->class_vtable_hash, class, vt);
944 /* class->runtime_info is protected by the loader lock, both when
945 * it it enlarged and when it is stored info.
948 old_info = class->runtime_info;
949 if (old_info && old_info->max_domain >= domain->domain_id) {
950 /* someone already created a large enough runtime info */
951 old_info->domain_vtables [domain->domain_id] = vt;
953 int new_size = domain->domain_id;
955 new_size = MAX (new_size, old_info->max_domain);
957 /* make the new size a power of two */
962 /* this is a bounded memory retention issue: may want to
963 * handle it differently when we'll have a rcu-like system.
965 runtime_info = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassRuntimeInfo) + new_size * sizeof (gpointer));
966 runtime_info->max_domain = new_size - 1;
967 /* copy the stuff from the older info */
969 memcpy (runtime_info->domain_vtables, old_info->domain_vtables, (old_info->max_domain + 1) * sizeof (gpointer));
971 runtime_info->domain_vtables [domain->domain_id] = vt;
972 /* keep this last (add membarrier) */
973 class->runtime_info = runtime_info;
975 mono_loader_unlock ();
977 /* initialize vtable */
978 if (init_vtable_func)
979 inited = init_vtable_func (vt);
982 mono_class_setup_vtable (class);
984 for (i = 0; i < class->vtable_size; ++i) {
987 if ((cm = class->vtable [i])) {
988 if (mono_method_signature (cm)->generic_param_count)
991 vt->vtable [i] = arch_create_jit_trampoline (cm);
996 mono_domain_unlock (domain);
998 /* Initialization is now complete, we can throw if the InheritanceDemand aren't satisfied */
999 if (mono_is_security_manager_active () && (class->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND)) {
1000 MonoException *exc = mono_class_get_exception_for_failure (class);
1002 mono_raise_exception (exc);
1005 /* make sure the the parent is initialized */
1007 mono_class_vtable (domain, class->parent);
1009 vt->type = mono_type_get_object (domain, &class->byval_arg);
1010 if (class->contextbound)
1019 * mono_class_proxy_vtable:
1020 * @domain: the application domain
1021 * @remove_class: the remote class
1023 * Creates a vtable for transparent proxies. It is basically
1024 * a copy of the real vtable of the class wrapped in @remote_class,
1025 * but all function pointers invoke the remoting functions, and
1026 * vtable->klass points to the transparent proxy class, and not to @class.
1029 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type)
1031 MonoVTable *vt, *pvt;
1032 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
1034 GSList *extra_interfaces = NULL;
1035 MonoClass *class = remote_class->proxy_class;
1036 gpointer *interface_offsets;
1038 vt = mono_class_vtable (domain, class);
1039 max_interface_id = vt->max_interface_id;
1041 /* Calculate vtable space for extra interfaces */
1042 for (j = 0; j < remote_class->interface_count; j++) {
1043 MonoClass* iclass = remote_class->interfaces[j];
1047 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != -1)
1048 continue; /* interface implemented by the class */
1049 if (g_slist_find (extra_interfaces, iclass))
1052 extra_interfaces = g_slist_prepend (extra_interfaces, iclass);
1054 method_count = mono_class_num_methods (iclass);
1056 ifaces = mono_class_get_implemented_interfaces (iclass);
1058 for (i = 0; i < ifaces->len; ++i) {
1059 MonoClass *ic = g_ptr_array_index (ifaces, i);
1060 if (ic->interface_id <= class->max_interface_id && class->interface_offsets[ic->interface_id] != -1)
1061 continue; /* interface implemented by the class */
1062 if (g_slist_find (extra_interfaces, ic))
1064 extra_interfaces = g_slist_prepend (extra_interfaces, ic);
1065 method_count += mono_class_num_methods (ic);
1067 g_ptr_array_free (ifaces, TRUE);
1070 extra_interface_vtsize += method_count * sizeof (gpointer);
1071 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
1074 vtsize = sizeof (gpointer) * (max_interface_id + 1) +
1075 sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
1077 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
1079 interface_offsets = mono_mempool_alloc0 (domain->mp, vtsize + extra_interface_vtsize);
1080 pvt = (MonoVTable*)(interface_offsets + max_interface_id + 1);
1081 memcpy (pvt, vt, sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer));
1083 pvt->klass = mono_defaults.transparent_proxy_class;
1084 /* we need to keep the GC descriptor for a transparent proxy or we confuse the precise GC */
1085 pvt->gc_descr = mono_defaults.transparent_proxy_class->gc_descr;
1087 /* initialize vtable */
1088 mono_class_setup_vtable (class);
1089 for (i = 0; i < class->vtable_size; ++i) {
1092 if ((cm = class->vtable [i]))
1093 pvt->vtable [i] = arch_create_remoting_trampoline (cm, target_type);
1096 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT) {
1097 /* create trampolines for abstract methods */
1098 for (k = class; k; k = k->parent) {
1100 gpointer iter = NULL;
1101 while ((m = mono_class_get_methods (k, &iter)))
1102 if (!pvt->vtable [m->slot])
1103 pvt->vtable [m->slot] = arch_create_remoting_trampoline (m, target_type);
1107 pvt->max_interface_id = max_interface_id;
1109 /* initialize interface offsets */
1110 for (i = 0; i <= class->max_interface_id; ++i) {
1111 int slot = class->interface_offsets [i];
1113 interface_offsets [max_interface_id - i] = &(pvt->vtable [slot]);
1116 if (extra_interfaces) {
1117 int slot = class->vtable_size;
1123 /* Create trampolines for the methods of the interfaces */
1124 for (list_item = extra_interfaces; list_item != NULL; list_item=list_item->next) {
1125 interf = list_item->data;
1126 interface_offsets [max_interface_id - interf->interface_id] = &pvt->vtable [slot];
1130 while ((cm = mono_class_get_methods (interf, &iter)))
1131 pvt->vtable [slot + j++] = arch_create_remoting_trampoline (cm, target_type);
1133 slot += mono_class_num_methods (interf);
1135 g_slist_free (extra_interfaces);
1142 * mono_class_has_special_static_fields:
1144 * Returns whenever @klass has any thread/context static fields.
1147 mono_class_has_special_static_fields (MonoClass *klass)
1149 MonoClassField *field;
1153 while ((field = mono_class_get_fields (klass, &iter))) {
1154 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
1156 if (mono_field_is_deleted (field))
1158 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
1159 if (field_is_special_static (klass, field) != SPECIAL_STATIC_NONE)
1168 * create_remote_class_key:
1169 * Creates an array of pointers that can be used as a hash key for a remote class.
1170 * The first element of the array is the number of pointers.
1173 create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
1178 if (remote_class == NULL) {
1179 if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1180 key = g_malloc (sizeof(gpointer) * 3);
1181 key [0] = GINT_TO_POINTER (2);
1182 key [1] = mono_defaults.marshalbyrefobject_class;
1183 key [2] = extra_class;
1185 key = g_malloc (sizeof(gpointer) * 2);
1186 key [0] = GINT_TO_POINTER (1);
1187 key [1] = extra_class;
1190 if (extra_class != NULL && (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
1191 key = g_malloc (sizeof(gpointer) * (remote_class->interface_count + 3));
1192 key [0] = GINT_TO_POINTER (remote_class->interface_count + 2);
1193 key [1] = remote_class->proxy_class;
1195 // Keep the list of interfaces sorted
1196 for (i = 0, j = 2; i < remote_class->interface_count; i++, j++) {
1197 if (extra_class && remote_class->interfaces [i] > extra_class) {
1198 key [j++] = extra_class;
1201 key [j] = remote_class->interfaces [i];
1204 key [j] = extra_class;
1206 // Replace the old class. The interface list is the same
1207 key = g_malloc (sizeof(gpointer) * (remote_class->interface_count + 2));
1208 key [0] = GINT_TO_POINTER (remote_class->interface_count + 1);
1209 key [1] = extra_class != NULL ? extra_class : remote_class->proxy_class;
1210 for (i = 0; i < remote_class->interface_count; i++)
1211 key [2 + i] = remote_class->interfaces [i];
1219 * copy_remote_class_key:
1221 * Make a copy of KEY in the mempool MP and return the copy.
1224 copy_remote_class_key (MonoMemPool *mp, gpointer *key)
1226 int key_size = (GPOINTER_TO_UINT (key [0]) + 1) * sizeof (gpointer);
1227 gpointer *mp_key = mono_mempool_alloc (mp, key_size);
1229 memcpy (mp_key, key, key_size);
1235 * mono_remote_class:
1236 * @domain: the application domain
1237 * @class_name: name of the remote class
1239 * Creates and initializes a MonoRemoteClass object for a remote type.
1243 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
1245 MonoRemoteClass *rc;
1246 gpointer* key, *mp_key;
1248 key = create_remote_class_key (NULL, proxy_class);
1250 mono_domain_lock (domain);
1251 rc = g_hash_table_lookup (domain->proxy_vtable_hash, key);
1255 mono_domain_unlock (domain);
1259 mp_key = copy_remote_class_key (domain->mp, key);
1263 if (proxy_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1264 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*));
1265 rc->interface_count = 1;
1266 rc->interfaces [0] = proxy_class;
1267 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
1269 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
1270 rc->interface_count = 0;
1271 rc->proxy_class = proxy_class;
1274 rc->default_vtable = NULL;
1275 rc->xdomain_vtable = NULL;
1276 rc->proxy_class_name = mono_string_to_utf8_mp (domain->mp, class_name);
1278 g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
1280 mono_domain_unlock (domain);
1285 * clone_remote_class:
1286 * Creates a copy of the remote_class, adding the provided class or interface
1288 static MonoRemoteClass*
1289 clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass *extra_class)
1291 MonoRemoteClass *rc;
1292 gpointer* key, *mp_key;
1294 key = create_remote_class_key (remote_class, extra_class);
1295 rc = g_hash_table_lookup (domain->proxy_vtable_hash, key);
1301 mp_key = copy_remote_class_key (domain->mp, key);
1305 if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1307 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * (remote_class->interface_count + 1));
1308 rc->proxy_class = remote_class->proxy_class;
1309 rc->interface_count = remote_class->interface_count + 1;
1311 // Keep the list of interfaces sorted, since the hash key of
1312 // the remote class depends on this
1313 for (i = 0, j = 0; i < remote_class->interface_count; i++, j++) {
1314 if (remote_class->interfaces [i] > extra_class && i == j)
1315 rc->interfaces [j++] = extra_class;
1316 rc->interfaces [j] = remote_class->interfaces [i];
1319 rc->interfaces [j] = extra_class;
1321 // Replace the old class. The interface array is the same
1322 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * remote_class->interface_count);
1323 rc->proxy_class = extra_class;
1324 rc->interface_count = remote_class->interface_count;
1325 if (rc->interface_count > 0)
1326 memcpy (rc->interfaces, remote_class->interfaces, rc->interface_count * sizeof (MonoClass*));
1329 rc->default_vtable = NULL;
1330 rc->xdomain_vtable = NULL;
1331 rc->proxy_class_name = remote_class->proxy_class_name;
1333 g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
1339 mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp)
1341 mono_domain_lock (domain);
1342 if (rp->target_domain_id != -1) {
1343 if (remote_class->xdomain_vtable == NULL)
1344 remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN);
1345 mono_domain_unlock (domain);
1346 return remote_class->xdomain_vtable;
1348 if (remote_class->default_vtable == NULL) {
1351 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
1352 klass = mono_class_from_mono_type (type);
1353 if ((klass->is_com_object || klass == mono_defaults.com_object_class) && !mono_class_vtable (mono_domain_get (), klass)->remote)
1354 remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP);
1356 remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
1359 mono_domain_unlock (domain);
1360 return remote_class->default_vtable;
1364 * mono_upgrade_remote_class:
1365 * @domain: the application domain
1366 * @tproxy: the proxy whose remote class has to be upgraded.
1367 * @klass: class to which the remote class can be casted.
1369 * Updates the vtable of the remote class by adding the necessary method slots
1370 * and interface offsets so it can be safely casted to klass. klass can be a
1371 * class or an interface.
1374 mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass)
1376 MonoTransparentProxy *tproxy;
1377 MonoRemoteClass *remote_class;
1378 gboolean redo_vtable;
1380 mono_domain_lock (domain);
1382 tproxy = (MonoTransparentProxy*) proxy_object;
1383 remote_class = tproxy->remote_class;
1385 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1388 for (i = 0; i < remote_class->interface_count && redo_vtable; i++)
1389 if (remote_class->interfaces [i] == klass)
1390 redo_vtable = FALSE;
1393 redo_vtable = (remote_class->proxy_class != klass);
1397 tproxy->remote_class = clone_remote_class (domain, remote_class, klass);
1398 proxy_object->vtable = mono_remote_class_vtable (domain, tproxy->remote_class, tproxy->rp);
1401 mono_domain_unlock (domain);
1406 * mono_object_get_virtual_method:
1407 * @obj: object to operate on.
1410 * Retrieves the MonoMethod that would be called on obj if obj is passed as
1411 * the instance of a callvirt of method.
1414 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method)
1417 MonoMethod **vtable;
1419 MonoMethod *res = NULL;
1421 klass = mono_object_class (obj);
1422 if (klass == mono_defaults.transparent_proxy_class) {
1423 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
1429 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
1432 mono_class_setup_vtable (klass);
1433 vtable = klass->vtable;
1435 /* check method->slot is a valid index: perform isinstance? */
1436 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1438 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
1440 if (method->slot != -1)
1441 res = vtable [method->slot];
1445 if (!res) res = method; /* It may be an interface or abstract class method */
1446 res = mono_marshal_get_remoting_invoke (res);
1455 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1457 g_error ("runtime invoke called on uninitialized runtime");
1461 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
1464 * mono_runtime_invoke:
1465 * @method: method to invoke
1466 * @obJ: object instance
1467 * @params: arguments to the method
1468 * @exc: exception information.
1470 * Invokes the method represented by @method on the object @obj.
1472 * obj is the 'this' pointer, it should be NULL for static
1473 * methods, a MonoObject* for object instances and a pointer to
1474 * the value type for value types.
1476 * The params array contains the arguments to the method with the
1477 * same convention: MonoObject* pointers for object instances and
1478 * pointers to the value type otherwise.
1480 * From unmanaged code you'll usually use the
1481 * mono_runtime_invoke() variant.
1483 * Note that this function doesn't handle virtual methods for
1484 * you, it will exec the exact method you pass: we still need to
1485 * expose a function to lookup the derived class implementation
1486 * of a virtual method (there are examples of this in the code,
1489 * You can pass NULL as the exc argument if you don't want to
1490 * catch exceptions, otherwise, *exc will be set to the exception
1491 * thrown, if any. if an exception is thrown, you can't use the
1492 * MonoObject* result from the function.
1494 * If the method returns a value type, it is boxed in an object
1498 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1500 return default_mono_runtime_invoke (method, obj, params, exc);
1504 set_value (MonoType *type, void *dest, void *value, int deref_pointer)
1508 gpointer *p = (gpointer*)dest;
1515 case MONO_TYPE_BOOLEAN:
1517 case MONO_TYPE_U1: {
1518 guint8 *p = (guint8*)dest;
1519 *p = value ? *(guint8*)value : 0;
1524 case MONO_TYPE_CHAR: {
1525 guint16 *p = (guint16*)dest;
1526 *p = value ? *(guint16*)value : 0;
1529 #if SIZEOF_VOID_P == 4
1534 case MONO_TYPE_U4: {
1535 gint32 *p = (gint32*)dest;
1536 *p = value ? *(gint32*)value : 0;
1539 #if SIZEOF_VOID_P == 8
1544 case MONO_TYPE_U8: {
1545 gint64 *p = (gint64*)dest;
1546 *p = value ? *(gint64*)value : 0;
1549 case MONO_TYPE_R4: {
1550 float *p = (float*)dest;
1551 *p = value ? *(float*)value : 0;
1554 case MONO_TYPE_R8: {
1555 double *p = (double*)dest;
1556 *p = value ? *(double*)value : 0;
1559 case MONO_TYPE_STRING:
1560 case MONO_TYPE_SZARRAY:
1561 case MONO_TYPE_CLASS:
1562 case MONO_TYPE_OBJECT:
1563 case MONO_TYPE_ARRAY:
1564 mono_gc_wbarrier_generic_store (dest, deref_pointer? *(gpointer*)value: value);
1566 case MONO_TYPE_FNPTR:
1567 case MONO_TYPE_PTR: {
1568 gpointer *p = (gpointer*)dest;
1569 *p = deref_pointer? *(gpointer*)value: value;
1572 case MONO_TYPE_VALUETYPE:
1573 if (type->data.klass->enumtype) {
1574 t = type->data.klass->enum_basetype->type;
1578 size = mono_class_value_size (mono_class_from_mono_type (type), NULL);
1580 memset (dest, 0, size);
1582 memcpy (dest, value, size);
1585 case MONO_TYPE_GENERICINST:
1586 t = type->data.generic_class->container_class->byval_arg.type;
1589 g_warning ("got type %x", type->type);
1590 g_assert_not_reached ();
1595 * mono_field_set_value:
1596 * @obj: Instance object
1597 * @field: MonoClassField describing the field to set
1598 * @value: The value to be set
1600 * Sets the value of the field described by @field in the object instance @obj
1601 * to the value passed in @value.
1603 * The value must be on the native format of the field type.
1606 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1610 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1612 dest = (char*)obj + field->offset;
1613 set_value (field->type, dest, value, FALSE);
1617 * mono_field_static_set_value:
1618 * @field: MonoClassField describing the field to set
1619 * @value: The value to be set
1621 * Sets the value of the static field described by @field
1622 * to the value passed in @value.
1624 * The value must be on the native format of the field type.
1627 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1631 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1632 /* you cant set a constant! */
1633 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
1635 dest = (char*)vt->data + field->offset;
1636 set_value (field->type, dest, value, FALSE);
1639 /* Used by the debugger */
1641 mono_vtable_get_static_field_data (MonoVTable *vt)
1647 * mono_field_get_value:
1648 * @obj: Object instance
1649 * @field: MonoClassField describing the field to fetch information from
1650 * @value: pointer to the location where the value will be stored
1652 * Use this routine to get the value of the field @field in the object
1655 * The pointer provided by value must be of the field type, for reference
1656 * types this is a MonoObject*, for value types its the actual pointer to
1661 * mono_field_get_value (obj, int_field, &i);
1664 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1668 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1670 src = (char*)obj + field->offset;
1671 set_value (field->type, value, src, TRUE);
1675 * mono_field_get_value_object:
1676 * @domain: domain where the object will be created (if boxing)
1677 * @field: MonoClassField describing the field to fetch information from
1678 * @obj: The object instance for the field.
1680 * Returns: a new MonoObject with the value from the given field. If the
1681 * field represents a value type, the value is boxed.
1685 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1689 MonoVTable *vtable = NULL;
1691 gboolean is_static = FALSE;
1692 gboolean is_ref = FALSE;
1694 switch (field->type->type) {
1695 case MONO_TYPE_STRING:
1696 case MONO_TYPE_OBJECT:
1697 case MONO_TYPE_CLASS:
1698 case MONO_TYPE_ARRAY:
1699 case MONO_TYPE_SZARRAY:
1704 case MONO_TYPE_BOOLEAN:
1707 case MONO_TYPE_CHAR:
1716 case MONO_TYPE_VALUETYPE:
1717 is_ref = field->type->byref;
1719 case MONO_TYPE_GENERICINST:
1720 is_ref = !field->type->data.generic_class->container_class->valuetype;
1723 g_error ("type 0x%x not handled in "
1724 "mono_field_get_value_object", field->type->type);
1728 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1730 vtable = mono_class_vtable (domain, field->parent);
1731 if (!vtable->initialized)
1732 mono_runtime_class_init (vtable);
1737 mono_field_static_get_value (vtable, field, &o);
1739 mono_field_get_value (obj, field, &o);
1744 /* boxed value type */
1745 klass = mono_class_from_mono_type (field->type);
1746 o = mono_object_new (domain, klass);
1747 v = ((gchar *) o) + sizeof (MonoObject);
1749 mono_field_static_get_value (vtable, field, v);
1751 mono_field_get_value (obj, field, v);
1758 mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const char *blob, void *value)
1761 const char *p = blob;
1762 mono_metadata_decode_blob_size (p, &p);
1765 case MONO_TYPE_BOOLEAN:
1768 *(guint8 *) value = *p;
1770 case MONO_TYPE_CHAR:
1773 *(guint16*) value = read16 (p);
1777 *(guint32*) value = read32 (p);
1781 *(guint64*) value = read64 (p);
1784 readr4 (p, (float*) value);
1787 readr8 (p, (double*) value);
1789 case MONO_TYPE_STRING:
1790 *(gpointer*) value = mono_ldstr_metdata_sig (domain, blob);
1792 case MONO_TYPE_CLASS:
1793 *(gpointer*) value = NULL;
1797 g_warning ("type 0x%02x should not be in constant table", type);
1803 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
1805 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
1806 mono_get_constant_value_from_blob (domain, field->def_type, field->data, value);
1810 * mono_field_static_get_value:
1811 * @vt: vtable to the object
1812 * @field: MonoClassField describing the field to fetch information from
1813 * @value: where the value is returned
1815 * Use this routine to get the value of the static field @field value.
1817 * The pointer provided by value must be of the field type, for reference
1818 * types this is a MonoObject*, for value types its the actual pointer to
1823 * mono_field_static_get_value (vt, int_field, &i);
1826 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1830 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1832 if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
1833 get_default_field_value (vt->domain, field, value);
1837 src = (char*)vt->data + field->offset;
1838 set_value (field->type, value, src, TRUE);
1842 * mono_property_set_value:
1843 * @prop: MonoProperty to set
1844 * @obj: instance object on which to act
1845 * @params: parameters to pass to the propery
1846 * @exc: optional exception
1848 * Invokes the property's set method with the given arguments on the
1849 * object instance obj (or NULL for static properties).
1851 * You can pass NULL as the exc argument if you don't want to
1852 * catch exceptions, otherwise, *exc will be set to the exception
1853 * thrown, if any. if an exception is thrown, you can't use the
1854 * MonoObject* result from the function.
1857 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1859 default_mono_runtime_invoke (prop->set, obj, params, exc);
1863 * mono_property_get_value:
1864 * @prop: MonoProperty to fetch
1865 * @obj: instance object on which to act
1866 * @params: parameters to pass to the propery
1867 * @exc: optional exception
1869 * Invokes the property's get method with the given arguments on the
1870 * object instance obj (or NULL for static properties).
1872 * You can pass NULL as the exc argument if you don't want to
1873 * catch exceptions, otherwise, *exc will be set to the exception
1874 * thrown, if any. if an exception is thrown, you can't use the
1875 * MonoObject* result from the function.
1877 * Returns: the value from invoking the get method on the property.
1880 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1882 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1886 * mono_nullable_init:
1887 * @buf: The nullable structure to initialize.
1888 * @value: the value to initialize from
1889 * @klass: the type for the object
1891 * Initialize the nullable structure pointed to by @buf from @value which
1892 * should be a boxed value type. The size of @buf should be able to hold
1893 * as much data as the @klass->instance_size (which is the number of bytes
1894 * that will be copies).
1896 * Since Nullables have variable structure, we can not define a C
1897 * structure for them.
1900 mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
1902 MonoClass *param_class = klass->cast_class;
1904 g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
1905 g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
1907 *(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject)) = value ? 1 : 0;
1909 memcpy (buf + klass->fields [0].offset - sizeof (MonoObject), mono_object_unbox (value), mono_class_value_size (param_class, NULL));
1911 memset (buf + klass->fields [0].offset - sizeof (MonoObject), 0, mono_class_value_size (param_class, NULL));
1915 * mono_nullable_box:
1916 * @buf: The buffer representing the data to be boxed
1917 * @klass: the type to box it as.
1919 * Creates a boxed vtype or NULL from the Nullable structure pointed to by
1923 mono_nullable_box (guint8 *buf, MonoClass *klass)
1925 MonoClass *param_class = klass->cast_class;
1927 g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
1928 g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
1930 if (*(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject))) {
1931 MonoObject *o = mono_object_new (mono_domain_get (), param_class);
1932 memcpy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL));
1940 * mono_get_delegate_invoke:
1941 * @klass: The delegate class
1943 * Returns: the MonoMethod for the "Invoke" method in the delegate klass
1946 mono_get_delegate_invoke (MonoClass *klass)
1950 im = mono_class_get_method_from_name (klass, "Invoke", -1);
1957 * mono_runtime_delegate_invoke:
1958 * @delegate: pointer to a delegate object.
1959 * @params: parameters for the delegate.
1960 * @exc: Pointer to the exception result.
1962 * Invokes the delegate method @delegate with the parameters provided.
1964 * You can pass NULL as the exc argument if you don't want to
1965 * catch exceptions, otherwise, *exc will be set to the exception
1966 * thrown, if any. if an exception is thrown, you can't use the
1967 * MonoObject* result from the function.
1970 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1974 im = mono_get_delegate_invoke (delegate->vtable->klass);
1977 return mono_runtime_invoke (im, delegate, params, exc);
1980 static char **main_args = NULL;
1981 static int num_main_args;
1984 * mono_runtime_get_main_args:
1986 * Returns: a MonoArray with the arguments passed to the main program
1989 mono_runtime_get_main_args (void)
1993 MonoDomain *domain = mono_domain_get ();
1998 res = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, num_main_args);
2000 for (i = 0; i < num_main_args; ++i)
2001 mono_array_setref (res, i, mono_string_new (domain, main_args [i]));
2007 fire_process_exit_event (void)
2009 MonoClassField *field;
2010 MonoDomain *domain = mono_domain_get ();
2012 MonoObject *delegate, *exc;
2014 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
2017 if (domain != mono_get_root_domain ())
2020 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
2021 if (delegate == NULL)
2026 mono_runtime_delegate_invoke (delegate, pa, &exc);
2030 * mono_runtime_run_main:
2031 * @method: the method to start the application with (usually Main)
2032 * @argc: number of arguments from the command line
2033 * @argv: array of strings from the command line
2034 * @exc: excetption results
2036 * Execute a standard Main() method (argc/argv contains the
2037 * executable name). This method also sets the command line argument value
2038 * needed by System.Environment.
2043 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
2047 MonoArray *args = NULL;
2048 MonoDomain *domain = mono_domain_get ();
2049 gchar *utf8_fullpath;
2052 g_assert (method != NULL);
2054 mono_thread_set_main (mono_thread_current ());
2056 main_args = g_new0 (char*, argc);
2057 num_main_args = argc;
2059 if (!g_path_is_absolute (argv [0])) {
2060 gchar *basename = g_path_get_basename (argv [0]);
2061 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
2065 utf8_fullpath = mono_utf8_from_external (fullpath);
2066 if(utf8_fullpath == NULL) {
2067 /* Printing the arg text will cause glib to
2068 * whinge about "Invalid UTF-8", but at least
2069 * its relevant, and shows the problem text
2072 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
2073 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
2080 utf8_fullpath = mono_utf8_from_external (argv[0]);
2081 if(utf8_fullpath == NULL) {
2082 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
2083 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
2088 main_args [0] = utf8_fullpath;
2090 for (i = 1; i < argc; ++i) {
2093 utf8_arg=mono_utf8_from_external (argv[i]);
2094 if(utf8_arg==NULL) {
2095 /* Ditto the comment about Invalid UTF-8 here */
2096 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
2097 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
2101 main_args [i] = utf8_arg;
2105 if (mono_method_signature (method)->param_count) {
2106 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
2107 for (i = 0; i < argc; ++i) {
2108 /* The encodings should all work, given that
2109 * we've checked all these args for the
2112 gchar *str = mono_utf8_from_external (argv [i]);
2113 MonoString *arg = mono_string_new (domain, str);
2114 mono_array_setref (args, i, arg);
2118 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
2121 mono_assembly_set_main (method->klass->image->assembly);
2123 result = mono_runtime_exec_main (method, args, exc);
2124 fire_process_exit_event ();
2128 /* Used in mono_unhandled_exception */
2130 create_unhandled_exception_eventargs (MonoObject *exc)
2134 MonoMethod *method = NULL;
2135 MonoBoolean is_terminating = TRUE;
2138 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
2141 mono_class_init (klass);
2143 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
2144 method = mono_class_get_method_from_name_flags (klass, ".ctor", 2, METHOD_ATTRIBUTE_PUBLIC);
2148 args [1] = &is_terminating;
2150 obj = mono_object_new (mono_domain_get (), klass);
2151 mono_runtime_invoke (method, obj, args, NULL);
2157 * mono_unhandled_exception:
2158 * @exc: exception thrown
2160 * This is a VM internal routine.
2162 * We call this function when we detect an unhandled exception
2163 * in the default domain.
2165 * It invokes the * UnhandledException event in AppDomain or prints
2166 * a warning to the console
2169 mono_unhandled_exception (MonoObject *exc)
2171 MonoDomain *domain = mono_domain_get ();
2172 MonoClassField *field;
2173 MonoObject *delegate;
2175 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
2176 "UnhandledException");
2179 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
2180 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
2182 /* set exitcode only in the main thread */
2183 if (mono_thread_current () == main_thread)
2184 mono_environment_exitcode_set (1);
2185 if (domain != mono_get_root_domain () || !delegate) {
2186 mono_print_unhandled_exception (exc);
2188 MonoObject *e = NULL;
2191 pa [0] = domain->domain;
2192 pa [1] = create_unhandled_exception_eventargs (exc);
2193 mono_runtime_delegate_invoke (delegate, pa, &e);
2196 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
2197 g_warning ("exception inside UnhandledException handler: %s\n", msg);
2205 * Launch a new thread to execute a function
2207 * main_func is called back from the thread with main_args as the
2208 * parameter. The callback function is expected to start Main()
2209 * eventually. This function then waits for all managed threads to
2211 * It is not necesseray anymore to execute managed code in a subthread,
2212 * so this function should not be used anymore by default: just
2213 * execute the code and then call mono_thread_manage ().
2216 mono_runtime_exec_managed_code (MonoDomain *domain,
2217 MonoMainThreadFunc main_func,
2220 mono_thread_create (domain, main_func, main_args);
2222 mono_thread_manage ();
2226 * Execute a standard Main() method (args doesn't contain the
2230 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
2240 domain = mono_object_domain (args);
2241 if (!domain->entry_assembly) {
2243 MonoAssembly *assembly;
2245 assembly = method->klass->image->assembly;
2246 domain->entry_assembly = assembly;
2247 MONO_OBJECT_SETREF (domain->setup, application_base, mono_string_new (domain, assembly->basedir));
2249 str = g_strconcat (assembly->image->name, ".config", NULL);
2250 MONO_OBJECT_SETREF (domain->setup, configuration_file, mono_string_new (domain, str));
2254 /* FIXME: check signature of method */
2255 if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
2257 res = mono_runtime_invoke (method, NULL, pa, exc);
2259 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
2263 mono_environment_exitcode_set (rval);
2265 mono_runtime_invoke (method, NULL, pa, exc);
2269 /* If the return type of Main is void, only
2270 * set the exitcode if an exception was thrown
2271 * (we don't want to blow away an
2272 * explicitly-set exit code)
2275 mono_environment_exitcode_set (rval);
2283 * mono_install_runtime_invoke:
2284 * @func: Function to install
2286 * This is a VM internal routine
2289 mono_install_runtime_invoke (MonoInvokeFunc func)
2291 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
2295 * mono_runtime_invoke_array:
2296 * @method: method to invoke
2297 * @obJ: object instance
2298 * @params: arguments to the method
2299 * @exc: exception information.
2301 * Invokes the method represented by @method on the object @obj.
2303 * obj is the 'this' pointer, it should be NULL for static
2304 * methods, a MonoObject* for object instances and a pointer to
2305 * the value type for value types.
2307 * The params array contains the arguments to the method with the
2308 * same convention: MonoObject* pointers for object instances and
2309 * pointers to the value type otherwise. The _invoke_array
2310 * variant takes a C# object[] as the params argument (MonoArray
2311 * *params): in this case the value types are boxed inside the
2312 * respective reference representation.
2314 * From unmanaged code you'll usually use the
2315 * mono_runtime_invoke() variant.
2317 * Note that this function doesn't handle virtual methods for
2318 * you, it will exec the exact method you pass: we still need to
2319 * expose a function to lookup the derived class implementation
2320 * of a virtual method (there are examples of this in the code,
2323 * You can pass NULL as the exc argument if you don't want to
2324 * catch exceptions, otherwise, *exc will be set to the exception
2325 * thrown, if any. if an exception is thrown, you can't use the
2326 * MonoObject* result from the function.
2328 * If the method returns a value type, it is boxed in an object
2332 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
2335 MonoMethodSignature *sig = mono_method_signature (method);
2336 gpointer *pa = NULL;
2339 if (NULL != params) {
2340 pa = alloca (sizeof (gpointer) * mono_array_length (params));
2341 for (i = 0; i < mono_array_length (params); i++) {
2342 MonoType *t = sig->params [i];
2348 case MONO_TYPE_BOOLEAN:
2351 case MONO_TYPE_CHAR:
2360 case MONO_TYPE_VALUETYPE:
2361 if (t->type == MONO_TYPE_VALUETYPE && mono_class_is_nullable (mono_class_from_mono_type (sig->params [i]))) {
2364 g_assert_not_reached ();
2365 /* The runtime invoke wrapper needs the original boxed vtype */
2366 pa [i] = (char *)(((gpointer *)params->vector)[i]);
2368 /* MS seems to create the objects if a null is passed in */
2369 if (!((gpointer *)params->vector)[i])
2370 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
2374 * We can't pass the unboxed vtype byref to the callee, since
2375 * that would mean the callee would be able to modify boxed
2376 * primitive types. So we (and MS) make a copy of the boxed
2377 * object, pass that to the callee, and replace the original
2378 * boxed object in the arg array with the copy.
2380 MonoObject *orig = mono_array_get (params, MonoObject*, i);
2381 MonoObject *copy = mono_value_box (mono_domain_get (), orig->vtable->klass, mono_object_unbox (orig));
2382 mono_array_setref (params, i, copy);
2385 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
2388 case MONO_TYPE_STRING:
2389 case MONO_TYPE_OBJECT:
2390 case MONO_TYPE_CLASS:
2391 case MONO_TYPE_ARRAY:
2392 case MONO_TYPE_SZARRAY:
2394 pa [i] = &(((gpointer *)params->vector)[i]);
2396 pa [i] = (char *)(((gpointer *)params->vector)[i]);
2398 case MONO_TYPE_GENERICINST:
2399 t = &t->data.generic_class->container_class->byval_arg;
2402 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
2407 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
2410 if (mono_class_is_nullable (method->klass)) {
2411 /* Need to create a boxed vtype instead */
2417 return mono_value_box (mono_domain_get (), method->klass->cast_class, pa [0]);
2421 obj = mono_object_new (mono_domain_get (), method->klass);
2422 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
2423 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
2425 if (method->klass->valuetype)
2426 o = mono_object_unbox (obj);
2430 else if (method->klass->valuetype)
2431 obj = mono_value_box (mono_domain_get (), method->klass, obj);
2433 mono_runtime_invoke (method, o, pa, exc);
2436 /* obj must be already unboxed if needed */
2437 return mono_runtime_invoke (method, obj, pa, exc);
2442 arith_overflow (void)
2444 mono_raise_exception (mono_get_exception_overflow ());
2448 * mono_object_allocate:
2449 * @size: number of bytes to allocate
2451 * This is a very simplistic routine until we have our GC-aware
2454 * Returns: an allocated object of size @size, or NULL on failure.
2456 static inline void *
2457 mono_object_allocate (size_t size, MonoVTable *vtable)
2460 mono_stats.new_object_count++;
2461 ALLOC_OBJECT (o, vtable, size);
2467 * mono_object_allocate_ptrfree:
2468 * @size: number of bytes to allocate
2470 * Note that the memory allocated is not zeroed.
2471 * Returns: an allocated object of size @size, or NULL on failure.
2473 static inline void *
2474 mono_object_allocate_ptrfree (size_t size, MonoVTable *vtable)
2477 mono_stats.new_object_count++;
2478 ALLOC_PTRFREE (o, vtable, size);
2482 static inline void *
2483 mono_object_allocate_spec (size_t size, MonoVTable *vtable)
2486 ALLOC_TYPED (o, size, vtable);
2487 mono_stats.new_object_count++;
2494 * @klass: the class of the object that we want to create
2496 * Returns: a newly created object whose definition is
2497 * looked up using @klass. This will not invoke any constructors,
2498 * so the consumer of this routine has to invoke any constructors on
2499 * its own to initialize the object.
2502 mono_object_new (MonoDomain *domain, MonoClass *klass)
2504 MONO_ARCH_SAVE_REGS;
2505 return mono_object_new_specific (mono_class_vtable (domain, klass));
2509 * mono_object_new_specific:
2510 * @vtable: the vtable of the object that we want to create
2512 * Returns: A newly created object with class and domain specified
2516 mono_object_new_specific (MonoVTable *vtable)
2520 MONO_ARCH_SAVE_REGS;
2522 /* check for is_com_object for COM Interop */
2523 if (vtable->remote || vtable->klass->is_com_object)
2526 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
2529 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
2532 mono_class_init (klass);
2534 im = mono_class_get_method_from_name (klass, "CreateProxyForType", 1);
2536 vtable->domain->create_proxy_for_type_method = im;
2539 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
2541 o = mono_runtime_invoke (im, NULL, pa, NULL);
2542 if (o != NULL) return o;
2545 return mono_object_new_alloc_specific (vtable);
2549 mono_object_new_alloc_specific (MonoVTable *vtable)
2553 if (!vtable->klass->has_references) {
2554 o = mono_object_new_ptrfree (vtable);
2555 } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2556 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
2558 /* printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2559 o = mono_object_allocate (vtable->klass->instance_size, vtable);
2561 if (vtable->klass->has_finalize)
2562 mono_object_register_finalizer (o);
2564 mono_profiler_allocation (o, vtable->klass);
2569 mono_object_new_fast (MonoVTable *vtable)
2572 ALLOC_TYPED (o, vtable->klass->instance_size, vtable);
2577 mono_object_new_ptrfree (MonoVTable *vtable)
2580 ALLOC_PTRFREE (obj, vtable, vtable->klass->instance_size);
2581 #if NEED_TO_ZERO_PTRFREE
2582 /* an inline memset is much faster for the common vcase of small objects
2583 * note we assume the allocated size is a multiple of sizeof (void*).
2585 if (vtable->klass->instance_size < 128) {
2587 end = (gpointer*)((char*)obj + vtable->klass->instance_size);
2588 p = (gpointer*)((char*)obj + sizeof (MonoObject));
2594 memset ((char*)obj + sizeof (MonoObject), 0, vtable->klass->instance_size - sizeof (MonoObject));
2601 mono_object_new_ptrfree_box (MonoVTable *vtable)
2604 ALLOC_PTRFREE (obj, vtable, vtable->klass->instance_size);
2605 /* the object will be boxed right away, no need to memzero it */
2610 * mono_class_get_allocation_ftn:
2612 * @for_box: the object will be used for boxing
2613 * @pass_size_in_words:
2615 * Return the allocation function appropriate for the given class.
2619 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *pass_size_in_words)
2621 *pass_size_in_words = FALSE;
2623 if (vtable->klass->has_finalize || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
2624 return mono_object_new_specific;
2626 if (!vtable->klass->has_references) {
2627 //g_print ("ptrfree for %s.%s\n", vtable->klass->name_space, vtable->klass->name);
2629 return mono_object_new_ptrfree_box;
2630 return mono_object_new_ptrfree;
2633 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2635 return mono_object_new_fast;
2638 * FIXME: This is actually slower than mono_object_new_fast, because
2639 * of the overhead of parameter passing.
2642 *pass_size_in_words = TRUE;
2643 #ifdef GC_REDIRECT_TO_LOCAL
2644 return GC_local_gcj_fast_malloc;
2646 return GC_gcj_fast_malloc;
2651 return mono_object_new_specific;
2655 * mono_object_new_from_token:
2656 * @image: Context where the type_token is hosted
2657 * @token: a token of the type that we want to create
2659 * Returns: A newly created object whose definition is
2660 * looked up using @token in the @image image
2663 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
2667 class = mono_class_get (image, token);
2669 return mono_object_new (domain, class);
2674 * mono_object_clone:
2675 * @obj: the object to clone
2677 * Returns: A newly created object who is a shallow copy of @obj
2680 mono_object_clone (MonoObject *obj)
2685 size = obj->vtable->klass->instance_size;
2686 o = mono_object_allocate (size, obj->vtable);
2687 /* do not copy the sync state */
2688 memcpy ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
2690 mono_profiler_allocation (o, obj->vtable->klass);
2692 if (obj->vtable->klass->has_finalize)
2693 mono_object_register_finalizer (o);
2698 * mono_array_full_copy:
2699 * @src: source array to copy
2700 * @dest: destination array
2702 * Copies the content of one array to another with exactly the same type and size.
2705 mono_array_full_copy (MonoArray *src, MonoArray *dest)
2708 MonoClass *klass = src->obj.vtable->klass;
2710 MONO_ARCH_SAVE_REGS;
2712 g_assert (klass == dest->obj.vtable->klass);
2714 size = mono_array_length (src);
2715 g_assert (size == mono_array_length (dest));
2716 size *= mono_array_element_size (klass);
2717 memcpy (&dest->vector, &src->vector, size);
2721 * mono_array_clone_in_domain:
2722 * @domain: the domain in which the array will be cloned into
2723 * @array: the array to clone
2725 * This routine returns a copy of the array that is hosted on the
2726 * specified MonoDomain.
2729 mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
2734 MonoClass *klass = array->obj.vtable->klass;
2736 MONO_ARCH_SAVE_REGS;
2738 if (array->bounds == NULL) {
2739 size = mono_array_length (array);
2740 o = mono_array_new_full (domain, klass, &size, NULL);
2742 size *= mono_array_element_size (klass);
2743 memcpy (&o->vector, &array->vector, size);
2747 sizes = alloca (klass->rank * sizeof(guint32) * 2);
2748 size = mono_array_element_size (klass);
2749 for (i = 0; i < klass->rank; ++i) {
2750 sizes [i] = array->bounds [i].length;
2751 size *= array->bounds [i].length;
2752 sizes [i + klass->rank] = array->bounds [i].lower_bound;
2754 o = mono_array_new_full (domain, klass, sizes, sizes + klass->rank);
2755 memcpy (&o->vector, &array->vector, size);
2762 * @array: the array to clone
2764 * Returns: A newly created array who is a shallow copy of @array
2767 mono_array_clone (MonoArray *array)
2769 return mono_array_clone_in_domain (((MonoObject *)array)->vtable->domain, array);
2772 /* helper macros to check for overflow when calculating the size of arrays */
2773 #define MYGUINT32_MAX 4294967295U
2774 #define CHECK_ADD_OVERFLOW_UN(a,b) \
2775 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
2776 #define CHECK_MUL_OVERFLOW_UN(a,b) \
2777 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
2778 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
2781 * mono_array_new_full:
2782 * @domain: domain where the object is created
2783 * @array_class: array class
2784 * @lengths: lengths for each dimension in the array
2785 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
2787 * This routine creates a new array objects with the given dimensions,
2788 * lower bounds and type.
2791 mono_array_new_full (MonoDomain *domain, MonoClass *array_class, guint32 *lengths, guint32 *lower_bounds)
2793 guint32 byte_len, len, bounds_size;
2799 if (!array_class->inited)
2800 mono_class_init (array_class);
2802 byte_len = mono_array_element_size (array_class);
2805 /* A single dimensional array with a 0 lower bound is the same as an szarray */
2806 if (array_class->rank == 1 && ((array_class->byval_arg.type == MONO_TYPE_SZARRAY) || (lower_bounds && lower_bounds [0] == 0))) {
2812 bounds_size = sizeof (MonoArrayBounds) * array_class->rank;
2814 for (i = 0; i < array_class->rank; ++i) {
2815 if ((int) lengths [i] < 0)
2817 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
2818 mono_gc_out_of_memory (MYGUINT32_MAX);
2823 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
2824 mono_gc_out_of_memory (MYGUINT32_MAX);
2826 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2827 mono_gc_out_of_memory (MYGUINT32_MAX);
2828 byte_len += sizeof (MonoArray);
2831 if (CHECK_ADD_OVERFLOW_UN (byte_len, 3))
2832 mono_gc_out_of_memory (MYGUINT32_MAX);
2833 byte_len = (byte_len + 3) & ~3;
2834 if (CHECK_ADD_OVERFLOW_UN (byte_len, bounds_size))
2835 mono_gc_out_of_memory (MYGUINT32_MAX);
2836 byte_len += bounds_size;
2839 * Following three lines almost taken from mono_object_new ():
2840 * they need to be kept in sync.
2842 vtable = mono_class_vtable (domain, array_class);
2843 if (!array_class->has_references) {
2844 o = mono_object_allocate_ptrfree (byte_len, vtable);
2845 #if NEED_TO_ZERO_PTRFREE
2846 memset ((char*)o + sizeof (MonoObject), 0, byte_len - sizeof (MonoObject));
2848 } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2849 o = mono_object_allocate_spec (byte_len, vtable);
2851 o = mono_object_allocate (byte_len, vtable);
2854 array = (MonoArray*)o;
2855 array->max_length = len;
2858 MonoArrayBounds *bounds = (MonoArrayBounds*)((char*)array + byte_len - bounds_size);
2859 array->bounds = bounds;
2860 for (i = 0; i < array_class->rank; ++i) {
2861 bounds [i].length = lengths [i];
2863 bounds [i].lower_bound = lower_bounds [i];
2867 mono_profiler_allocation (o, array_class);
2874 * @domain: domain where the object is created
2875 * @eclass: element class
2876 * @n: number of array elements
2878 * This routine creates a new szarray with @n elements of type @eclass.
2881 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
2885 MONO_ARCH_SAVE_REGS;
2887 ac = mono_array_class_get (eclass, 1);
2888 g_assert (ac != NULL);
2890 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
2894 * mono_array_new_specific:
2895 * @vtable: a vtable in the appropriate domain for an initialized class
2896 * @n: number of array elements
2898 * This routine is a fast alternative to mono_array_new() for code which
2899 * can be sure about the domain it operates in.
2902 mono_array_new_specific (MonoVTable *vtable, guint32 n)
2906 guint32 byte_len, elem_size;
2908 MONO_ARCH_SAVE_REGS;
2913 elem_size = mono_array_element_size (vtable->klass);
2914 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
2915 mono_gc_out_of_memory (MYGUINT32_MAX);
2916 byte_len = n * elem_size;
2917 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2918 mono_gc_out_of_memory (MYGUINT32_MAX);
2919 byte_len += sizeof (MonoArray);
2920 if (!vtable->klass->has_references) {
2921 o = mono_object_allocate_ptrfree (byte_len, vtable);
2922 #if NEED_TO_ZERO_PTRFREE
2923 memset ((char*)o + sizeof (MonoObject), 0, byte_len - sizeof (MonoObject));
2925 } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2926 o = mono_object_allocate_spec (byte_len, vtable);
2928 /* printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2929 o = mono_object_allocate (byte_len, vtable);
2932 ao = (MonoArray *)o;
2935 mono_profiler_allocation (o, vtable->klass);
2941 * mono_string_new_utf16:
2942 * @text: a pointer to an utf16 string
2943 * @len: the length of the string
2945 * Returns: A newly created string object which contains @text.
2948 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
2952 s = mono_string_new_size (domain, len);
2953 g_assert (s != NULL);
2955 memcpy (mono_string_chars (s), text, len * 2);
2961 * mono_string_new_size:
2962 * @text: a pointer to an utf16 string
2963 * @len: the length of the string
2965 * Returns: A newly created string object of @len
2968 mono_string_new_size (MonoDomain *domain, gint32 len)
2972 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2974 /* overflow ? can't fit it, can't allocate it! */
2976 mono_gc_out_of_memory (-1);
2978 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2980 s = mono_object_allocate_ptrfree (size, vtable);
2983 #if NEED_TO_ZERO_PTRFREE
2986 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2992 * mono_string_new_len:
2993 * @text: a pointer to an utf8 string
2994 * @length: number of bytes in @text to consider
2996 * Returns: A newly created string object which contains @text.
2999 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
3001 GError *error = NULL;
3002 MonoString *o = NULL;
3004 glong items_written;
3006 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
3009 o = mono_string_new_utf16 (domain, ut, items_written);
3011 g_error_free (error);
3020 * @text: a pointer to an utf8 string
3022 * Returns: A newly created string object which contains @text.
3025 mono_string_new (MonoDomain *domain, const char *text)
3027 GError *error = NULL;
3028 MonoString *o = NULL;
3030 glong items_written;
3035 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
3038 o = mono_string_new_utf16 (domain, ut, items_written);
3040 g_error_free (error);
3048 * mono_string_new_wrapper:
3049 * @text: pointer to utf8 characters.
3051 * Helper function to create a string object from @text in the current domain.
3054 mono_string_new_wrapper (const char *text)
3056 MonoDomain *domain = mono_domain_get ();
3058 MONO_ARCH_SAVE_REGS;
3061 return mono_string_new (domain, text);
3068 * @class: the class of the value
3069 * @value: a pointer to the unboxed data
3071 * Returns: A newly created object which contains @value.
3074 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
3080 g_assert (class->valuetype);
3082 vtable = mono_class_vtable (domain, class);
3083 size = mono_class_instance_size (class);
3084 res = mono_object_allocate (size, vtable);
3085 mono_profiler_allocation (res, class);
3087 size = size - sizeof (MonoObject);
3089 #if NO_UNALIGNED_ACCESS
3090 memcpy ((char *)res + sizeof (MonoObject), value, size);
3094 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
3097 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
3100 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
3103 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
3106 memcpy ((char *)res + sizeof (MonoObject), value, size);
3109 if (class->has_finalize)
3110 mono_object_register_finalizer (res);
3116 * @dest: destination pointer
3117 * @src: source pointer
3118 * @klass: a valuetype class
3120 * Copy a valuetype from @src to @dest. This function must be used
3121 * when @klass contains references fields.
3124 mono_value_copy (gpointer dest, gpointer src, MonoClass *klass)
3126 int size = mono_class_value_size (klass, NULL);
3127 mono_gc_wbarrier_value_copy (dest, src, 1, klass);
3128 memcpy (dest, src, size);
3132 * mono_value_copy_array:
3133 * @dest: destination array
3134 * @dest_idx: index in the @dest array
3135 * @src: source pointer
3136 * @count: number of items
3138 * Copy @count valuetype items from @src to @dest. This function must be used
3139 * when @klass contains references fields.
3140 * Overlap is handled.
3143 mono_value_copy_array (MonoArray *dest, int dest_idx, gpointer src, int count)
3145 int size = mono_array_element_size (dest->obj.vtable->klass);
3146 char *d = mono_array_addr_with_size (dest, size, dest_idx);
3147 mono_gc_wbarrier_value_copy (d, src, count, mono_object_class (dest)->element_class);
3148 memmove (d, src, size * count);
3152 * mono_object_get_domain:
3153 * @obj: object to query
3155 * Returns: the MonoDomain where the object is hosted
3158 mono_object_get_domain (MonoObject *obj)
3160 return mono_object_domain (obj);
3164 * mono_object_get_class:
3165 * @obj: object to query
3167 * Returns: the MonOClass of the object.
3170 mono_object_get_class (MonoObject *obj)
3172 return mono_object_class (obj);
3175 * mono_object_get_size:
3176 * @o: object to query
3178 * Returns: the size, in bytes, of @o
3181 mono_object_get_size (MonoObject* o)
3183 MonoClass* klass = mono_object_class (o);
3184 if (klass == mono_defaults.string_class) {
3185 return sizeof (MonoString) + 2 * mono_string_length ((MonoString*) o) + 2;
3186 } else if (o->vtable->rank) {
3187 MonoArray *array = (MonoArray*)o;
3188 size_t size = sizeof (MonoArray) + mono_array_element_size (klass) * mono_array_length (array);
3189 if (array->bounds) {
3192 size += sizeof (MonoArrayBounds) * o->vtable->rank;
3196 return mono_class_instance_size (klass);
3201 * mono_object_unbox:
3202 * @obj: object to unbox
3204 * Returns: a pointer to the start of the valuetype boxed in this
3207 * This method will assert if the object passed is not a valuetype.
3210 mono_object_unbox (MonoObject *obj)
3212 /* add assert for valuetypes? */
3213 g_assert (obj->vtable->klass->valuetype);
3214 return ((char*)obj) + sizeof (MonoObject);
3218 * mono_object_isinst:
3220 * @klass: a pointer to a class
3222 * Returns: @obj if @obj is derived from @klass
3225 mono_object_isinst (MonoObject *obj, MonoClass *klass)
3228 mono_class_init (klass);
3230 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
3231 return mono_object_isinst_mbyref (obj, klass);
3236 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
3240 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
3249 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
3250 if (klass->interface_id <= vt->max_interface_id) {
3251 /* the interface_offsets array is stored before the vtable */
3252 gpointer *interface_offsets = (gpointer*)vt;
3253 if (interface_offsets [- (klass->interface_id + 1)] != NULL)
3257 MonoClass *oklass = vt->klass;
3258 if ((oklass == mono_defaults.transparent_proxy_class))
3259 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
3261 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
3265 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
3267 MonoDomain *domain = mono_domain_get ();
3269 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
3270 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
3271 MonoMethod *im = NULL;
3274 im = mono_class_get_method_from_name (rpklass, "CanCastTo", -1);
3275 im = mono_object_get_virtual_method (rp, im);
3278 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
3281 res = mono_runtime_invoke (im, rp, pa, NULL);
3283 if (*(MonoBoolean *) mono_object_unbox(res)) {
3284 /* Update the vtable of the remote type, so it can safely cast to this new type */
3285 mono_upgrade_remote_class (domain, obj, klass);
3294 * mono_object_castclass_mbyref:
3296 * @klass: a pointer to a class
3298 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
3301 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
3303 if (!obj) return NULL;
3304 if (mono_object_isinst_mbyref (obj, klass)) return obj;
3306 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
3308 "InvalidCastException"));
3313 MonoDomain *orig_domain;
3319 str_lookup (MonoDomain *domain, gpointer user_data)
3321 LDStrInfo *info = user_data;
3322 if (info->res || domain == info->orig_domain)
3324 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
3330 mono_string_get_pinned (MonoString *str)
3334 size = sizeof (MonoString) + 2 * (mono_string_length (str) + 1);
3335 news = mono_gc_alloc_pinned_obj (((MonoObject*)str)->vtable, size);
3336 memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
3337 news->length = mono_string_length (str);
3342 #define mono_string_get_pinned(str) (str)
3346 mono_string_is_interned_lookup (MonoString *str, int insert)
3348 MonoGHashTable *ldstr_table;
3352 domain = ((MonoObject *)str)->vtable->domain;
3353 ldstr_table = domain->ldstr_table;
3355 if ((res = mono_g_hash_table_lookup (ldstr_table, str))) {
3360 str = mono_string_get_pinned (str);
3361 mono_g_hash_table_insert (ldstr_table, str, str);
3365 LDStrInfo ldstr_info;
3366 ldstr_info.orig_domain = domain;
3367 ldstr_info.ins = str;
3368 ldstr_info.res = NULL;
3370 mono_domain_foreach (str_lookup, &ldstr_info);
3371 if (ldstr_info.res) {
3373 * the string was already interned in some other domain:
3374 * intern it in the current one as well.
3376 mono_g_hash_table_insert (ldstr_table, str, str);
3386 * mono_string_is_interned:
3387 * @o: String to probe
3389 * Returns whether the string has been interned.
3392 mono_string_is_interned (MonoString *o)
3394 return mono_string_is_interned_lookup (o, FALSE);
3398 * mono_string_intern:
3399 * @o: String to intern
3401 * Interns the string passed.
3402 * Returns: The interned string.
3405 mono_string_intern (MonoString *str)
3407 return mono_string_is_interned_lookup (str, TRUE);
3412 * @domain: the domain where the string will be used.
3413 * @image: a metadata context
3414 * @idx: index into the user string table.
3416 * Implementation for the ldstr opcode.
3417 * Returns: a loaded string from the @image/@idx combination.
3420 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
3422 MONO_ARCH_SAVE_REGS;
3425 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
3427 return mono_ldstr_metdata_sig (domain, mono_metadata_user_string (image, idx));
3431 * mono_ldstr_metdata_sig
3432 * @domain: the domain for the string
3433 * @sig: the signature of a metadata string
3435 * Returns: a MonoString for a string stored in the metadata
3438 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
3440 const char *str = sig;
3441 MonoString *o, *interned;
3444 len2 = mono_metadata_decode_blob_size (str, &str);
3447 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
3448 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3451 guint16 *p2 = (guint16*)mono_string_chars (o);
3452 for (i = 0; i < len2; ++i) {
3453 *p2 = GUINT16_FROM_LE (*p2);
3459 if ((interned = mono_g_hash_table_lookup (domain->ldstr_table, o))) {
3461 /* o will get garbage collected */
3465 o = mono_string_get_pinned (o);
3466 mono_g_hash_table_insert (domain->ldstr_table, o, o);
3473 * mono_string_to_utf8:
3474 * @s: a System.String
3476 * Return the UTF8 representation for @s.
3477 * the resulting buffer nedds to be freed with g_free().
3480 mono_string_to_utf8 (MonoString *s)
3483 GError *error = NULL;
3489 return g_strdup ("");
3491 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
3493 MonoException *exc = mono_get_exception_argument ("string", error->message);
3494 g_error_free (error);
3495 mono_raise_exception(exc);
3502 * mono_string_to_utf16:
3505 * Return an null-terminated array of the utf-16 chars
3506 * contained in @s. The result must be freed with g_free().
3507 * This is a temporary helper until our string implementation
3508 * is reworked to always include the null terminating char.
3511 mono_string_to_utf16 (MonoString *s)
3518 as = g_malloc ((s->length * 2) + 2);
3519 as [(s->length * 2)] = '\0';
3520 as [(s->length * 2) + 1] = '\0';
3523 return (gunichar2 *)(as);
3526 memcpy (as, mono_string_chars(s), s->length * 2);
3527 return (gunichar2 *)(as);
3531 * mono_string_from_utf16:
3532 * @data: the UTF16 string (LPWSTR) to convert
3534 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString.
3536 * Returns: a MonoString.
3539 mono_string_from_utf16 (gunichar2 *data)
3541 MonoDomain *domain = mono_domain_get ();
3547 while (data [len]) len++;
3549 return mono_string_new_utf16 (domain, data, len);
3553 * mono_string_to_utf8_mp:
3554 * @s: a System.String
3556 * Same as mono_string_to_utf8, but allocate the string from a mempool.
3559 mono_string_to_utf8_mp (MonoMemPool *mp, MonoString *s)
3561 char *r = mono_string_to_utf8 (s);
3568 len = strlen (r) + 1;
3569 mp_s = mono_mempool_alloc (mp, len);
3570 memcpy (mp_s, r, len);
3578 default_ex_handler (MonoException *ex)
3580 MonoObject *o = (MonoObject*)ex;
3581 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
3585 static MonoExceptionFunc ex_handler = default_ex_handler;
3588 * mono_install_handler:
3589 * @func: exception handler
3591 * This is an internal JIT routine used to install the handler for exceptions
3595 mono_install_handler (MonoExceptionFunc func)
3597 ex_handler = func? func: default_ex_handler;
3601 * mono_raise_exception:
3602 * @ex: exception object
3604 * Signal the runtime that the exception @ex has been raised in unmanaged code.
3607 mono_raise_exception (MonoException *ex)
3610 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
3611 * that will cause gcc to omit the function epilog, causing problems when
3612 * the JIT tries to walk the stack, since the return address on the stack
3613 * will point into the next function in the executable, not this one.
3616 if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class)
3617 MONO_OBJECT_SETREF (mono_thread_current (), abort_exc, ex);
3623 * mono_wait_handle_new:
3624 * @domain: Domain where the object will be created
3625 * @handle: Handle for the wait handle
3627 * Returns: A new MonoWaitHandle created in the given domain for the given handle
3630 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
3632 MonoWaitHandle *res;
3634 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
3636 res->handle = handle;
3642 * mono_async_result_new:
3643 * @domain:domain where the object will be created.
3644 * @handle: wait handle.
3645 * @state: state to pass to AsyncResult
3646 * @data: C closure data.
3648 * Creates a new MonoAsyncResult (AsyncResult C# class) in the given domain.
3649 * If the handle is not null, the handle is initialized to a MonOWaitHandle.
3653 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data)
3655 MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
3656 MonoMethod *method = mono_get_context_capture_method ();
3658 /* we must capture the execution context from the original thread */
3660 MONO_OBJECT_SETREF (res, execution_context, mono_runtime_invoke (method, NULL, NULL, NULL));
3661 /* note: result may be null if the flow is suppressed */
3665 MONO_OBJECT_SETREF (res, object_data, object_data);
3666 MONO_OBJECT_SETREF (res, async_state, state);
3668 MONO_OBJECT_SETREF (res, handle, (MonoObject *) mono_wait_handle_new (domain, handle));
3670 res->sync_completed = FALSE;
3671 res->completed = FALSE;
3677 mono_message_init (MonoDomain *domain,
3678 MonoMethodMessage *this,
3679 MonoReflectionMethod *method,
3680 MonoArray *out_args)
3682 MonoMethodSignature *sig = mono_method_signature (method->method);
3688 MONO_OBJECT_SETREF (this, method, method);
3690 MONO_OBJECT_SETREF (this, args, mono_array_new (domain, mono_defaults.object_class, sig->param_count));
3691 MONO_OBJECT_SETREF (this, arg_types, mono_array_new (domain, mono_defaults.byte_class, sig->param_count));
3692 this->async_result = NULL;
3693 this->call_type = CallType_Sync;
3695 names = g_new (char *, sig->param_count);
3696 mono_method_get_param_names (method->method, (const char **) names);
3697 MONO_OBJECT_SETREF (this, names, mono_array_new (domain, mono_defaults.string_class, sig->param_count));
3699 for (i = 0; i < sig->param_count; i++) {
3700 name = mono_string_new (domain, names [i]);
3701 mono_array_setref (this->names, i, name);
3705 for (i = 0, j = 0; i < sig->param_count; i++) {
3707 if (sig->params [i]->byref) {
3709 MonoObject* arg = mono_array_get (out_args, gpointer, j);
3710 mono_array_setref (this->args, i, arg);
3714 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
3718 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT)
3721 mono_array_set (this->arg_types, guint8, i, arg_type);
3726 * mono_remoting_invoke:
3727 * @real_proxy: pointer to a RealProxy object
3728 * @msg: The MonoMethodMessage to execute
3729 * @exc: used to store exceptions
3730 * @out_args: used to store output arguments
3732 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
3733 * IMessage interface and it is not trivial to extract results from there. So
3734 * we call an helper method PrivateInvoke instead of calling
3735 * RealProxy::Invoke() directly.
3737 * Returns: the result object.
3740 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
3741 MonoObject **exc, MonoArray **out_args)
3743 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
3746 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
3749 im = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "PrivateInvoke", 4);
3751 real_proxy->vtable->domain->private_invoke_method = im;
3754 pa [0] = real_proxy;
3759 return mono_runtime_invoke (im, NULL, pa, exc);
3763 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
3764 MonoObject **exc, MonoArray **out_args)
3768 MonoMethodSignature *sig;
3770 int i, j, outarg_count = 0;
3772 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
3774 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
3775 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3776 target = tp->rp->unwrapped_server;
3778 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
3782 domain = mono_domain_get ();
3783 method = msg->method->method;
3784 sig = mono_method_signature (method);
3786 for (i = 0; i < sig->param_count; i++) {
3787 if (sig->params [i]->byref)
3791 /* FIXME: GC ensure we insert a write barrier for out_args, maybe in the caller? */
3792 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3795 ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
3797 for (i = 0, j = 0; i < sig->param_count; i++) {
3798 if (sig->params [i]->byref) {
3800 arg = mono_array_get (msg->args, gpointer, i);
3801 mono_array_setref (*out_args, j, arg);
3810 * mono_print_unhandled_exception:
3811 * @exc: The exception
3813 * Prints the unhandled exception.
3816 mono_print_unhandled_exception (MonoObject *exc)
3818 char *message = (char *) "";
3822 gboolean free_message = FALSE;
3824 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
3825 klass = exc->vtable->klass;
3827 while (klass && method == NULL) {
3828 method = mono_class_get_method_from_name_flags (klass, "ToString", 0, METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_PUBLIC);
3830 klass = klass->parent;
3835 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
3837 message = mono_string_to_utf8 (str);
3838 free_message = TRUE;
3843 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
3844 * exc->vtable->klass->name, message);
3846 g_printerr ("\nUnhandled Exception: %s\n", message);
3853 * mono_delegate_ctor:
3854 * @this: pointer to an uninitialized delegate object
3855 * @target: target object
3856 * @addr: pointer to native code
3858 * This is used to initialize a delegate. We also insert the method_info if
3859 * we find the info with mono_jit_info_table_find().
3862 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
3864 MonoDomain *domain = mono_domain_get ();
3865 MonoDelegate *delegate = (MonoDelegate *)this;
3866 MonoMethod *method = NULL;
3873 class = this->vtable->klass;
3875 if ((ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (addr)))) {
3876 method = ji->method;
3877 MONO_OBJECT_SETREF (delegate, method_info, mono_method_get_object (domain, method, NULL));
3880 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
3882 method = mono_marshal_get_remoting_invoke (method);
3883 delegate->method_ptr = mono_compile_method (method);
3884 MONO_OBJECT_SETREF (delegate, target, target);
3885 } else if (mono_method_signature (method)->hasthis && method->klass->valuetype) {
3886 method = mono_marshal_get_unbox_wrapper (method);
3887 delegate->method_ptr = mono_compile_method (method);
3888 MONO_OBJECT_SETREF (delegate, target, target);
3892 * Replace the original trampoline with a delegate trampoline
3893 * which will patch delegate->method_ptr with the address of the
3896 addr = arch_create_delegate_trampoline (method, addr);
3898 delegate->method_ptr = addr;
3899 MONO_OBJECT_SETREF (delegate, target, target);
3904 * mono_method_call_message_new:
3905 * @method: method to encapsulate
3906 * @params: parameters to the method
3907 * @invoke: optional, delegate invoke.
3908 * @cb: async callback delegate.
3909 * @state: state passed to the async callback.
3911 * Translates arguments pointers into a MonoMethodMessage.
3914 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
3915 MonoDelegate **cb, MonoObject **state)
3917 MonoDomain *domain = mono_domain_get ();
3918 MonoMethodSignature *sig = mono_method_signature (method);
3919 MonoMethodMessage *msg;
3922 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3925 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
3926 count = sig->param_count - 2;
3928 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
3929 count = sig->param_count;
3932 for (i = 0; i < count; i++) {
3937 if (sig->params [i]->byref)
3938 vpos = *((gpointer *)params [i]);
3942 type = sig->params [i]->type;
3943 class = mono_class_from_mono_type (sig->params [i]);
3945 if (class->valuetype)
3946 arg = mono_value_box (domain, class, vpos);
3948 arg = *((MonoObject **)vpos);
3950 mono_array_setref (msg->args, i, arg);
3953 if (cb != NULL && state != NULL) {
3954 *cb = *((MonoDelegate **)params [i]);
3956 *state = *((MonoObject **)params [i]);
3963 * mono_method_return_message_restore:
3965 * Restore results from message based processing back to arguments pointers
3968 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
3970 MonoMethodSignature *sig = mono_method_signature (method);
3971 int i, j, type, size, out_len;
3973 if (out_args == NULL)
3975 out_len = mono_array_length (out_args);
3979 for (i = 0, j = 0; i < sig->param_count; i++) {
3980 MonoType *pt = sig->params [i];
3985 mono_raise_exception (mono_get_exception_execution_engine ("The proxy call returned an incorrect number of output arguments"));
3987 arg = mono_array_get (out_args, gpointer, j);
3991 case MONO_TYPE_VOID:
3992 g_assert_not_reached ();
3996 case MONO_TYPE_BOOLEAN:
3999 case MONO_TYPE_CHAR:
4006 case MONO_TYPE_VALUETYPE: {
4008 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
4009 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
4012 size = mono_class_value_size (mono_class_from_mono_type (pt), NULL);
4013 memset (*((gpointer *)params [i]), 0, size);
4017 case MONO_TYPE_STRING:
4018 case MONO_TYPE_CLASS:
4019 case MONO_TYPE_ARRAY:
4020 case MONO_TYPE_SZARRAY:
4021 case MONO_TYPE_OBJECT:
4022 **((MonoObject ***)params [i]) = (MonoObject *)arg;
4025 g_assert_not_reached ();
4034 * mono_load_remote_field:
4035 * @this: pointer to an object
4036 * @klass: klass of the object containing @field
4037 * @field: the field to load
4038 * @res: a storage to store the result
4040 * This method is called by the runtime on attempts to load fields of
4041 * transparent proxy objects. @this points to such TP, @klass is the class of
4042 * the object containing @field. @res is a storage location which can be
4043 * used to store the result.
4045 * Returns: an address pointing to the value of field.
4048 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
4050 static MonoMethod *getter = NULL;
4051 MonoDomain *domain = mono_domain_get ();
4052 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
4053 MonoClass *field_class;
4054 MonoMethodMessage *msg;
4055 MonoArray *out_args;
4059 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
4060 g_assert (res != NULL);
4062 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
4063 mono_field_get_value (tp->rp->unwrapped_server, field, res);
4068 getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
4072 field_class = mono_class_from_mono_type (field->type);
4074 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
4075 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
4076 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
4078 full_name = mono_type_get_full_name (klass);
4079 mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
4080 mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
4083 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
4085 if (exc) mono_raise_exception ((MonoException *)exc);
4087 if (mono_array_length (out_args) == 0)
4090 *res = mono_array_get (out_args, MonoObject *, 0); /* FIXME: GC write abrrier for res */
4092 if (field_class->valuetype) {
4093 return ((char *)*res) + sizeof (MonoObject);
4099 * mono_load_remote_field_new:
4104 * Missing documentation.
4107 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
4109 static MonoMethod *getter = NULL;
4110 MonoDomain *domain = mono_domain_get ();
4111 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
4112 MonoClass *field_class;
4113 MonoMethodMessage *msg;
4114 MonoArray *out_args;
4115 MonoObject *exc, *res;
4118 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
4120 field_class = mono_class_from_mono_type (field->type);
4122 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
4124 if (field_class->valuetype) {
4125 res = mono_object_new (domain, field_class);
4126 val = ((gchar *) res) + sizeof (MonoObject);
4130 mono_field_get_value (tp->rp->unwrapped_server, field, val);
4135 getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
4139 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
4140 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
4142 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
4144 full_name = mono_type_get_full_name (klass);
4145 mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
4146 mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
4149 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
4151 if (exc) mono_raise_exception ((MonoException *)exc);
4153 if (mono_array_length (out_args) == 0)
4156 res = mono_array_get (out_args, MonoObject *, 0);
4162 * mono_store_remote_field:
4163 * @this: pointer to an object
4164 * @klass: klass of the object containing @field
4165 * @field: the field to load
4166 * @val: the value/object to store
4168 * This method is called by the runtime on attempts to store fields of
4169 * transparent proxy objects. @this points to such TP, @klass is the class of
4170 * the object containing @field. @val is the new value to store in @field.
4173 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
4175 static MonoMethod *setter = NULL;
4176 MonoDomain *domain = mono_domain_get ();
4177 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
4178 MonoClass *field_class;
4179 MonoMethodMessage *msg;
4180 MonoArray *out_args;
4185 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
4187 field_class = mono_class_from_mono_type (field->type);
4189 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
4190 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
4191 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
4196 setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
4200 if (field_class->valuetype)
4201 arg = mono_value_box (domain, field_class, val);
4203 arg = *((MonoObject **)val);
4206 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
4207 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
4209 full_name = mono_type_get_full_name (klass);
4210 mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
4211 mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
4212 mono_array_setref (msg->args, 2, arg);
4215 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
4217 if (exc) mono_raise_exception ((MonoException *)exc);
4221 * mono_store_remote_field_new:
4227 * Missing documentation
4230 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
4232 static MonoMethod *setter = NULL;
4233 MonoDomain *domain = mono_domain_get ();
4234 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
4235 MonoClass *field_class;
4236 MonoMethodMessage *msg;
4237 MonoArray *out_args;
4241 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
4243 field_class = mono_class_from_mono_type (field->type);
4245 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
4246 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
4247 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
4252 setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
4256 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
4257 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
4259 full_name = mono_type_get_full_name (klass);
4260 mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
4261 mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
4262 mono_array_setref (msg->args, 2, arg);
4265 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
4267 if (exc) mono_raise_exception ((MonoException *)exc);
4271 * mono_get_addr_from_ftnptr:
4273 * Given a pointer to a function descriptor, return the function address.
4274 * This is only needed on IA64.
4277 mono_get_addr_from_ftnptr (gpointer descr)
4280 return *(gpointer*)descr;
4288 * mono_string_chars:
4291 * Returns a pointer to the UCS16 characters stored in the MonoString
4294 mono_string_chars(MonoString *s)
4296 /* This method is here only for documentation extraction, this is a macro */
4300 * mono_string_length:
4303 * Returns the lenght in characters of the string
4306 mono_string_length (MonoString *s)
4308 /* This method is here only for documentation extraction, this is a macro */