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 * mono_runtime_class_init:
190 * @vtable: vtable that needs to be initialized
192 * This routine calls the class constructor for @vtable.
195 mono_runtime_class_init (MonoVTable *vtable)
198 MonoException *exc_to_throw;
199 MonoMethod *method = NULL;
205 if (vtable->initialized)
209 klass = vtable->klass;
211 method = mono_class_get_cctor (klass);
214 MonoDomain *domain = vtable->domain;
215 TypeInitializationLock *lock;
216 guint32 tid = GetCurrentThreadId();
217 int do_initialization = 0;
218 MonoDomain *last_domain = NULL;
220 mono_type_initialization_lock ();
221 /* double check... */
222 if (vtable->initialized) {
223 mono_type_initialization_unlock ();
226 lock = g_hash_table_lookup (type_initialization_hash, vtable);
228 /* This thread will get to do the initialization */
229 if (mono_domain_get () != domain) {
230 /* Transfer into the target domain */
231 last_domain = mono_domain_get ();
232 if (!mono_domain_set (domain, FALSE)) {
233 vtable->initialized = 1;
234 mono_type_initialization_unlock ();
235 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
238 lock = g_malloc (sizeof(TypeInitializationLock));
239 InitializeCriticalSection (&lock->initialization_section);
240 lock->initializing_tid = tid;
241 lock->waiting_count = 1;
243 /* grab the vtable lock while this thread still owns type_initialization_section */
244 EnterCriticalSection (&lock->initialization_section);
245 g_hash_table_insert (type_initialization_hash, vtable, lock);
246 do_initialization = 1;
249 TypeInitializationLock *pending_lock;
251 if (lock->initializing_tid == tid || lock->done) {
252 mono_type_initialization_unlock ();
255 /* see if the thread doing the initialization is already blocked on this thread */
256 blocked = GUINT_TO_POINTER (lock->initializing_tid);
257 while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) {
258 if (pending_lock->initializing_tid == tid) {
259 if (!pending_lock->done) {
260 mono_type_initialization_unlock ();
263 /* the thread doing the initialization is blocked on this thread,
264 but on a lock that has already been freed. It just hasn't got
269 blocked = GUINT_TO_POINTER (pending_lock->initializing_tid);
271 ++lock->waiting_count;
272 /* record the fact that we are waiting on the initializing thread */
273 g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
275 mono_type_initialization_unlock ();
277 if (do_initialization) {
278 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
280 mono_domain_set (last_domain, TRUE);
282 LeaveCriticalSection (&lock->initialization_section);
284 /* this just blocks until the initializing thread is done */
285 EnterCriticalSection (&lock->initialization_section);
286 LeaveCriticalSection (&lock->initialization_section);
289 mono_type_initialization_lock ();
290 if (lock->initializing_tid != tid)
291 g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
292 --lock->waiting_count;
293 if (lock->waiting_count == 0) {
294 DeleteCriticalSection (&lock->initialization_section);
295 g_hash_table_remove (type_initialization_hash, vtable);
298 vtable->initialized = 1;
299 /* FIXME: if the cctor fails, the type must be marked as unusable */
300 mono_type_initialization_unlock ();
302 vtable->initialized = 1;
307 (klass->image == mono_defaults.corlib &&
308 !strcmp (klass->name_space, "System") &&
309 !strcmp (klass->name, "TypeInitializationException")))
310 return; /* No static constructor found or avoid infinite loop */
312 if (klass->name_space && *klass->name_space)
313 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
315 full_name = g_strdup (klass->name);
317 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
320 mono_raise_exception (exc_to_throw);
324 gboolean release_type_locks (gpointer key, gpointer value, gpointer user)
326 TypeInitializationLock *lock = (TypeInitializationLock*) value;
327 if (lock->initializing_tid == GPOINTER_TO_UINT (user) && !lock->done) {
329 LeaveCriticalSection (&lock->initialization_section);
330 --lock->waiting_count;
331 if (lock->waiting_count == 0) {
332 DeleteCriticalSection (&lock->initialization_section);
341 mono_release_type_locks (MonoThread *thread)
343 mono_type_initialization_lock ();
344 g_hash_table_foreach_remove (type_initialization_hash, release_type_locks, (gpointer)(gsize)(thread->tid));
345 mono_type_initialization_unlock ();
349 default_trampoline (MonoMethod *method)
355 default_remoting_trampoline (MonoMethod *method, MonoRemotingTarget target)
357 g_error ("remoting not installed");
362 default_delegate_trampoline (MonoMethod *method, gpointer addr)
364 g_assert_not_reached ();
368 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
369 static MonoRemotingTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
370 static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline;
373 mono_install_trampoline (MonoTrampoline func)
375 arch_create_jit_trampoline = func? func: default_trampoline;
379 mono_install_remoting_trampoline (MonoRemotingTrampoline func)
381 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
385 mono_install_delegate_trampoline (MonoDelegateTrampoline func)
387 arch_create_delegate_trampoline = func? func: default_delegate_trampoline;
390 static MonoCompileFunc default_mono_compile_method = NULL;
393 * mono_install_compile_method:
394 * @func: function to install
396 * This is a VM internal routine
399 mono_install_compile_method (MonoCompileFunc func)
401 default_mono_compile_method = func;
405 * mono_compile_method:
406 * @method: The method to compile.
408 * This JIT-compiles the method, and returns the pointer to the native code
412 mono_compile_method (MonoMethod *method)
414 if (!default_mono_compile_method) {
415 g_error ("compile method called on uninitialized runtime");
418 return default_mono_compile_method (method);
421 static MonoFreeMethodFunc default_mono_free_method = NULL;
424 * mono_install_free_method:
425 * @func: pointer to the MonoFreeMethodFunc used to release a method
427 * This is an internal VM routine, it is used for the engines to
428 * register a handler to release the resources associated with a method.
430 * Methods are freed when no more references to the delegate that holds
434 mono_install_free_method (MonoFreeMethodFunc func)
436 default_mono_free_method = func;
440 * mono_runtime_free_method:
441 * @domain; domain where the method is hosted
442 * @method: method to release
444 * This routine is invoked to free the resources associated with
445 * a method that has been JIT compiled. This is used to discard
446 * methods that were used only temporarily (for example, used in marshalling)
450 mono_runtime_free_method (MonoDomain *domain, MonoMethod *method)
452 if (default_mono_free_method != NULL)
453 default_mono_free_method (domain, method);
455 mono_free_method (method);
458 static MonoInitVTableFunc init_vtable_func = NULL;
461 * mono_install_init_vtable:
462 * @func: pointer to the function to be installed
464 * Register a function which will be called by the runtime to initialize the
465 * method pointers inside a vtable. The JIT can use this function to load the
466 * vtable from the AOT file for example.
469 mono_install_init_vtable (MonoInitVTableFunc func)
471 init_vtable_func = func;
475 * The vtables in the root appdomain are assumed to be reachable by other
476 * roots, and we don't use typed allocation in the other domains.
479 /* The sync block is no longer a GC pointer */
480 #define GC_HEADER_BITMAP (0)
482 #define BITMAP_EL_SIZE (sizeof (gsize) * 8)
485 compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set, gboolean static_fields)
487 MonoClassField *field;
493 max_size = class->class_size / sizeof (gpointer);
495 max_size = class->instance_size / sizeof (gpointer);
496 if (max_size > size) {
497 bitmap = g_malloc0 (sizeof (gsize) * ((max_size) + 1));
500 for (p = class; p != NULL; p = p->parent) {
501 gpointer iter = NULL;
502 while ((field = mono_class_get_fields (p, &iter))) {
506 if (!(field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA)))
509 if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
512 /* FIXME: should not happen, flag as type load error */
513 if (field->type->byref)
516 pos = field->offset / sizeof (gpointer);
519 type = mono_type_get_underlying_type (field->type);
520 switch (type->type) {
521 /* FIXME: _I and _U and _PTR should be removed eventually */
525 case MONO_TYPE_FNPTR:
529 case MONO_TYPE_STRING:
530 case MONO_TYPE_SZARRAY:
531 case MONO_TYPE_CLASS:
532 case MONO_TYPE_OBJECT:
533 case MONO_TYPE_ARRAY:
534 g_assert ((field->offset % sizeof(gpointer)) == 0);
536 bitmap [pos / BITMAP_EL_SIZE] |= ((gsize)1) << (pos % BITMAP_EL_SIZE);
537 *max_set = MAX (*max_set, pos);
539 case MONO_TYPE_GENERICINST:
540 if (!mono_type_generic_inst_is_valuetype (type)) {
541 g_assert ((field->offset % sizeof(gpointer)) == 0);
543 bitmap [pos / BITMAP_EL_SIZE] |= ((gsize)1) << (pos % BITMAP_EL_SIZE);
544 *max_set = MAX (*max_set, pos);
549 case MONO_TYPE_VALUETYPE: {
550 MonoClass *fclass = mono_class_from_mono_type (field->type);
551 if (fclass->has_references) {
552 /* remove the object header */
553 compute_class_bitmap (fclass, bitmap, size, pos - (sizeof (MonoObject) / sizeof (gpointer)), max_set, FALSE);
567 case MONO_TYPE_BOOLEAN:
571 g_assert_not_reached ();
582 mono_class_compute_gc_descriptor (MonoClass *class)
586 gsize default_bitmap [4] = {0};
587 static gboolean gcj_inited = FALSE;
592 mono_register_jit_icall (mono_object_new_ptrfree, "mono_object_new_ptrfree", mono_create_icall_signature ("object ptr"), FALSE);
593 mono_register_jit_icall (mono_object_new_ptrfree_box, "mono_object_new_ptrfree_box", mono_create_icall_signature ("object ptr"), FALSE);
594 mono_register_jit_icall (mono_object_new_fast, "mono_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE);
596 #ifdef HAVE_GC_GCJ_MALLOC
598 GC_init_gcj_malloc (5, NULL);
600 #ifdef GC_REDIRECT_TO_LOCAL
601 mono_register_jit_icall (GC_local_gcj_malloc, "GC_local_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
602 mono_register_jit_icall (GC_local_gcj_fast_malloc, "GC_local_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
604 mono_register_jit_icall (GC_gcj_malloc, "GC_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
605 mono_register_jit_icall (GC_gcj_fast_malloc, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
608 mono_loader_unlock ();
612 mono_class_init (class);
614 if (class->gc_descr_inited)
617 class->gc_descr_inited = TRUE;
618 class->gc_descr = GC_NO_DESCRIPTOR;
620 bitmap = default_bitmap;
621 if (class == mono_defaults.string_class) {
622 class->gc_descr = (gpointer)MAKE_STRING_DESCRIPTOR (bitmap, 2);
623 } else if (class->rank) {
624 mono_class_compute_gc_descriptor (class->element_class);
626 /* libgc has no usable support for arrays... */
627 if (!class->element_class->valuetype) {
629 class->gc_descr = mono_gc_make_descr_for_array (TRUE, &abm, 1, sizeof (gpointer));
630 /*printf ("new array descriptor: 0x%x for %s.%s\n", class->gc_descr,
631 class->name_space, class->name);*/
633 /* remove the object header */
634 bitmap = compute_class_bitmap (class->element_class, default_bitmap, sizeof (default_bitmap) * 8, - (sizeof (MonoObject) / sizeof (gpointer)), &max_set, FALSE);
635 class->gc_descr = mono_gc_make_descr_for_array (TRUE, bitmap, mono_array_element_size (class) / sizeof (gpointer), mono_array_element_size (class));
636 /*printf ("new vt array descriptor: 0x%x for %s.%s\n", class->gc_descr,
637 class->name_space, class->name);*/
638 if (bitmap != default_bitmap)
643 /*static int count = 0;
646 bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, FALSE);
648 /* It seems there are issues when the bitmap doesn't fit: play it safe */
650 /*g_print ("disabling typed alloc (%d) for %s.%s\n", max_set, class->name_space, class->name);*/
651 if (bitmap != default_bitmap)
656 class->gc_descr = (gpointer)MAKE_DESCRIPTOR (bitmap, max_set + 1, class->instance_size);
657 /*printf ("new descriptor: %p 0x%x for %s.%s\n", class->gc_descr, bitmap [0], class->name_space, class->name);*/
658 if (bitmap != default_bitmap)
664 * field_is_special_static:
665 * @fklass: The MonoClass to look up.
666 * @field: The MonoClassField describing the field.
668 * Returns: SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
669 * SPECIAL_STATIC_NONE otherwise.
672 field_is_special_static (MonoClass *fklass, MonoClassField *field)
674 MonoCustomAttrInfo *ainfo;
676 ainfo = mono_custom_attrs_from_field (fklass, field);
679 for (i = 0; i < ainfo->num_attrs; ++i) {
680 MonoClass *klass = ainfo->attrs [i].ctor->klass;
681 if (klass->image == mono_defaults.corlib) {
682 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
683 mono_custom_attrs_free (ainfo);
684 return SPECIAL_STATIC_THREAD;
686 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
687 mono_custom_attrs_free (ainfo);
688 return SPECIAL_STATIC_CONTEXT;
692 mono_custom_attrs_free (ainfo);
693 return SPECIAL_STATIC_NONE;
696 static MonoVTable *mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class);
700 * @domain: the application domain
701 * @class: the class to initialize
703 * VTables are domain specific because we create domain specific code, and
704 * they contain the domain specific static class data.
707 mono_class_vtable (MonoDomain *domain, MonoClass *class)
709 MonoClassRuntimeInfo *runtime_info;
713 /* this check can be inlined in jitted code, too */
714 runtime_info = class->runtime_info;
715 if (runtime_info && runtime_info->max_domain >= domain->domain_id && runtime_info->domain_vtables [domain->domain_id])
716 return runtime_info->domain_vtables [domain->domain_id];
717 return mono_class_create_runtime_vtable (domain, class);
721 mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
724 MonoClassRuntimeInfo *runtime_info, *old_info;
725 MonoClassField *field;
728 gboolean inited = FALSE;
731 guint32 constant_cols [MONO_CONSTANT_SIZE];
733 gpointer *interface_offsets;
735 mono_domain_lock (domain);
736 runtime_info = class->runtime_info;
737 if (runtime_info && runtime_info->max_domain >= domain->domain_id && runtime_info->domain_vtables [domain->domain_id]) {
738 mono_domain_unlock (domain);
739 return runtime_info->domain_vtables [domain->domain_id];
742 if (!mono_class_init (class)){
744 mono_domain_unlock (domain);
745 exc = mono_class_get_exception_for_failure (class);
747 mono_raise_exception (exc);
751 * FIXME: This breaks the AOT optimization below. This should be changed
752 * to only init the interface offsets etc.
754 mono_class_setup_vtable (class);
756 vtable_size = sizeof (gpointer) * (class->max_interface_id + 1) +
757 sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
759 mono_stats.used_class_count++;
760 mono_stats.class_vtable_size += vtable_size;
761 interface_offsets = mono_mempool_alloc0 (domain->mp, vtable_size);
763 vt = (MonoVTable*) (interface_offsets + class->max_interface_id + 1);
765 vt->rank = class->rank;
768 mono_class_compute_gc_descriptor (class);
770 * We can't use typed allocation in the non-root domains, since the
771 * collector needs the GC descriptor stored in the vtable even after
772 * the mempool containing the vtable is destroyed when the domain is
773 * unloaded. An alternative might be to allocate vtables in the GC
774 * heap, but this does not seem to work (it leads to crashes inside
775 * libgc). If that approach is tried, two gc descriptors need to be
776 * allocated for each class: one for the root domain, and one for all
777 * other domains. The second descriptor should contain a bit for the
778 * vtable field in MonoObject, since we can no longer assume the
779 * vtable is reachable by other roots after the appdomain is unloaded.
782 if (domain != mono_get_root_domain ())
783 vt->gc_descr = GC_NO_DESCRIPTOR;
786 vt->gc_descr = class->gc_descr;
788 if (class->class_size) {
789 if (class->has_static_refs) {
790 gpointer statics_gc_descr;
792 gsize default_bitmap [4] = {0};
795 bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, TRUE);
796 /*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class->class_size);*/
797 statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set? max_set + 1: 0);
798 vt->data = mono_gc_alloc_fixed (class->class_size, statics_gc_descr);
799 mono_domain_add_class_static_data (domain, class, vt->data, NULL);
800 if (bitmap != default_bitmap)
803 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size);
805 mono_stats.class_static_data_size += class->class_size;
810 while ((field = mono_class_get_fields (class, &iter))) {
811 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
813 if (mono_field_is_deleted (field))
815 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
816 gint32 special_static = class->no_special_static_fields ? SPECIAL_STATIC_NONE : field_is_special_static (class, field);
817 if (special_static != SPECIAL_STATIC_NONE) {
818 guint32 size, offset;
820 size = mono_type_size (field->type, &align);
821 offset = mono_alloc_special_static_data (special_static, size, align);
822 if (!domain->special_static_fields)
823 domain->special_static_fields = g_hash_table_new (NULL, NULL);
824 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
828 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
829 MonoClass *fklass = mono_class_from_mono_type (field->type);
830 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT));
831 t = (char*)vt->data + field->offset;
832 if (fklass->valuetype) {
833 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
835 /* it's a pointer type: add check */
836 g_assert ((fklass->byval_arg.type == MONO_TYPE_PTR) || (fklass->byval_arg.type == MONO_TYPE_FNPTR));
837 *t = *(char *)field->data;
841 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
844 /* later do this only on demand if needed */
846 cindex = mono_metadata_get_constant_index (class->image, mono_class_get_field_token (field), cindex + 1);
848 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
850 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
851 field->def_type = constant_cols [MONO_CONSTANT_TYPE];
852 field->data = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
857 vt->max_interface_id = class->max_interface_id;
859 /* initialize interface offsets */
860 for (i = 0; i <= class->max_interface_id; ++i) {
861 int slot = class->interface_offsets [i];
863 interface_offsets [class->max_interface_id - i] = &(vt->vtable [slot]);
867 * arch_create_jit_trampoline () can recursively call this function again
868 * because it compiles icall methods right away.
870 /* FIXME: class_vtable_hash is basically obsolete now: remove as soon
871 * as we change the code in appdomain.c to invalidate vtables by
872 * looking at the possible MonoClasses created for the domain.
874 g_hash_table_insert (domain->class_vtable_hash, class, vt);
875 /* class->runtime_info is protected by the loader lock, both when
876 * it it enlarged and when it is stored info.
879 old_info = class->runtime_info;
880 if (old_info && old_info->max_domain >= domain->domain_id) {
881 /* someone already created a large enough runtime info */
882 old_info->domain_vtables [domain->domain_id] = vt;
884 int new_size = domain->domain_id;
886 new_size = MAX (new_size, old_info->max_domain);
888 /* make the new size a power of two */
893 /* this is a bounded memory retention issue: may want to
894 * handle it differently when we'll have a rcu-like system.
896 runtime_info = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassRuntimeInfo) + new_size * sizeof (gpointer));
897 runtime_info->max_domain = new_size - 1;
898 /* copy the stuff from the older info */
900 memcpy (runtime_info->domain_vtables, old_info->domain_vtables, (old_info->max_domain + 1) * sizeof (gpointer));
902 runtime_info->domain_vtables [domain->domain_id] = vt;
903 /* keep this last (add membarrier) */
904 class->runtime_info = runtime_info;
906 mono_loader_unlock ();
908 /* initialize vtable */
909 if (init_vtable_func)
910 inited = init_vtable_func (vt);
913 mono_class_setup_vtable (class);
915 for (i = 0; i < class->vtable_size; ++i) {
918 if ((cm = class->vtable [i])) {
919 if (mono_method_signature (cm)->generic_param_count)
922 vt->vtable [i] = arch_create_jit_trampoline (cm);
927 mono_domain_unlock (domain);
929 /* Initialization is now complete, we can throw if the InheritanceDemand aren't satisfied */
930 if (mono_is_security_manager_active () && (class->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND)) {
931 MonoException *exc = mono_class_get_exception_for_failure (class);
933 mono_raise_exception (exc);
936 /* make sure the the parent is initialized */
938 mono_class_vtable (domain, class->parent);
940 vt->type = mono_type_get_object (domain, &class->byval_arg);
941 if (class->contextbound)
950 * mono_class_proxy_vtable:
951 * @domain: the application domain
952 * @remove_class: the remote class
954 * Creates a vtable for transparent proxies. It is basically
955 * a copy of the real vtable of the class wrapped in @remote_class,
956 * but all function pointers invoke the remoting functions, and
957 * vtable->klass points to the transparent proxy class, and not to @class.
960 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type)
962 MonoVTable *vt, *pvt;
963 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
965 GSList *extra_interfaces = NULL;
966 MonoClass *class = remote_class->proxy_class;
967 gpointer *interface_offsets;
969 vt = mono_class_vtable (domain, class);
970 max_interface_id = vt->max_interface_id;
972 /* Calculate vtable space for extra interfaces */
973 for (j = 0; j < remote_class->interface_count; j++) {
974 MonoClass* iclass = remote_class->interfaces[j];
978 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != -1)
979 continue; /* interface implemented by the class */
980 if (g_slist_find (extra_interfaces, iclass))
983 extra_interfaces = g_slist_prepend (extra_interfaces, iclass);
985 method_count = mono_class_num_methods (iclass);
987 ifaces = mono_class_get_implemented_interfaces (iclass);
989 for (i = 0; i < ifaces->len; ++i) {
990 MonoClass *ic = g_ptr_array_index (ifaces, i);
991 if (ic->interface_id <= class->max_interface_id && class->interface_offsets[ic->interface_id] != -1)
992 continue; /* interface implemented by the class */
993 if (g_slist_find (extra_interfaces, ic))
995 extra_interfaces = g_slist_prepend (extra_interfaces, ic);
996 method_count += mono_class_num_methods (ic);
998 g_ptr_array_free (ifaces, TRUE);
1001 extra_interface_vtsize += method_count * sizeof (gpointer);
1002 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
1005 vtsize = sizeof (gpointer) * (max_interface_id + 1) +
1006 sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
1008 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
1010 interface_offsets = mono_mempool_alloc0 (domain->mp, vtsize + extra_interface_vtsize);
1011 pvt = (MonoVTable*)(interface_offsets + max_interface_id + 1);
1012 memcpy (pvt, vt, sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer));
1014 pvt->klass = mono_defaults.transparent_proxy_class;
1015 /* we need to keep the GC descriptor for a transparent proxy or we confuse the precise GC */
1016 pvt->gc_descr = mono_defaults.transparent_proxy_class->gc_descr;
1018 /* initialize vtable */
1019 mono_class_setup_vtable (class);
1020 for (i = 0; i < class->vtable_size; ++i) {
1023 if ((cm = class->vtable [i]))
1024 pvt->vtable [i] = arch_create_remoting_trampoline (cm, target_type);
1027 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT) {
1028 /* create trampolines for abstract methods */
1029 for (k = class; k; k = k->parent) {
1031 gpointer iter = NULL;
1032 while ((m = mono_class_get_methods (k, &iter)))
1033 if (!pvt->vtable [m->slot])
1034 pvt->vtable [m->slot] = arch_create_remoting_trampoline (m, target_type);
1038 pvt->max_interface_id = max_interface_id;
1040 /* initialize interface offsets */
1041 for (i = 0; i <= class->max_interface_id; ++i) {
1042 int slot = class->interface_offsets [i];
1044 interface_offsets [max_interface_id - i] = &(pvt->vtable [slot]);
1047 if (extra_interfaces) {
1048 int slot = class->vtable_size;
1054 /* Create trampolines for the methods of the interfaces */
1055 for (list_item = extra_interfaces; list_item != NULL; list_item=list_item->next) {
1056 interf = list_item->data;
1057 interface_offsets [max_interface_id - interf->interface_id] = &pvt->vtable [slot];
1061 while ((cm = mono_class_get_methods (interf, &iter)))
1062 pvt->vtable [slot + j++] = arch_create_remoting_trampoline (cm, target_type);
1064 slot += mono_class_num_methods (interf);
1066 g_slist_free (extra_interfaces);
1073 * mono_class_has_special_static_fields:
1075 * Returns whenever @klass has any thread/context static fields.
1078 mono_class_has_special_static_fields (MonoClass *klass)
1080 MonoClassField *field;
1084 while ((field = mono_class_get_fields (klass, &iter))) {
1085 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
1087 if (mono_field_is_deleted (field))
1089 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
1090 if (field_is_special_static (klass, field) != SPECIAL_STATIC_NONE)
1099 * create_remote_class_key:
1100 * Creates an array of pointers that can be used as a hash key for a remote class.
1101 * The first element of the array is the number of pointers.
1104 create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
1109 if (remote_class == NULL) {
1110 if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1111 key = g_malloc (sizeof(gpointer) * 3);
1112 key [0] = GINT_TO_POINTER (2);
1113 key [1] = mono_defaults.marshalbyrefobject_class;
1114 key [2] = extra_class;
1116 key = g_malloc (sizeof(gpointer) * 2);
1117 key [0] = GINT_TO_POINTER (1);
1118 key [1] = extra_class;
1121 if (extra_class != NULL && (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
1122 key = g_malloc (sizeof(gpointer) * (remote_class->interface_count + 3));
1123 key [0] = GINT_TO_POINTER (remote_class->interface_count + 2);
1124 key [1] = remote_class->proxy_class;
1126 // Keep the list of interfaces sorted
1127 for (i = 0, j = 2; i < remote_class->interface_count; i++, j++) {
1128 if (extra_class && remote_class->interfaces [i] > extra_class) {
1129 key [j++] = extra_class;
1132 key [j] = remote_class->interfaces [i];
1135 key [j] = extra_class;
1137 // Replace the old class. The interface list is the same
1138 key = g_malloc (sizeof(gpointer) * (remote_class->interface_count + 2));
1139 key [0] = GINT_TO_POINTER (remote_class->interface_count + 1);
1140 key [1] = extra_class != NULL ? extra_class : remote_class->proxy_class;
1141 for (i = 0; i < remote_class->interface_count; i++)
1142 key [2 + i] = remote_class->interfaces [i];
1150 * copy_remote_class_key:
1152 * Make a copy of KEY in the mempool MP and return the copy.
1155 copy_remote_class_key (MonoMemPool *mp, gpointer *key)
1157 int key_size = (GPOINTER_TO_UINT (key [0]) + 1) * sizeof (gpointer);
1158 gpointer *mp_key = mono_mempool_alloc (mp, key_size);
1160 memcpy (mp_key, key, key_size);
1166 * mono_remote_class:
1167 * @domain: the application domain
1168 * @class_name: name of the remote class
1170 * Creates and initializes a MonoRemoteClass object for a remote type.
1174 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
1176 MonoRemoteClass *rc;
1177 gpointer* key, *mp_key;
1179 key = create_remote_class_key (NULL, proxy_class);
1181 mono_domain_lock (domain);
1182 rc = g_hash_table_lookup (domain->proxy_vtable_hash, key);
1186 mono_domain_unlock (domain);
1190 mp_key = copy_remote_class_key (domain->mp, key);
1194 if (proxy_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1195 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*));
1196 rc->interface_count = 1;
1197 rc->interfaces [0] = proxy_class;
1198 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
1200 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
1201 rc->interface_count = 0;
1202 rc->proxy_class = proxy_class;
1205 rc->default_vtable = NULL;
1206 rc->xdomain_vtable = NULL;
1207 rc->proxy_class_name = mono_string_to_utf8_mp (domain->mp, class_name);
1209 g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
1211 mono_domain_unlock (domain);
1216 * clone_remote_class:
1217 * Creates a copy of the remote_class, adding the provided class or interface
1219 static MonoRemoteClass*
1220 clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass *extra_class)
1222 MonoRemoteClass *rc;
1223 gpointer* key, *mp_key;
1225 key = create_remote_class_key (remote_class, extra_class);
1226 rc = g_hash_table_lookup (domain->proxy_vtable_hash, key);
1232 mp_key = copy_remote_class_key (domain->mp, key);
1236 if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1238 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * (remote_class->interface_count + 1));
1239 rc->proxy_class = remote_class->proxy_class;
1240 rc->interface_count = remote_class->interface_count + 1;
1242 // Keep the list of interfaces sorted, since the hash key of
1243 // the remote class depends on this
1244 for (i = 0, j = 0; i < remote_class->interface_count; i++, j++) {
1245 if (remote_class->interfaces [i] > extra_class && i == j)
1246 rc->interfaces [j++] = extra_class;
1247 rc->interfaces [j] = remote_class->interfaces [i];
1250 rc->interfaces [j] = extra_class;
1252 // Replace the old class. The interface array is the same
1253 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * remote_class->interface_count);
1254 rc->proxy_class = extra_class;
1255 rc->interface_count = remote_class->interface_count;
1256 if (rc->interface_count > 0)
1257 memcpy (rc->interfaces, remote_class->interfaces, rc->interface_count * sizeof (MonoClass*));
1260 rc->default_vtable = NULL;
1261 rc->xdomain_vtable = NULL;
1262 rc->proxy_class_name = remote_class->proxy_class_name;
1264 g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
1270 mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp)
1272 mono_domain_lock (domain);
1273 if (rp->target_domain_id != -1) {
1274 if (remote_class->xdomain_vtable == NULL)
1275 remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN);
1276 mono_domain_unlock (domain);
1277 return remote_class->xdomain_vtable;
1279 if (remote_class->default_vtable == NULL) {
1282 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
1283 klass = mono_class_from_mono_type (type);
1284 if ((klass->is_com_object || klass == mono_defaults.com_object_class) && !mono_class_vtable (mono_domain_get (), klass)->remote)
1285 remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP);
1287 remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
1290 mono_domain_unlock (domain);
1291 return remote_class->default_vtable;
1295 * mono_upgrade_remote_class:
1296 * @domain: the application domain
1297 * @tproxy: the proxy whose remote class has to be upgraded.
1298 * @klass: class to which the remote class can be casted.
1300 * Updates the vtable of the remote class by adding the necessary method slots
1301 * and interface offsets so it can be safely casted to klass. klass can be a
1302 * class or an interface.
1305 mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass)
1307 MonoTransparentProxy *tproxy;
1308 MonoRemoteClass *remote_class;
1309 gboolean redo_vtable;
1311 mono_domain_lock (domain);
1313 tproxy = (MonoTransparentProxy*) proxy_object;
1314 remote_class = tproxy->remote_class;
1316 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1319 for (i = 0; i < remote_class->interface_count && redo_vtable; i++)
1320 if (remote_class->interfaces [i] == klass)
1321 redo_vtable = FALSE;
1324 redo_vtable = (remote_class->proxy_class != klass);
1328 tproxy->remote_class = clone_remote_class (domain, remote_class, klass);
1329 proxy_object->vtable = mono_remote_class_vtable (domain, tproxy->remote_class, tproxy->rp);
1332 mono_domain_unlock (domain);
1337 * mono_object_get_virtual_method:
1338 * @obj: object to operate on.
1341 * Retrieves the MonoMethod that would be called on obj if obj is passed as
1342 * the instance of a callvirt of method.
1345 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method)
1348 MonoMethod **vtable;
1350 MonoMethod *res = NULL;
1352 klass = mono_object_class (obj);
1353 if (klass == mono_defaults.transparent_proxy_class) {
1354 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
1360 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
1363 mono_class_setup_vtable (klass);
1364 vtable = klass->vtable;
1366 /* check method->slot is a valid index: perform isinstance? */
1367 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1369 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
1371 if (method->slot != -1)
1372 res = vtable [method->slot];
1376 if (!res) res = method; /* It may be an interface or abstract class method */
1377 res = mono_marshal_get_remoting_invoke (res);
1386 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1388 g_error ("runtime invoke called on uninitialized runtime");
1392 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
1395 * mono_runtime_invoke:
1396 * @method: method to invoke
1397 * @obJ: object instance
1398 * @params: arguments to the method
1399 * @exc: exception information.
1401 * Invokes the method represented by @method on the object @obj.
1403 * obj is the 'this' pointer, it should be NULL for static
1404 * methods, a MonoObject* for object instances and a pointer to
1405 * the value type for value types.
1407 * The params array contains the arguments to the method with the
1408 * same convention: MonoObject* pointers for object instances and
1409 * pointers to the value type otherwise.
1411 * From unmanaged code you'll usually use the
1412 * mono_runtime_invoke() variant.
1414 * Note that this function doesn't handle virtual methods for
1415 * you, it will exec the exact method you pass: we still need to
1416 * expose a function to lookup the derived class implementation
1417 * of a virtual method (there are examples of this in the code,
1420 * You can pass NULL as the exc argument if you don't want to
1421 * catch exceptions, otherwise, *exc will be set to the exception
1422 * thrown, if any. if an exception is thrown, you can't use the
1423 * MonoObject* result from the function.
1425 * If the method returns a value type, it is boxed in an object
1429 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1431 return default_mono_runtime_invoke (method, obj, params, exc);
1435 set_value (MonoType *type, void *dest, void *value, int deref_pointer)
1439 gpointer *p = (gpointer*)dest;
1446 case MONO_TYPE_BOOLEAN:
1448 case MONO_TYPE_U1: {
1449 guint8 *p = (guint8*)dest;
1450 *p = value ? *(guint8*)value : 0;
1455 case MONO_TYPE_CHAR: {
1456 guint16 *p = (guint16*)dest;
1457 *p = value ? *(guint16*)value : 0;
1460 #if SIZEOF_VOID_P == 4
1465 case MONO_TYPE_U4: {
1466 gint32 *p = (gint32*)dest;
1467 *p = value ? *(gint32*)value : 0;
1470 #if SIZEOF_VOID_P == 8
1475 case MONO_TYPE_U8: {
1476 gint64 *p = (gint64*)dest;
1477 *p = value ? *(gint64*)value : 0;
1480 case MONO_TYPE_R4: {
1481 float *p = (float*)dest;
1482 *p = value ? *(float*)value : 0;
1485 case MONO_TYPE_R8: {
1486 double *p = (double*)dest;
1487 *p = value ? *(double*)value : 0;
1490 case MONO_TYPE_STRING:
1491 case MONO_TYPE_SZARRAY:
1492 case MONO_TYPE_CLASS:
1493 case MONO_TYPE_OBJECT:
1494 case MONO_TYPE_ARRAY:
1495 mono_gc_wbarrier_generic_store (dest, deref_pointer? *(gpointer*)value: value);
1497 case MONO_TYPE_FNPTR:
1498 case MONO_TYPE_PTR: {
1499 gpointer *p = (gpointer*)dest;
1500 *p = deref_pointer? *(gpointer*)value: value;
1503 case MONO_TYPE_VALUETYPE:
1504 if (type->data.klass->enumtype) {
1505 t = type->data.klass->enum_basetype->type;
1509 size = mono_class_value_size (mono_class_from_mono_type (type), NULL);
1511 memset (dest, 0, size);
1513 memcpy (dest, value, size);
1516 case MONO_TYPE_GENERICINST:
1517 t = type->data.generic_class->container_class->byval_arg.type;
1520 g_warning ("got type %x", type->type);
1521 g_assert_not_reached ();
1526 * mono_field_set_value:
1527 * @obj: Instance object
1528 * @field: MonoClassField describing the field to set
1529 * @value: The value to be set
1531 * Sets the value of the field described by @field in the object instance @obj
1532 * to the value passed in @value.
1534 * The value must be on the native format of the field type.
1537 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1541 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1543 dest = (char*)obj + field->offset;
1544 set_value (field->type, dest, value, FALSE);
1548 * mono_field_static_set_value:
1549 * @field: MonoClassField describing the field to set
1550 * @value: The value to be set
1552 * Sets the value of the static field described by @field
1553 * to the value passed in @value.
1555 * The value must be on the native format of the field type.
1558 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1562 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1563 /* you cant set a constant! */
1564 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
1566 dest = (char*)vt->data + field->offset;
1567 set_value (field->type, dest, value, FALSE);
1570 /* Used by the debugger */
1572 mono_vtable_get_static_field_data (MonoVTable *vt)
1578 * mono_field_get_value:
1579 * @obj: Object instance
1580 * @field: MonoClassField describing the field to fetch information from
1581 * @value: pointer to the location where the value will be stored
1583 * Use this routine to get the value of the field @field in the object
1586 * The pointer provided by value must be of the field type, for reference
1587 * types this is a MonoObject*, for value types its the actual pointer to
1592 * mono_field_get_value (obj, int_field, &i);
1595 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1599 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1601 src = (char*)obj + field->offset;
1602 set_value (field->type, value, src, TRUE);
1606 * mono_field_get_value_object:
1607 * @domain: domain where the object will be created (if boxing)
1608 * @field: MonoClassField describing the field to fetch information from
1609 * @obj: The object instance for the field.
1611 * Returns: a new MonoObject with the value from the given field. If the
1612 * field represents a value type, the value is boxed.
1616 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1620 MonoVTable *vtable = NULL;
1622 gboolean is_static = FALSE;
1623 gboolean is_ref = FALSE;
1625 switch (field->type->type) {
1626 case MONO_TYPE_STRING:
1627 case MONO_TYPE_OBJECT:
1628 case MONO_TYPE_CLASS:
1629 case MONO_TYPE_ARRAY:
1630 case MONO_TYPE_SZARRAY:
1635 case MONO_TYPE_BOOLEAN:
1638 case MONO_TYPE_CHAR:
1647 case MONO_TYPE_VALUETYPE:
1648 is_ref = field->type->byref;
1650 case MONO_TYPE_GENERICINST:
1651 is_ref = !field->type->data.generic_class->container_class->valuetype;
1654 g_error ("type 0x%x not handled in "
1655 "mono_field_get_value_object", field->type->type);
1659 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1661 vtable = mono_class_vtable (domain, field->parent);
1662 if (!vtable->initialized)
1663 mono_runtime_class_init (vtable);
1668 mono_field_static_get_value (vtable, field, &o);
1670 mono_field_get_value (obj, field, &o);
1675 /* boxed value type */
1676 klass = mono_class_from_mono_type (field->type);
1677 o = mono_object_new (domain, klass);
1678 v = ((gchar *) o) + sizeof (MonoObject);
1680 mono_field_static_get_value (vtable, field, v);
1682 mono_field_get_value (obj, field, v);
1689 mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const char *blob, void *value)
1692 const char *p = blob;
1693 mono_metadata_decode_blob_size (p, &p);
1696 case MONO_TYPE_BOOLEAN:
1699 *(guint8 *) value = *p;
1701 case MONO_TYPE_CHAR:
1704 *(guint16*) value = read16 (p);
1708 *(guint32*) value = read32 (p);
1712 *(guint64*) value = read64 (p);
1715 readr4 (p, (float*) value);
1718 readr8 (p, (double*) value);
1720 case MONO_TYPE_STRING:
1721 *(gpointer*) value = mono_ldstr_metdata_sig (domain, blob);
1723 case MONO_TYPE_CLASS:
1724 *(gpointer*) value = NULL;
1728 g_warning ("type 0x%02x should not be in constant table", type);
1734 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
1736 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
1737 mono_get_constant_value_from_blob (domain, field->def_type, field->data, value);
1741 * mono_field_static_get_value:
1742 * @vt: vtable to the object
1743 * @field: MonoClassField describing the field to fetch information from
1744 * @value: where the value is returned
1746 * Use this routine to get the value of the static field @field value.
1748 * The pointer provided by value must be of the field type, for reference
1749 * types this is a MonoObject*, for value types its the actual pointer to
1754 * mono_field_static_get_value (vt, int_field, &i);
1757 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1761 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1763 if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
1764 get_default_field_value (vt->domain, field, value);
1768 src = (char*)vt->data + field->offset;
1769 set_value (field->type, value, src, TRUE);
1773 * mono_property_set_value:
1774 * @prop: MonoProperty to set
1775 * @obj: instance object on which to act
1776 * @params: parameters to pass to the propery
1777 * @exc: optional exception
1779 * Invokes the property's set method with the given arguments on the
1780 * object instance obj (or NULL for static properties).
1782 * You can pass NULL as the exc argument if you don't want to
1783 * catch exceptions, otherwise, *exc will be set to the exception
1784 * thrown, if any. if an exception is thrown, you can't use the
1785 * MonoObject* result from the function.
1788 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1790 default_mono_runtime_invoke (prop->set, obj, params, exc);
1794 * mono_property_get_value:
1795 * @prop: MonoProperty to fetch
1796 * @obj: instance object on which to act
1797 * @params: parameters to pass to the propery
1798 * @exc: optional exception
1800 * Invokes the property's get method with the given arguments on the
1801 * object instance obj (or NULL for static properties).
1803 * You can pass NULL as the exc argument if you don't want to
1804 * catch exceptions, otherwise, *exc will be set to the exception
1805 * thrown, if any. if an exception is thrown, you can't use the
1806 * MonoObject* result from the function.
1808 * Returns: the value from invoking the get method on the property.
1811 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1813 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1817 * mono_nullable_init:
1818 * @buf: The nullable structure to initialize.
1819 * @value: the value to initialize from
1820 * @klass: the type for the object
1822 * Initialize the nullable structure pointed to by @buf from @value which
1823 * should be a boxed value type. The size of @buf should be able to hold
1824 * as much data as the @klass->instance_size (which is the number of bytes
1825 * that will be copies).
1827 * Since Nullables have variable structure, we can not define a C
1828 * structure for them.
1831 mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
1833 MonoClass *param_class = klass->cast_class;
1835 g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
1836 g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
1838 *(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject)) = value ? 1 : 0;
1840 memcpy (buf + klass->fields [0].offset - sizeof (MonoObject), mono_object_unbox (value), mono_class_value_size (param_class, NULL));
1842 memset (buf + klass->fields [0].offset - sizeof (MonoObject), 0, mono_class_value_size (param_class, NULL));
1846 * mono_nullable_box:
1847 * @buf: The buffer representing the data to be boxed
1848 * @klass: the type to box it as.
1850 * Creates a boxed vtype or NULL from the Nullable structure pointed to by
1854 mono_nullable_box (guint8 *buf, MonoClass *klass)
1856 MonoClass *param_class = klass->cast_class;
1858 g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
1859 g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
1861 if (*(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject))) {
1862 MonoObject *o = mono_object_new (mono_domain_get (), param_class);
1863 memcpy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL));
1871 * mono_get_delegate_invoke:
1872 * @klass: The delegate class
1874 * Returns: the MonoMethod for the "Invoke" method in the delegate klass
1877 mono_get_delegate_invoke (MonoClass *klass)
1881 im = mono_class_get_method_from_name (klass, "Invoke", -1);
1888 * mono_runtime_delegate_invoke:
1889 * @delegate: pointer to a delegate object.
1890 * @params: parameters for the delegate.
1891 * @exc: Pointer to the exception result.
1893 * Invokes the delegate method @delegate with the parameters provided.
1895 * You can pass NULL as the exc argument if you don't want to
1896 * catch exceptions, otherwise, *exc will be set to the exception
1897 * thrown, if any. if an exception is thrown, you can't use the
1898 * MonoObject* result from the function.
1901 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1905 im = mono_get_delegate_invoke (delegate->vtable->klass);
1908 return mono_runtime_invoke (im, delegate, params, exc);
1911 static char **main_args = NULL;
1912 static int num_main_args;
1915 * mono_runtime_get_main_args:
1917 * Returns: a MonoArray with the arguments passed to the main program
1920 mono_runtime_get_main_args (void)
1924 MonoDomain *domain = mono_domain_get ();
1929 res = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, num_main_args);
1931 for (i = 0; i < num_main_args; ++i)
1932 mono_array_setref (res, i, mono_string_new (domain, main_args [i]));
1938 fire_process_exit_event (void)
1940 MonoClassField *field;
1941 MonoDomain *domain = mono_domain_get ();
1943 MonoObject *delegate, *exc;
1945 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1948 if (domain != mono_get_root_domain ())
1951 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1952 if (delegate == NULL)
1957 mono_runtime_delegate_invoke (delegate, pa, &exc);
1961 * mono_runtime_run_main:
1962 * @method: the method to start the application with (usually Main)
1963 * @argc: number of arguments from the command line
1964 * @argv: array of strings from the command line
1965 * @exc: excetption results
1967 * Execute a standard Main() method (argc/argv contains the
1968 * executable name). This method also sets the command line argument value
1969 * needed by System.Environment.
1974 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1978 MonoArray *args = NULL;
1979 MonoDomain *domain = mono_domain_get ();
1980 gchar *utf8_fullpath;
1983 g_assert (method != NULL);
1985 mono_thread_set_main (mono_thread_current ());
1987 main_args = g_new0 (char*, argc);
1988 num_main_args = argc;
1990 if (!g_path_is_absolute (argv [0])) {
1991 gchar *basename = g_path_get_basename (argv [0]);
1992 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1996 utf8_fullpath = mono_utf8_from_external (fullpath);
1997 if(utf8_fullpath == NULL) {
1998 /* Printing the arg text will cause glib to
1999 * whinge about "Invalid UTF-8", but at least
2000 * its relevant, and shows the problem text
2003 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
2004 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
2011 utf8_fullpath = mono_utf8_from_external (argv[0]);
2012 if(utf8_fullpath == NULL) {
2013 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
2014 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
2019 main_args [0] = utf8_fullpath;
2021 for (i = 1; i < argc; ++i) {
2024 utf8_arg=mono_utf8_from_external (argv[i]);
2025 if(utf8_arg==NULL) {
2026 /* Ditto the comment about Invalid UTF-8 here */
2027 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
2028 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
2032 main_args [i] = utf8_arg;
2036 if (mono_method_signature (method)->param_count) {
2037 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
2038 for (i = 0; i < argc; ++i) {
2039 /* The encodings should all work, given that
2040 * we've checked all these args for the
2043 gchar *str = mono_utf8_from_external (argv [i]);
2044 MonoString *arg = mono_string_new (domain, str);
2045 mono_array_setref (args, i, arg);
2049 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
2052 mono_assembly_set_main (method->klass->image->assembly);
2054 result = mono_runtime_exec_main (method, args, exc);
2055 fire_process_exit_event ();
2059 /* Used in mono_unhandled_exception */
2061 create_unhandled_exception_eventargs (MonoObject *exc)
2065 MonoMethod *method = NULL;
2066 MonoBoolean is_terminating = TRUE;
2069 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
2072 mono_class_init (klass);
2074 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
2075 method = mono_class_get_method_from_name_flags (klass, ".ctor", 2, METHOD_ATTRIBUTE_PUBLIC);
2079 args [1] = &is_terminating;
2081 obj = mono_object_new (mono_domain_get (), klass);
2082 mono_runtime_invoke (method, obj, args, NULL);
2088 * mono_unhandled_exception:
2089 * @exc: exception thrown
2091 * This is a VM internal routine.
2093 * We call this function when we detect an unhandled exception
2094 * in the default domain.
2096 * It invokes the * UnhandledException event in AppDomain or prints
2097 * a warning to the console
2100 mono_unhandled_exception (MonoObject *exc)
2102 MonoDomain *domain = mono_domain_get ();
2103 MonoClassField *field;
2104 MonoObject *delegate;
2106 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
2107 "UnhandledException");
2110 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
2111 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
2113 /* set exitcode only in the main thread */
2114 if (mono_thread_current () == main_thread)
2115 mono_environment_exitcode_set (1);
2116 if (domain != mono_get_root_domain () || !delegate) {
2117 mono_print_unhandled_exception (exc);
2119 MonoObject *e = NULL;
2122 pa [0] = domain->domain;
2123 pa [1] = create_unhandled_exception_eventargs (exc);
2124 mono_runtime_delegate_invoke (delegate, pa, &e);
2127 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
2128 g_warning ("exception inside UnhandledException handler: %s\n", msg);
2136 * Launch a new thread to execute a function
2138 * main_func is called back from the thread with main_args as the
2139 * parameter. The callback function is expected to start Main()
2140 * eventually. This function then waits for all managed threads to
2142 * It is not necesseray anymore to execute managed code in a subthread,
2143 * so this function should not be used anymore by default: just
2144 * execute the code and then call mono_thread_manage ().
2147 mono_runtime_exec_managed_code (MonoDomain *domain,
2148 MonoMainThreadFunc main_func,
2151 mono_thread_create (domain, main_func, main_args);
2153 mono_thread_manage ();
2157 * Execute a standard Main() method (args doesn't contain the
2161 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
2171 domain = mono_object_domain (args);
2172 if (!domain->entry_assembly) {
2174 MonoAssembly *assembly;
2176 assembly = method->klass->image->assembly;
2177 domain->entry_assembly = assembly;
2178 MONO_OBJECT_SETREF (domain->setup, application_base, mono_string_new (domain, assembly->basedir));
2180 str = g_strconcat (assembly->image->name, ".config", NULL);
2181 MONO_OBJECT_SETREF (domain->setup, configuration_file, mono_string_new (domain, str));
2185 /* FIXME: check signature of method */
2186 if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
2188 res = mono_runtime_invoke (method, NULL, pa, exc);
2190 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
2194 mono_environment_exitcode_set (rval);
2196 mono_runtime_invoke (method, NULL, pa, exc);
2200 /* If the return type of Main is void, only
2201 * set the exitcode if an exception was thrown
2202 * (we don't want to blow away an
2203 * explicitly-set exit code)
2206 mono_environment_exitcode_set (rval);
2214 * mono_install_runtime_invoke:
2215 * @func: Function to install
2217 * This is a VM internal routine
2220 mono_install_runtime_invoke (MonoInvokeFunc func)
2222 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
2226 * mono_runtime_invoke_array:
2227 * @method: method to invoke
2228 * @obJ: object instance
2229 * @params: arguments to the method
2230 * @exc: exception information.
2232 * Invokes the method represented by @method on the object @obj.
2234 * obj is the 'this' pointer, it should be NULL for static
2235 * methods, a MonoObject* for object instances and a pointer to
2236 * the value type for value types.
2238 * The params array contains the arguments to the method with the
2239 * same convention: MonoObject* pointers for object instances and
2240 * pointers to the value type otherwise. The _invoke_array
2241 * variant takes a C# object[] as the params argument (MonoArray
2242 * *params): in this case the value types are boxed inside the
2243 * respective reference representation.
2245 * From unmanaged code you'll usually use the
2246 * mono_runtime_invoke() variant.
2248 * Note that this function doesn't handle virtual methods for
2249 * you, it will exec the exact method you pass: we still need to
2250 * expose a function to lookup the derived class implementation
2251 * of a virtual method (there are examples of this in the code,
2254 * You can pass NULL as the exc argument if you don't want to
2255 * catch exceptions, otherwise, *exc will be set to the exception
2256 * thrown, if any. if an exception is thrown, you can't use the
2257 * MonoObject* result from the function.
2259 * If the method returns a value type, it is boxed in an object
2263 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
2266 MonoMethodSignature *sig = mono_method_signature (method);
2267 gpointer *pa = NULL;
2270 if (NULL != params) {
2271 pa = alloca (sizeof (gpointer) * mono_array_length (params));
2272 for (i = 0; i < mono_array_length (params); i++) {
2273 MonoType *t = sig->params [i];
2279 case MONO_TYPE_BOOLEAN:
2282 case MONO_TYPE_CHAR:
2291 case MONO_TYPE_VALUETYPE:
2292 if (t->type == MONO_TYPE_VALUETYPE && mono_class_is_nullable (mono_class_from_mono_type (sig->params [i]))) {
2295 g_assert_not_reached ();
2296 /* The runtime invoke wrapper needs the original boxed vtype */
2297 pa [i] = (char *)(((gpointer *)params->vector)[i]);
2299 /* MS seems to create the objects if a null is passed in */
2300 if (!((gpointer *)params->vector)[i])
2301 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
2305 * We can't pass the unboxed vtype byref to the callee, since
2306 * that would mean the callee would be able to modify boxed
2307 * primitive types. So we (and MS) make a copy of the boxed
2308 * object, pass that to the callee, and replace the original
2309 * boxed object in the arg array with the copy.
2311 MonoObject *orig = mono_array_get (params, MonoObject*, i);
2312 MonoObject *copy = mono_value_box (mono_domain_get (), orig->vtable->klass, mono_object_unbox (orig));
2313 mono_array_setref (params, i, copy);
2316 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
2319 case MONO_TYPE_STRING:
2320 case MONO_TYPE_OBJECT:
2321 case MONO_TYPE_CLASS:
2322 case MONO_TYPE_ARRAY:
2323 case MONO_TYPE_SZARRAY:
2325 pa [i] = &(((gpointer *)params->vector)[i]);
2327 pa [i] = (char *)(((gpointer *)params->vector)[i]);
2329 case MONO_TYPE_GENERICINST:
2330 t = &t->data.generic_class->container_class->byval_arg;
2333 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
2338 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
2341 if (mono_class_is_nullable (method->klass)) {
2342 /* Need to create a boxed vtype instead */
2348 return mono_value_box (mono_domain_get (), method->klass->cast_class, pa [0]);
2352 obj = mono_object_new (mono_domain_get (), method->klass);
2353 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
2354 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
2356 if (method->klass->valuetype)
2357 o = mono_object_unbox (obj);
2361 else if (method->klass->valuetype)
2362 obj = mono_value_box (mono_domain_get (), method->klass, obj);
2364 mono_runtime_invoke (method, o, pa, exc);
2367 /* obj must be already unboxed if needed */
2368 return mono_runtime_invoke (method, obj, pa, exc);
2373 arith_overflow (void)
2375 mono_raise_exception (mono_get_exception_overflow ());
2379 * mono_object_allocate:
2380 * @size: number of bytes to allocate
2382 * This is a very simplistic routine until we have our GC-aware
2385 * Returns: an allocated object of size @size, or NULL on failure.
2387 static inline void *
2388 mono_object_allocate (size_t size, MonoVTable *vtable)
2391 mono_stats.new_object_count++;
2392 ALLOC_OBJECT (o, vtable, size);
2398 * mono_object_allocate_ptrfree:
2399 * @size: number of bytes to allocate
2401 * Note that the memory allocated is not zeroed.
2402 * Returns: an allocated object of size @size, or NULL on failure.
2404 static inline void *
2405 mono_object_allocate_ptrfree (size_t size, MonoVTable *vtable)
2408 mono_stats.new_object_count++;
2409 ALLOC_PTRFREE (o, vtable, size);
2413 static inline void *
2414 mono_object_allocate_spec (size_t size, MonoVTable *vtable)
2417 ALLOC_TYPED (o, size, vtable);
2418 mono_stats.new_object_count++;
2425 * @klass: the class of the object that we want to create
2427 * Returns: a newly created object whose definition is
2428 * looked up using @klass. This will not invoke any constructors,
2429 * so the consumer of this routine has to invoke any constructors on
2430 * its own to initialize the object.
2433 mono_object_new (MonoDomain *domain, MonoClass *klass)
2435 MONO_ARCH_SAVE_REGS;
2436 return mono_object_new_specific (mono_class_vtable (domain, klass));
2440 * mono_object_new_specific:
2441 * @vtable: the vtable of the object that we want to create
2443 * Returns: A newly created object with class and domain specified
2447 mono_object_new_specific (MonoVTable *vtable)
2451 MONO_ARCH_SAVE_REGS;
2453 /* check for is_com_object for COM Interop */
2454 if (vtable->remote || vtable->klass->is_com_object)
2457 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
2460 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
2463 mono_class_init (klass);
2465 im = mono_class_get_method_from_name (klass, "CreateProxyForType", 1);
2467 vtable->domain->create_proxy_for_type_method = im;
2470 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
2472 o = mono_runtime_invoke (im, NULL, pa, NULL);
2473 if (o != NULL) return o;
2476 return mono_object_new_alloc_specific (vtable);
2480 mono_object_new_alloc_specific (MonoVTable *vtable)
2484 if (!vtable->klass->has_references) {
2485 o = mono_object_new_ptrfree (vtable);
2486 } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2487 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
2489 /* printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2490 o = mono_object_allocate (vtable->klass->instance_size, vtable);
2492 if (vtable->klass->has_finalize)
2493 mono_object_register_finalizer (o);
2495 mono_profiler_allocation (o, vtable->klass);
2500 mono_object_new_fast (MonoVTable *vtable)
2503 ALLOC_TYPED (o, vtable->klass->instance_size, vtable);
2508 mono_object_new_ptrfree (MonoVTable *vtable)
2511 ALLOC_PTRFREE (obj, vtable, vtable->klass->instance_size);
2512 #if NEED_TO_ZERO_PTRFREE
2513 /* an inline memset is much faster for the common vcase of small objects
2514 * note we assume the allocated size is a multiple of sizeof (void*).
2516 if (vtable->klass->instance_size < 128) {
2518 end = (gpointer*)((char*)obj + vtable->klass->instance_size);
2519 p = (gpointer*)((char*)obj + sizeof (MonoObject));
2525 memset ((char*)obj + sizeof (MonoObject), 0, vtable->klass->instance_size - sizeof (MonoObject));
2532 mono_object_new_ptrfree_box (MonoVTable *vtable)
2535 ALLOC_PTRFREE (obj, vtable, vtable->klass->instance_size);
2536 /* the object will be boxed right away, no need to memzero it */
2541 * mono_class_get_allocation_ftn:
2543 * @for_box: the object will be used for boxing
2544 * @pass_size_in_words:
2546 * Return the allocation function appropriate for the given class.
2550 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *pass_size_in_words)
2552 *pass_size_in_words = FALSE;
2554 if (vtable->klass->has_finalize || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
2555 return mono_object_new_specific;
2557 if (!vtable->klass->has_references) {
2558 //g_print ("ptrfree for %s.%s\n", vtable->klass->name_space, vtable->klass->name);
2560 return mono_object_new_ptrfree_box;
2561 return mono_object_new_ptrfree;
2564 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2566 return mono_object_new_fast;
2569 * FIXME: This is actually slower than mono_object_new_fast, because
2570 * of the overhead of parameter passing.
2573 *pass_size_in_words = TRUE;
2574 #ifdef GC_REDIRECT_TO_LOCAL
2575 return GC_local_gcj_fast_malloc;
2577 return GC_gcj_fast_malloc;
2582 return mono_object_new_specific;
2586 * mono_object_new_from_token:
2587 * @image: Context where the type_token is hosted
2588 * @token: a token of the type that we want to create
2590 * Returns: A newly created object whose definition is
2591 * looked up using @token in the @image image
2594 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
2598 class = mono_class_get (image, token);
2600 return mono_object_new (domain, class);
2605 * mono_object_clone:
2606 * @obj: the object to clone
2608 * Returns: A newly created object who is a shallow copy of @obj
2611 mono_object_clone (MonoObject *obj)
2616 size = obj->vtable->klass->instance_size;
2617 o = mono_object_allocate (size, obj->vtable);
2618 /* do not copy the sync state */
2619 memcpy ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
2621 mono_profiler_allocation (o, obj->vtable->klass);
2623 if (obj->vtable->klass->has_finalize)
2624 mono_object_register_finalizer (o);
2629 * mono_array_full_copy:
2630 * @src: source array to copy
2631 * @dest: destination array
2633 * Copies the content of one array to another with exactly the same type and size.
2636 mono_array_full_copy (MonoArray *src, MonoArray *dest)
2639 MonoClass *klass = src->obj.vtable->klass;
2641 MONO_ARCH_SAVE_REGS;
2643 g_assert (klass == dest->obj.vtable->klass);
2645 size = mono_array_length (src);
2646 g_assert (size == mono_array_length (dest));
2647 size *= mono_array_element_size (klass);
2648 memcpy (&dest->vector, &src->vector, size);
2652 * mono_array_clone_in_domain:
2653 * @domain: the domain in which the array will be cloned into
2654 * @array: the array to clone
2656 * This routine returns a copy of the array that is hosted on the
2657 * specified MonoDomain.
2660 mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
2665 MonoClass *klass = array->obj.vtable->klass;
2667 MONO_ARCH_SAVE_REGS;
2669 if (array->bounds == NULL) {
2670 size = mono_array_length (array);
2671 o = mono_array_new_full (domain, klass, &size, NULL);
2673 size *= mono_array_element_size (klass);
2674 memcpy (&o->vector, &array->vector, size);
2678 sizes = alloca (klass->rank * sizeof(guint32) * 2);
2679 size = mono_array_element_size (klass);
2680 for (i = 0; i < klass->rank; ++i) {
2681 sizes [i] = array->bounds [i].length;
2682 size *= array->bounds [i].length;
2683 sizes [i + klass->rank] = array->bounds [i].lower_bound;
2685 o = mono_array_new_full (domain, klass, sizes, sizes + klass->rank);
2686 memcpy (&o->vector, &array->vector, size);
2693 * @array: the array to clone
2695 * Returns: A newly created array who is a shallow copy of @array
2698 mono_array_clone (MonoArray *array)
2700 return mono_array_clone_in_domain (((MonoObject *)array)->vtable->domain, array);
2703 /* helper macros to check for overflow when calculating the size of arrays */
2704 #define MYGUINT32_MAX 4294967295U
2705 #define CHECK_ADD_OVERFLOW_UN(a,b) \
2706 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
2707 #define CHECK_MUL_OVERFLOW_UN(a,b) \
2708 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
2709 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
2712 * mono_array_new_full:
2713 * @domain: domain where the object is created
2714 * @array_class: array class
2715 * @lengths: lengths for each dimension in the array
2716 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
2718 * This routine creates a new array objects with the given dimensions,
2719 * lower bounds and type.
2722 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
2723 guint32 *lengths, guint32 *lower_bounds)
2725 guint32 byte_len, len, bounds_size;
2731 if (!array_class->inited)
2732 mono_class_init (array_class);
2734 byte_len = mono_array_element_size (array_class);
2737 /* A single dimensional array with a 0 lower bound is the same as an szarray */
2738 if (array_class->rank == 1 && ((array_class->byval_arg.type == MONO_TYPE_SZARRAY) || (lower_bounds && lower_bounds [0] == 0))) {
2744 bounds_size = sizeof (MonoArrayBounds) * array_class->rank;
2746 for (i = 0; i < array_class->rank; ++i) {
2747 if ((int) lengths [i] < 0)
2749 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
2750 mono_gc_out_of_memory (MYGUINT32_MAX);
2755 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
2756 mono_gc_out_of_memory (MYGUINT32_MAX);
2758 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2759 mono_gc_out_of_memory (MYGUINT32_MAX);
2760 byte_len += sizeof (MonoArray);
2763 if (CHECK_ADD_OVERFLOW_UN (byte_len, 3))
2764 mono_gc_out_of_memory (MYGUINT32_MAX);
2765 byte_len = (byte_len + 3) & ~3;
2766 if (CHECK_ADD_OVERFLOW_UN (byte_len, bounds_size))
2767 mono_gc_out_of_memory (MYGUINT32_MAX);
2768 byte_len += bounds_size;
2771 * Following three lines almost taken from mono_object_new ():
2772 * they need to be kept in sync.
2774 vtable = mono_class_vtable (domain, array_class);
2775 if (!array_class->has_references) {
2776 o = mono_object_allocate_ptrfree (byte_len, vtable);
2777 #if NEED_TO_ZERO_PTRFREE
2778 memset ((char*)o + sizeof (MonoObject), 0, byte_len - sizeof (MonoObject));
2780 } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2781 o = mono_object_allocate_spec (byte_len, vtable);
2783 o = mono_object_allocate (byte_len, vtable);
2786 array = (MonoArray*)o;
2787 array->max_length = len;
2790 MonoArrayBounds *bounds = (MonoArrayBounds*)((char*)array + byte_len - bounds_size);
2791 array->bounds = bounds;
2792 for (i = 0; i < array_class->rank; ++i) {
2793 bounds [i].length = lengths [i];
2795 bounds [i].lower_bound = lower_bounds [i];
2799 mono_profiler_allocation (o, array_class);
2806 * @domain: domain where the object is created
2807 * @eclass: element class
2808 * @n: number of array elements
2810 * This routine creates a new szarray with @n elements of type @eclass.
2813 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
2817 MONO_ARCH_SAVE_REGS;
2819 ac = mono_array_class_get (eclass, 1);
2820 g_assert (ac != NULL);
2822 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
2826 * mono_array_new_specific:
2827 * @vtable: a vtable in the appropriate domain for an initialized class
2828 * @n: number of array elements
2830 * This routine is a fast alternative to mono_array_new() for code which
2831 * can be sure about the domain it operates in.
2834 mono_array_new_specific (MonoVTable *vtable, guint32 n)
2838 guint32 byte_len, elem_size;
2840 MONO_ARCH_SAVE_REGS;
2845 elem_size = mono_array_element_size (vtable->klass);
2846 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
2847 mono_gc_out_of_memory (MYGUINT32_MAX);
2848 byte_len = n * elem_size;
2849 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2850 mono_gc_out_of_memory (MYGUINT32_MAX);
2851 byte_len += sizeof (MonoArray);
2852 if (!vtable->klass->has_references) {
2853 o = mono_object_allocate_ptrfree (byte_len, vtable);
2854 #if NEED_TO_ZERO_PTRFREE
2855 memset ((char*)o + sizeof (MonoObject), 0, byte_len - sizeof (MonoObject));
2857 } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2858 o = mono_object_allocate_spec (byte_len, vtable);
2860 /* printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2861 o = mono_object_allocate (byte_len, vtable);
2864 ao = (MonoArray *)o;
2867 mono_profiler_allocation (o, vtable->klass);
2873 * mono_string_new_utf16:
2874 * @text: a pointer to an utf16 string
2875 * @len: the length of the string
2877 * Returns: A newly created string object which contains @text.
2880 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
2884 s = mono_string_new_size (domain, len);
2885 g_assert (s != NULL);
2887 memcpy (mono_string_chars (s), text, len * 2);
2893 * mono_string_new_size:
2894 * @text: a pointer to an utf16 string
2895 * @len: the length of the string
2897 * Returns: A newly created string object of @len
2900 mono_string_new_size (MonoDomain *domain, gint32 len)
2904 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2906 /* overflow ? can't fit it, can't allocate it! */
2908 mono_gc_out_of_memory (-1);
2910 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2912 s = mono_object_allocate_ptrfree (size, vtable);
2915 #if NEED_TO_ZERO_PTRFREE
2918 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2924 * mono_string_new_len:
2925 * @text: a pointer to an utf8 string
2926 * @length: number of bytes in @text to consider
2928 * Returns: A newly created string object which contains @text.
2931 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2933 GError *error = NULL;
2934 MonoString *o = NULL;
2936 glong items_written;
2938 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2941 o = mono_string_new_utf16 (domain, ut, items_written);
2943 g_error_free (error);
2952 * @text: a pointer to an utf8 string
2954 * Returns: A newly created string object which contains @text.
2957 mono_string_new (MonoDomain *domain, const char *text)
2959 GError *error = NULL;
2960 MonoString *o = NULL;
2962 glong items_written;
2967 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2970 o = mono_string_new_utf16 (domain, ut, items_written);
2972 g_error_free (error);
2980 * mono_string_new_wrapper:
2981 * @text: pointer to utf8 characters.
2983 * Helper function to create a string object from @text in the current domain.
2986 mono_string_new_wrapper (const char *text)
2988 MonoDomain *domain = mono_domain_get ();
2990 MONO_ARCH_SAVE_REGS;
2993 return mono_string_new (domain, text);
3000 * @class: the class of the value
3001 * @value: a pointer to the unboxed data
3003 * Returns: A newly created object which contains @value.
3006 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
3012 g_assert (class->valuetype);
3014 vtable = mono_class_vtable (domain, class);
3015 size = mono_class_instance_size (class);
3016 res = mono_object_allocate (size, vtable);
3017 mono_profiler_allocation (res, class);
3019 size = size - sizeof (MonoObject);
3021 #if NO_UNALIGNED_ACCESS
3022 memcpy ((char *)res + sizeof (MonoObject), value, size);
3026 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
3029 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
3032 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
3035 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
3038 memcpy ((char *)res + sizeof (MonoObject), value, size);
3041 if (class->has_finalize)
3042 mono_object_register_finalizer (res);
3048 * @dest: destination pointer
3049 * @src: source pointer
3050 * @klass: a valuetype class
3052 * Copy a valuetype from @src to @dest. This function must be used
3053 * when @klass contains references fields.
3056 mono_value_copy (gpointer dest, gpointer src, MonoClass *klass)
3058 int size = mono_class_value_size (klass, NULL);
3059 mono_gc_wbarrier_value_copy (dest, src, 1, klass);
3060 memcpy (dest, src, size);
3064 * mono_value_copy_array:
3065 * @dest: destination array
3066 * @dest_idx: index in the @dest array
3067 * @src: source pointer
3068 * @count: number of items
3070 * Copy @count valuetype items from @src to @dest. This function must be used
3071 * when @klass contains references fields.
3072 * Overlap is handled.
3075 mono_value_copy_array (MonoArray *dest, int dest_idx, gpointer src, int count)
3077 int size = mono_array_element_size (dest->obj.vtable->klass);
3078 char *d = mono_array_addr_with_size (dest, size, dest_idx);
3079 mono_gc_wbarrier_value_copy (d, src, count, mono_object_class (dest)->element_class);
3080 memmove (d, src, size * count);
3084 * mono_object_get_domain:
3085 * @obj: object to query
3087 * Returns: the MonoDomain where the object is hosted
3090 mono_object_get_domain (MonoObject *obj)
3092 return mono_object_domain (obj);
3096 * mono_object_get_class:
3097 * @obj: object to query
3099 * Returns: the MonOClass of the object.
3102 mono_object_get_class (MonoObject *obj)
3104 return mono_object_class (obj);
3107 * mono_object_get_size:
3108 * @o: object to query
3110 * Returns: the size, in bytes, of @o
3113 mono_object_get_size (MonoObject* o)
3115 MonoClass* klass = mono_object_class (o);
3116 if (klass == mono_defaults.string_class) {
3117 return sizeof (MonoString) + 2 * mono_string_length ((MonoString*) o) + 2;
3118 } else if (o->vtable->rank) {
3119 MonoArray *array = (MonoArray*)o;
3120 size_t size = sizeof (MonoArray) + mono_array_element_size (klass) * mono_array_length (array);
3121 if (array->bounds) {
3124 size += sizeof (MonoArrayBounds) * o->vtable->rank;
3128 return mono_class_instance_size (klass);
3133 * mono_object_unbox:
3134 * @obj: object to unbox
3136 * Returns: a pointer to the start of the valuetype boxed in this
3139 * This method will assert if the object passed is not a valuetype.
3142 mono_object_unbox (MonoObject *obj)
3144 /* add assert for valuetypes? */
3145 g_assert (obj->vtable->klass->valuetype);
3146 return ((char*)obj) + sizeof (MonoObject);
3150 * mono_object_isinst:
3152 * @klass: a pointer to a class
3154 * Returns: @obj if @obj is derived from @klass
3157 mono_object_isinst (MonoObject *obj, MonoClass *klass)
3160 mono_class_init (klass);
3162 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
3163 return mono_object_isinst_mbyref (obj, klass);
3168 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
3172 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
3181 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
3182 if (klass->interface_id <= vt->max_interface_id) {
3183 /* the interface_offsets array is stored before the vtable */
3184 gpointer *interface_offsets = (gpointer*)vt;
3185 if (interface_offsets [- (klass->interface_id + 1)] != NULL)
3189 MonoClass *oklass = vt->klass;
3190 if ((oklass == mono_defaults.transparent_proxy_class))
3191 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
3193 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
3197 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
3199 MonoDomain *domain = mono_domain_get ();
3201 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
3202 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
3203 MonoMethod *im = NULL;
3206 im = mono_class_get_method_from_name (rpklass, "CanCastTo", -1);
3207 im = mono_object_get_virtual_method (rp, im);
3210 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
3213 res = mono_runtime_invoke (im, rp, pa, NULL);
3215 if (*(MonoBoolean *) mono_object_unbox(res)) {
3216 /* Update the vtable of the remote type, so it can safely cast to this new type */
3217 mono_upgrade_remote_class (domain, obj, klass);
3226 * mono_object_castclass_mbyref:
3228 * @klass: a pointer to a class
3230 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
3233 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
3235 if (!obj) return NULL;
3236 if (mono_object_isinst_mbyref (obj, klass)) return obj;
3238 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
3240 "InvalidCastException"));
3245 MonoDomain *orig_domain;
3251 str_lookup (MonoDomain *domain, gpointer user_data)
3253 LDStrInfo *info = user_data;
3254 if (info->res || domain == info->orig_domain)
3256 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
3262 mono_string_get_pinned (MonoString *str)
3266 size = sizeof (MonoString) + 2 * (mono_string_length (str) + 1);
3267 news = mono_gc_alloc_pinned_obj (((MonoObject*)str)->vtable, size);
3268 memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
3269 news->length = mono_string_length (str);
3274 #define mono_string_get_pinned(str) (str)
3278 mono_string_is_interned_lookup (MonoString *str, int insert)
3280 MonoGHashTable *ldstr_table;
3284 domain = ((MonoObject *)str)->vtable->domain;
3285 ldstr_table = domain->ldstr_table;
3287 if ((res = mono_g_hash_table_lookup (ldstr_table, str))) {
3292 str = mono_string_get_pinned (str);
3293 mono_g_hash_table_insert (ldstr_table, str, str);
3297 LDStrInfo ldstr_info;
3298 ldstr_info.orig_domain = domain;
3299 ldstr_info.ins = str;
3300 ldstr_info.res = NULL;
3302 mono_domain_foreach (str_lookup, &ldstr_info);
3303 if (ldstr_info.res) {
3305 * the string was already interned in some other domain:
3306 * intern it in the current one as well.
3308 mono_g_hash_table_insert (ldstr_table, str, str);
3318 * mono_string_is_interned:
3319 * @o: String to probe
3321 * Returns whether the string has been interned.
3324 mono_string_is_interned (MonoString *o)
3326 return mono_string_is_interned_lookup (o, FALSE);
3330 * mono_string_interne:
3331 * @o: String to intern
3333 * Interns the string passed.
3334 * Returns: The interned string.
3337 mono_string_intern (MonoString *str)
3339 return mono_string_is_interned_lookup (str, TRUE);
3344 * @domain: the domain where the string will be used.
3345 * @image: a metadata context
3346 * @idx: index into the user string table.
3348 * Implementation for the ldstr opcode.
3349 * Returns: a loaded string from the @image/@idx combination.
3352 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
3354 MONO_ARCH_SAVE_REGS;
3357 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
3359 return mono_ldstr_metdata_sig (domain, mono_metadata_user_string (image, idx));
3363 * mono_ldstr_metdata_sig
3364 * @domain: the domain for the string
3365 * @sig: the signature of a metadata string
3367 * Returns: a MonoString for a string stored in the metadata
3370 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
3372 const char *str = sig;
3373 MonoString *o, *interned;
3376 len2 = mono_metadata_decode_blob_size (str, &str);
3379 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
3380 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3383 guint16 *p2 = (guint16*)mono_string_chars (o);
3384 for (i = 0; i < len2; ++i) {
3385 *p2 = GUINT16_FROM_LE (*p2);
3391 if ((interned = mono_g_hash_table_lookup (domain->ldstr_table, o))) {
3393 /* o will get garbage collected */
3397 o = mono_string_get_pinned (o);
3398 mono_g_hash_table_insert (domain->ldstr_table, o, o);
3405 * mono_string_to_utf8:
3406 * @s: a System.String
3408 * Return the UTF8 representation for @s.
3409 * the resulting buffer nedds to be freed with g_free().
3412 mono_string_to_utf8 (MonoString *s)
3415 GError *error = NULL;
3421 return g_strdup ("");
3423 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
3425 MonoException *exc = mono_get_exception_argument ("string", error->message);
3426 g_error_free (error);
3427 mono_raise_exception(exc);
3434 * mono_string_to_utf16:
3437 * Return an null-terminated array of the utf-16 chars
3438 * contained in @s. The result must be freed with g_free().
3439 * This is a temporary helper until our string implementation
3440 * is reworked to always include the null terminating char.
3443 mono_string_to_utf16 (MonoString *s)
3450 as = g_malloc ((s->length * 2) + 2);
3451 as [(s->length * 2)] = '\0';
3452 as [(s->length * 2) + 1] = '\0';
3455 return (gunichar2 *)(as);
3458 memcpy (as, mono_string_chars(s), s->length * 2);
3459 return (gunichar2 *)(as);
3463 * mono_string_from_utf16:
3464 * @data: the UTF16 string (LPWSTR) to convert
3466 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString.
3468 * Returns: a MonoString.
3471 mono_string_from_utf16 (gunichar2 *data)
3473 MonoDomain *domain = mono_domain_get ();
3479 while (data [len]) len++;
3481 return mono_string_new_utf16 (domain, data, len);
3485 * mono_string_to_utf8_mp:
3486 * @s: a System.String
3488 * Same as mono_string_to_utf8, but allocate the string from a mempool.
3491 mono_string_to_utf8_mp (MonoMemPool *mp, MonoString *s)
3493 char *r = mono_string_to_utf8 (s);
3500 len = strlen (r) + 1;
3501 mp_s = mono_mempool_alloc (mp, len);
3502 memcpy (mp_s, r, len);
3510 default_ex_handler (MonoException *ex)
3512 MonoObject *o = (MonoObject*)ex;
3513 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
3517 static MonoExceptionFunc ex_handler = default_ex_handler;
3520 * mono_install_handler:
3521 * @func: exception handler
3523 * This is an internal JIT routine used to install the handler for exceptions
3527 mono_install_handler (MonoExceptionFunc func)
3529 ex_handler = func? func: default_ex_handler;
3533 * mono_raise_exception:
3534 * @ex: exception object
3536 * Signal the runtime that the exception @ex has been raised in unmanaged code.
3539 mono_raise_exception (MonoException *ex)
3542 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
3543 * that will cause gcc to omit the function epilog, causing problems when
3544 * the JIT tries to walk the stack, since the return address on the stack
3545 * will point into the next function in the executable, not this one.
3548 if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class)
3549 MONO_OBJECT_SETREF (mono_thread_current (), abort_exc, ex);
3555 * mono_wait_handle_new:
3556 * @domain: Domain where the object will be created
3557 * @handle: Handle for the wait handle
3559 * Returns: A new MonoWaitHandle created in the given domain for the given handle
3562 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
3564 MonoWaitHandle *res;
3566 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
3568 res->handle = handle;
3574 * mono_async_result_new:
3575 * @domain:domain where the object will be created.
3576 * @handle: wait handle.
3577 * @state: state to pass to AsyncResult
3578 * @data: C closure data.
3580 * Creates a new MonoAsyncResult (AsyncResult C# class) in the given domain.
3581 * If the handle is not null, the handle is initialized to a MonOWaitHandle.
3585 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data)
3587 MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
3588 MonoMethod *method = mono_get_context_capture_method ();
3590 /* we must capture the execution context from the original thread */
3592 MONO_OBJECT_SETREF (res, execution_context, mono_runtime_invoke (method, NULL, NULL, NULL));
3593 /* note: result may be null if the flow is suppressed */
3597 MONO_OBJECT_SETREF (res, object_data, object_data);
3598 MONO_OBJECT_SETREF (res, async_state, state);
3600 MONO_OBJECT_SETREF (res, handle, (MonoObject *) mono_wait_handle_new (domain, handle));
3602 res->sync_completed = FALSE;
3603 res->completed = FALSE;
3609 mono_message_init (MonoDomain *domain,
3610 MonoMethodMessage *this,
3611 MonoReflectionMethod *method,
3612 MonoArray *out_args)
3614 MonoMethodSignature *sig = mono_method_signature (method->method);
3620 MONO_OBJECT_SETREF (this, method, method);
3622 MONO_OBJECT_SETREF (this, args, mono_array_new (domain, mono_defaults.object_class, sig->param_count));
3623 MONO_OBJECT_SETREF (this, arg_types, mono_array_new (domain, mono_defaults.byte_class, sig->param_count));
3624 this->async_result = NULL;
3625 this->call_type = CallType_Sync;
3627 names = g_new (char *, sig->param_count);
3628 mono_method_get_param_names (method->method, (const char **) names);
3629 MONO_OBJECT_SETREF (this, names, mono_array_new (domain, mono_defaults.string_class, sig->param_count));
3631 for (i = 0; i < sig->param_count; i++) {
3632 name = mono_string_new (domain, names [i]);
3633 mono_array_setref (this->names, i, name);
3637 for (i = 0, j = 0; i < sig->param_count; i++) {
3639 if (sig->params [i]->byref) {
3641 MonoObject* arg = mono_array_get (out_args, gpointer, j);
3642 mono_array_setref (this->args, i, arg);
3646 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
3650 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT)
3653 mono_array_set (this->arg_types, guint8, i, arg_type);
3658 * mono_remoting_invoke:
3659 * @real_proxy: pointer to a RealProxy object
3660 * @msg: The MonoMethodMessage to execute
3661 * @exc: used to store exceptions
3662 * @out_args: used to store output arguments
3664 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
3665 * IMessage interface and it is not trivial to extract results from there. So
3666 * we call an helper method PrivateInvoke instead of calling
3667 * RealProxy::Invoke() directly.
3669 * Returns: the result object.
3672 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
3673 MonoObject **exc, MonoArray **out_args)
3675 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
3678 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
3681 im = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "PrivateInvoke", 4);
3683 real_proxy->vtable->domain->private_invoke_method = im;
3686 pa [0] = real_proxy;
3691 return mono_runtime_invoke (im, NULL, pa, exc);
3695 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
3696 MonoObject **exc, MonoArray **out_args)
3700 MonoMethodSignature *sig;
3702 int i, j, outarg_count = 0;
3704 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
3706 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
3707 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3708 target = tp->rp->unwrapped_server;
3710 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
3714 domain = mono_domain_get ();
3715 method = msg->method->method;
3716 sig = mono_method_signature (method);
3718 for (i = 0; i < sig->param_count; i++) {
3719 if (sig->params [i]->byref)
3723 /* FIXME: GC ensure we insert a write barrier for out_args, maybe in the caller? */
3724 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3727 ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
3729 for (i = 0, j = 0; i < sig->param_count; i++) {
3730 if (sig->params [i]->byref) {
3732 arg = mono_array_get (msg->args, gpointer, i);
3733 mono_array_setref (*out_args, j, arg);
3742 * mono_print_unhandled_exception:
3743 * @exc: The exception
3745 * Prints the unhandled exception.
3748 mono_print_unhandled_exception (MonoObject *exc)
3750 char *message = (char *) "";
3754 gboolean free_message = FALSE;
3756 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
3757 klass = exc->vtable->klass;
3759 while (klass && method == NULL) {
3760 method = mono_class_get_method_from_name_flags (klass, "ToString", 0, METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_PUBLIC);
3762 klass = klass->parent;
3767 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
3769 message = mono_string_to_utf8 (str);
3770 free_message = TRUE;
3775 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
3776 * exc->vtable->klass->name, message);
3778 g_printerr ("\nUnhandled Exception: %s\n", message);
3785 * mono_delegate_ctor:
3786 * @this: pointer to an uninitialized delegate object
3787 * @target: target object
3788 * @addr: pointer to native code
3790 * This is used to initialize a delegate. We also insert the method_info if
3791 * we find the info with mono_jit_info_table_find().
3794 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
3796 MonoDomain *domain = mono_domain_get ();
3797 MonoDelegate *delegate = (MonoDelegate *)this;
3798 MonoMethod *method = NULL;
3805 class = this->vtable->klass;
3807 if ((ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (addr)))) {
3808 method = ji->method;
3809 MONO_OBJECT_SETREF (delegate, method_info, mono_method_get_object (domain, method, NULL));
3812 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
3814 method = mono_marshal_get_remoting_invoke (method);
3815 delegate->method_ptr = mono_compile_method (method);
3816 MONO_OBJECT_SETREF (delegate, target, target);
3817 } else if (mono_method_signature (method)->hasthis && method->klass->valuetype) {
3818 method = mono_marshal_get_unbox_wrapper (method);
3819 delegate->method_ptr = mono_compile_method (method);
3820 MONO_OBJECT_SETREF (delegate, target, target);
3824 * Replace the original trampoline with a delegate trampoline
3825 * which will patch delegate->method_ptr with the address of the
3828 addr = arch_create_delegate_trampoline (method, addr);
3830 delegate->method_ptr = addr;
3831 MONO_OBJECT_SETREF (delegate, target, target);
3836 * mono_method_call_message_new:
3837 * @method: method to encapsulate
3838 * @params: parameters to the method
3839 * @invoke: optional, delegate invoke.
3840 * @cb: async callback delegate.
3841 * @state: state passed to the async callback.
3843 * Translates arguments pointers into a MonoMethodMessage.
3846 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
3847 MonoDelegate **cb, MonoObject **state)
3849 MonoDomain *domain = mono_domain_get ();
3850 MonoMethodSignature *sig = mono_method_signature (method);
3851 MonoMethodMessage *msg;
3854 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3857 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
3858 count = sig->param_count - 2;
3860 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
3861 count = sig->param_count;
3864 for (i = 0; i < count; i++) {
3869 if (sig->params [i]->byref)
3870 vpos = *((gpointer *)params [i]);
3874 type = sig->params [i]->type;
3875 class = mono_class_from_mono_type (sig->params [i]);
3877 if (class->valuetype)
3878 arg = mono_value_box (domain, class, vpos);
3880 arg = *((MonoObject **)vpos);
3882 mono_array_setref (msg->args, i, arg);
3885 if (cb != NULL && state != NULL) {
3886 *cb = *((MonoDelegate **)params [i]);
3888 *state = *((MonoObject **)params [i]);
3895 * mono_method_return_message_restore:
3897 * Restore results from message based processing back to arguments pointers
3900 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
3902 MonoMethodSignature *sig = mono_method_signature (method);
3903 int i, j, type, size, out_len;
3905 if (out_args == NULL)
3907 out_len = mono_array_length (out_args);
3911 for (i = 0, j = 0; i < sig->param_count; i++) {
3912 MonoType *pt = sig->params [i];
3917 mono_raise_exception (mono_get_exception_execution_engine ("The proxy call returned an incorrect number of output arguments"));
3919 arg = mono_array_get (out_args, gpointer, j);
3923 case MONO_TYPE_VOID:
3924 g_assert_not_reached ();
3928 case MONO_TYPE_BOOLEAN:
3931 case MONO_TYPE_CHAR:
3938 case MONO_TYPE_VALUETYPE: {
3939 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
3940 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
3943 case MONO_TYPE_STRING:
3944 case MONO_TYPE_CLASS:
3945 case MONO_TYPE_ARRAY:
3946 case MONO_TYPE_SZARRAY:
3947 case MONO_TYPE_OBJECT:
3948 **((MonoObject ***)params [i]) = (MonoObject *)arg;
3951 g_assert_not_reached ();
3960 * mono_load_remote_field:
3961 * @this: pointer to an object
3962 * @klass: klass of the object containing @field
3963 * @field: the field to load
3964 * @res: a storage to store the result
3966 * This method is called by the runtime on attempts to load fields of
3967 * transparent proxy objects. @this points to such TP, @klass is the class of
3968 * the object containing @field. @res is a storage location which can be
3969 * used to store the result.
3971 * Returns: an address pointing to the value of field.
3974 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
3976 static MonoMethod *getter = NULL;
3977 MonoDomain *domain = mono_domain_get ();
3978 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3979 MonoClass *field_class;
3980 MonoMethodMessage *msg;
3981 MonoArray *out_args;
3985 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3986 g_assert (res != NULL);
3988 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3989 mono_field_get_value (tp->rp->unwrapped_server, field, res);
3994 getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
3998 field_class = mono_class_from_mono_type (field->type);
4000 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
4001 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
4002 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
4004 full_name = mono_type_get_full_name (klass);
4005 mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
4006 mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
4009 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
4011 if (exc) mono_raise_exception ((MonoException *)exc);
4013 if (mono_array_length (out_args) == 0)
4016 *res = mono_array_get (out_args, MonoObject *, 0); /* FIXME: GC write abrrier for res */
4018 if (field_class->valuetype) {
4019 return ((char *)*res) + sizeof (MonoObject);
4025 * mono_load_remote_field_new:
4030 * Missing documentation.
4033 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
4035 static MonoMethod *getter = NULL;
4036 MonoDomain *domain = mono_domain_get ();
4037 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
4038 MonoClass *field_class;
4039 MonoMethodMessage *msg;
4040 MonoArray *out_args;
4041 MonoObject *exc, *res;
4044 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
4046 field_class = mono_class_from_mono_type (field->type);
4048 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
4050 if (field_class->valuetype) {
4051 res = mono_object_new (domain, field_class);
4052 val = ((gchar *) res) + sizeof (MonoObject);
4056 mono_field_get_value (tp->rp->unwrapped_server, field, val);
4061 getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
4065 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
4066 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
4068 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
4070 full_name = mono_type_get_full_name (klass);
4071 mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
4072 mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
4075 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
4077 if (exc) mono_raise_exception ((MonoException *)exc);
4079 if (mono_array_length (out_args) == 0)
4082 res = mono_array_get (out_args, MonoObject *, 0);
4088 * mono_store_remote_field:
4089 * @this: pointer to an object
4090 * @klass: klass of the object containing @field
4091 * @field: the field to load
4092 * @val: the value/object to store
4094 * This method is called by the runtime on attempts to store fields of
4095 * transparent proxy objects. @this points to such TP, @klass is the class of
4096 * the object containing @field. @val is the new value to store in @field.
4099 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
4101 static MonoMethod *setter = NULL;
4102 MonoDomain *domain = mono_domain_get ();
4103 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
4104 MonoClass *field_class;
4105 MonoMethodMessage *msg;
4106 MonoArray *out_args;
4111 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
4113 field_class = mono_class_from_mono_type (field->type);
4115 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
4116 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
4117 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
4122 setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
4126 if (field_class->valuetype)
4127 arg = mono_value_box (domain, field_class, val);
4129 arg = *((MonoObject **)val);
4132 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
4133 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
4135 full_name = mono_type_get_full_name (klass);
4136 mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
4137 mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
4138 mono_array_setref (msg->args, 2, arg);
4141 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
4143 if (exc) mono_raise_exception ((MonoException *)exc);
4147 * mono_store_remote_field_new:
4153 * Missing documentation
4156 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
4158 static MonoMethod *setter = NULL;
4159 MonoDomain *domain = mono_domain_get ();
4160 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
4161 MonoClass *field_class;
4162 MonoMethodMessage *msg;
4163 MonoArray *out_args;
4167 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
4169 field_class = mono_class_from_mono_type (field->type);
4171 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
4172 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
4173 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
4178 setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
4182 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
4183 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
4185 full_name = mono_type_get_full_name (klass);
4186 mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
4187 mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
4188 mono_array_setref (msg->args, 2, arg);
4191 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
4193 if (exc) mono_raise_exception ((MonoException *)exc);
4197 * mono_get_addr_from_ftnptr:
4199 * Given a pointer to a function descriptor, return the function address.
4200 * This is only needed on IA64.
4203 mono_get_addr_from_ftnptr (gpointer descr)
4206 return *(gpointer*)descr;