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/os/gc_wrapper.h>
35 #include <mono/utils/strenc.h>
38 * Enable experimental typed allocation using the GC_gcj_malloc function.
40 #ifdef HAVE_GC_GCJ_MALLOC
41 #define CREATION_SPEEDUP 1
45 mono_runtime_object_init (MonoObject *this)
48 MonoMethod *method = NULL;
49 MonoClass *klass = this->vtable->klass;
51 for (i = 0; i < klass->method.count; ++i) {
52 if (!strcmp (".ctor", klass->methods [i]->name) &&
53 klass->methods [i]->signature->param_count == 0) {
54 method = klass->methods [i];
61 mono_runtime_invoke (method, this, NULL, NULL);
64 /* The pseudo algorithm for type initialization from the spec
65 Note it doesn't say anything about domains - only threads.
67 2. If the type is initialized you are done.
68 2.1. If the type is not yet initialized, try to take an
70 2.2. If successful, record this thread as responsible for
71 initializing the type and proceed to step 2.3.
72 2.2.1. If not, see whether this thread or any thread
73 waiting for this thread to complete already holds the lock.
74 2.2.2. If so, return since blocking would create a deadlock. This thread
75 will now see an incompletely initialized state for the type,
76 but no deadlock will arise.
77 2.2.3 If not, block until the type is initialized then return.
78 2.3 Initialize the parent type and then all interfaces implemented
80 2.4 Execute the type initialization code for this type.
81 2.5 Mark the type as initialized, release the initialization lock,
82 awaken any threads waiting for this type to be initialized,
89 guint32 initializing_tid;
90 guint32 waiting_count;
91 CRITICAL_SECTION initialization_section;
92 } TypeInitializationLock;
94 /* for locking access to type_initialization_hash and blocked_thread_hash */
95 static CRITICAL_SECTION type_initialization_section;
97 /* from vtable to lock */
98 static GHashTable *type_initialization_hash;
100 /* from thread id to thread id being waited on */
101 static GHashTable *blocked_thread_hash;
104 static MonoThread *main_thread;
107 mono_type_initialization_init (void)
109 InitializeCriticalSection (&type_initialization_section);
110 type_initialization_hash = g_hash_table_new (NULL, NULL);
111 blocked_thread_hash = g_hash_table_new (NULL, NULL);
115 * mono_runtime_class_init:
116 * @vtable: vtable that needs to be initialized
118 * This routine calls the class constructor for @vtable.
121 mono_runtime_class_init (MonoVTable *vtable)
125 MonoException *exc_to_throw;
126 MonoMethod *method = NULL;
133 if (vtable->initialized)
138 klass = vtable->klass;
140 for (i = 0; i < klass->method.count; ++i) {
141 method = klass->methods [i];
142 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
143 (strcmp (".cctor", method->name) == 0)) {
150 MonoDomain *domain = vtable->domain;
151 TypeInitializationLock *lock;
152 guint32 tid = GetCurrentThreadId();
153 int do_initialization = 0;
154 MonoDomain *last_domain = NULL;
156 EnterCriticalSection (&type_initialization_section);
157 /* double check... */
158 if (vtable->initialized) {
159 LeaveCriticalSection (&type_initialization_section);
162 lock = g_hash_table_lookup (type_initialization_hash, vtable);
164 /* This thread will get to do the initialization */
165 if (mono_domain_get () != domain) {
166 /* Transfer into the target domain */
167 last_domain = mono_domain_get ();
168 if (!mono_domain_set (domain, FALSE)) {
169 vtable->initialized = 1;
170 LeaveCriticalSection (&type_initialization_section);
171 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
174 lock = g_malloc (sizeof(TypeInitializationLock));
175 InitializeCriticalSection (&lock->initialization_section);
176 lock->initializing_tid = tid;
177 lock->waiting_count = 1;
178 /* grab the vtable lock while this thread still owns type_initialization_section */
179 EnterCriticalSection (&lock->initialization_section);
180 g_hash_table_insert (type_initialization_hash, vtable, lock);
181 do_initialization = 1;
185 if (lock->initializing_tid == tid) {
186 LeaveCriticalSection (&type_initialization_section);
189 /* see if the thread doing the initialization is already blocked on this thread */
190 blocked = GUINT_TO_POINTER (lock->initializing_tid);
191 while ((blocked = g_hash_table_lookup (blocked_thread_hash, blocked))) {
192 if (blocked == GUINT_TO_POINTER (tid)) {
193 LeaveCriticalSection (&type_initialization_section);
197 ++lock->waiting_count;
198 /* record the fact that we are waiting on the initializing thread */
199 g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), GUINT_TO_POINTER (lock->initializing_tid));
201 LeaveCriticalSection (&type_initialization_section);
203 if (do_initialization) {
204 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
206 mono_domain_set (last_domain, TRUE);
207 LeaveCriticalSection (&lock->initialization_section);
209 /* this just blocks until the initializing thread is done */
210 EnterCriticalSection (&lock->initialization_section);
211 LeaveCriticalSection (&lock->initialization_section);
214 EnterCriticalSection (&type_initialization_section);
215 if (lock->initializing_tid != tid)
216 g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
217 --lock->waiting_count;
218 if (lock->waiting_count == 0) {
219 DeleteCriticalSection (&lock->initialization_section);
220 g_hash_table_remove (type_initialization_hash, vtable);
223 vtable->initialized = 1;
224 /* FIXME: if the cctor fails, the type must be marked as unusable */
225 LeaveCriticalSection (&type_initialization_section);
227 vtable->initialized = 1;
232 (klass->image == mono_defaults.corlib &&
233 !strcmp (klass->name_space, "System") &&
234 !strcmp (klass->name, "TypeInitializationException")))
235 return; /* No static constructor found or avoid infinite loop */
237 if (klass->name_space && *klass->name_space)
238 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
240 full_name = g_strdup (klass->name);
242 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
245 mono_raise_exception (exc_to_throw);
249 default_trampoline (MonoMethod *method)
255 default_remoting_trampoline (MonoMethod *method)
257 g_error ("remoting not installed");
261 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
262 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
265 mono_install_trampoline (MonoTrampoline func)
267 arch_create_jit_trampoline = func? func: default_trampoline;
271 mono_install_remoting_trampoline (MonoTrampoline func)
273 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
276 static MonoCompileFunc default_mono_compile_method = NULL;
279 mono_install_compile_method (MonoCompileFunc func)
281 default_mono_compile_method = func;
285 mono_compile_method (MonoMethod *method)
287 if (!default_mono_compile_method) {
288 g_error ("compile method called on uninitialized runtime");
291 return default_mono_compile_method (method);
295 #if 0 && HAVE_BOEHM_GC
297 vtable_finalizer (void *obj, void *data) {
298 g_print ("%s finalized (%p)\n", (char*)data, obj);
304 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
307 * The vtables in the root appdomain are assumed to be reachable by other
308 * roots, and we don't use typed allocation in the other domains.
311 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
314 mono_class_compute_gc_descriptor (MonoClass *class)
316 MonoClassField *field;
320 static gboolean gcj_inited = FALSE;
325 GC_init_gcj_malloc (5, NULL);
329 mono_class_init (class);
331 if (class->gc_descr_inited)
334 class->gc_descr_inited = TRUE;
335 class->gc_descr = GC_NO_DESCRIPTOR;
337 if (class == mono_defaults.string_class) {
338 bitmap = GC_HEADER_BITMAP;
339 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
341 else if (class->rank) {
342 mono_class_compute_gc_descriptor (class->element_class);
344 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
345 bitmap = GC_HEADER_BITMAP;
347 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
348 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
352 static int count = 0;
356 /* GC 6.1 has trouble handling 64 bit descriptors... */
357 if ((class->instance_size / sizeof (gpointer)) > 30) {
358 // printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
362 bitmap = GC_HEADER_BITMAP;
369 // printf("KLASS: %s.\n", class->name);
371 for (p = class; p != NULL; p = p->parent) {
372 for (i = 0; i < p->field.count; ++i) {
373 field = &p->fields [i];
374 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
376 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
379 pos = field->offset / sizeof (gpointer);
381 if (field->type->byref)
384 switch (field->type->type) {
385 case MONO_TYPE_BOOLEAN:
397 // printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
400 case MONO_TYPE_STRING:
401 case MONO_TYPE_SZARRAY:
402 case MONO_TYPE_CLASS:
403 case MONO_TYPE_OBJECT:
404 case MONO_TYPE_ARRAY:
406 g_assert ((field->offset % sizeof(gpointer)) == 0);
408 bitmap |= ((guint64)1) << pos;
409 // printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
411 case MONO_TYPE_VALUETYPE: {
412 MonoClass *fclass = field->type->data.klass;
413 if (!fclass->enumtype) {
414 mono_class_compute_gc_descriptor (fclass);
415 bitmap |= (fclass->gc_bitmap >> (sizeof (MonoObject) / sizeof (gpointer))) << pos;
425 // printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
426 class->gc_bitmap = bitmap;
427 /* Convert to the format expected by GC_make_descriptor */
428 bm [0] = (guint32)bitmap;
429 bm [1] = (guint32)(bitmap >> 32);
430 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bm, class->instance_size / sizeof (gpointer));
433 #endif /* CREATION_SPEEDUP */
436 * field_is_special_static:
438 * Returns SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
439 * SPECIAL_STATIC_NONE otherwise.
442 field_is_special_static (MonoClass *fklass, MonoClassField *field)
444 MonoCustomAttrInfo *ainfo;
446 ainfo = mono_custom_attrs_from_field (fklass, field);
449 for (i = 0; i < ainfo->num_attrs; ++i) {
450 MonoClass *klass = ainfo->attrs [i].ctor->klass;
451 if (klass->image == mono_defaults.corlib) {
452 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
453 mono_custom_attrs_free (ainfo);
454 return SPECIAL_STATIC_THREAD;
456 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
457 mono_custom_attrs_free (ainfo);
458 return SPECIAL_STATIC_CONTEXT;
462 mono_custom_attrs_free (ainfo);
463 return SPECIAL_STATIC_NONE;
468 * @domain: the application domain
469 * @class: the class to initialize
471 * VTables are domain specific because we create domain specific code, and
472 * they contain the domain specific static class data.
475 mono_class_vtable (MonoDomain *domain, MonoClass *class)
477 MonoVTable *vt = NULL;
478 MonoClassField *field;
484 guint32 constant_cols [MONO_CONSTANT_SIZE];
488 vt = class->cached_vtable;
489 if (vt && vt->domain == domain)
492 mono_domain_lock (domain);
493 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
494 mono_domain_unlock (domain);
499 mono_class_init (class);
501 mono_stats.used_class_count++;
502 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
504 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
506 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
512 mono_class_compute_gc_descriptor (class);
513 if (domain != mono_get_root_domain ())
515 * We can't use typed allocation in the non-root domains, since the
516 * collector needs the GC descriptor stored in the vtable even after
517 * the mempool containing the vtable is destroyed when the domain is
518 * unloaded. An alternative might be to allocate vtables in the GC
519 * heap, but this does not seem to work (it leads to crashes inside
520 * libgc). If that approach is tried, two gc descriptors need to be
521 * allocated for each class: one for the root domain, and one for all
522 * other domains. The second descriptor should contain a bit for the
523 * vtable field in MonoObject, since we can no longer assume the
524 * vtable is reachable by other roots after the appdomain is unloaded.
526 vt->gc_descr = GC_NO_DESCRIPTOR;
528 vt->gc_descr = class->gc_descr;
531 if (class->class_size) {
533 vt->data = GC_MALLOC (class->class_size + 8);
534 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
535 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
536 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
538 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
541 mono_stats.class_static_data_size += class->class_size + 8;
545 for (i = class->field.first; i < class->field.last; ++i) {
546 field = &class->fields [i - class->field.first];
547 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
549 if (mono_field_is_deleted (field))
551 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
552 gint32 special_static = field_is_special_static (class, field);
553 if (special_static != SPECIAL_STATIC_NONE) {
554 guint32 size, align, offset;
555 size = mono_type_size (field->type, &align);
556 offset = mono_alloc_special_static_data (special_static, size, align);
557 if (!domain->special_static_fields)
558 domain->special_static_fields = g_hash_table_new (NULL, NULL);
559 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
563 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
564 MonoClass *fklass = mono_class_from_mono_type (field->type);
565 t = (char*)vt->data + field->offset;
566 if (fklass->valuetype) {
567 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
569 /* it's a pointer type: add check */
570 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
571 *t = *(char *)field->data;
575 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
578 if (!field->def_value) {
579 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
582 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
583 field->def_value = g_new0 (MonoConstant, 1);
584 field->def_value->type = constant_cols [MONO_CONSTANT_TYPE];
585 field->def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
588 p = field->def_value->value;
589 len = mono_metadata_decode_blob_size (p, &p);
590 t = (char*)vt->data + field->offset;
591 /* should we check that the type matches? */
592 switch (field->def_value->type) {
593 case MONO_TYPE_BOOLEAN:
601 guint16 *val = (guint16*)t;
607 guint32 *val = (guint32*)t;
613 guint64 *val = (guint64*)t;
618 float *val = (float*)t;
623 double *val = (double*)t;
627 case MONO_TYPE_STRING: {
628 gpointer *val = (gpointer*)t;
629 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
630 gunichar2 *copy = g_malloc (len);
632 for (j = 0; j < len/2; j++) {
633 copy [j] = read16 (p);
636 *val = mono_string_new_utf16 (domain, copy, len/2);
639 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
643 case MONO_TYPE_CLASS:
644 /* nothing to do, we malloc0 the data and the value can be 0 only */
647 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
651 vt->max_interface_id = class->max_interface_id;
653 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
654 sizeof (gpointer) * (class->max_interface_id + 1));
656 /* initialize interface offsets */
657 for (i = 0; i <= class->max_interface_id; ++i) {
658 int slot = class->interface_offsets [i];
660 vt->interface_offsets [i] = &(vt->vtable [slot]);
664 * arch_create_jit_trampoline () can recursively call this function again
665 * because it compiles icall methods right away.
667 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
668 if (!class->cached_vtable)
669 class->cached_vtable = vt;
671 /* initialize vtable */
672 for (i = 0; i < class->vtable_size; ++i) {
675 if ((cm = class->vtable [i]))
676 vt->vtable [i] = arch_create_jit_trampoline (cm);
679 mono_domain_unlock (domain);
681 /* make sure the the parent is initialized */
683 mono_class_vtable (domain, class->parent);
685 vt->type = mono_type_get_object (domain, &class->byval_arg);
686 if (class->contextbound)
695 * mono_class_proxy_vtable:
696 * @domain: the application domain
697 * @remove_class: the remote class
699 * Creates a vtable for transparent proxies. It is basically
700 * a copy of the real vtable of the class wrapped in @remote_class,
701 * but all function pointers invoke the remoting functions, and
702 * vtable->klass points to the transparent proxy class, and not to @class.
705 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class)
707 MonoVTable *vt, *pvt;
708 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
710 MonoClass *class = remote_class->proxy_class;
712 vt = mono_class_vtable (domain, class);
713 max_interface_id = vt->max_interface_id;
715 /* Calculate vtable space for extra interfaces */
716 for (j = 0; j < remote_class->interface_count; j++) {
717 MonoClass* iclass = remote_class->interfaces[j];
718 int method_count = iclass->method.count;
720 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
721 continue; /* interface implemented by the class */
723 for (i = 0; i < iclass->interface_count; i++)
724 method_count += iclass->interfaces[i]->method.count;
726 extra_interface_vtsize += method_count * sizeof (gpointer);
727 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
730 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
732 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
734 pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
735 memcpy (pvt, vt, vtsize);
737 pvt->klass = mono_defaults.transparent_proxy_class;
739 /* initialize vtable */
740 for (i = 0; i < class->vtable_size; ++i) {
743 if ((cm = class->vtable [i]))
744 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
747 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
749 /* create trampolines for abstract methods */
750 for (k = class; k; k = k->parent) {
751 for (i = 0; i < k->method.count; i++) {
752 int slot = k->methods [i]->slot;
753 if (!pvt->vtable [slot])
754 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
759 pvt->max_interface_id = max_interface_id;
760 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
761 sizeof (gpointer) * (max_interface_id + 1));
763 /* initialize interface offsets */
764 for (i = 0; i <= class->max_interface_id; ++i) {
765 int slot = class->interface_offsets [i];
767 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
770 if (remote_class->interface_count > 0)
772 int slot = class->vtable_size;
777 /* Create trampolines for the methods of the interfaces */
778 for (n = 0; n < remote_class->interface_count; n++)
780 iclass = remote_class->interfaces[n];
781 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
782 continue; /* interface implemented by the class */
787 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
789 for (j = 0; j < interf->method.count; ++j) {
790 MonoMethod *cm = interf->methods [j];
791 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
793 slot += interf->method.count;
794 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
806 * @domain: the application domain
807 * @class_name: name of the remote class
809 * Creates and initializes a MonoRemoteClass object for a remote type.
813 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
817 mono_domain_lock (domain);
818 rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
821 mono_domain_unlock (domain);
825 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
827 rc->interface_count = 0;
828 rc->interfaces = NULL;
829 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
830 rc->proxy_class_name = mono_string_to_utf8 (class_name);
832 mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
833 mono_upgrade_remote_class (domain, rc, proxy_class);
835 if (rc->vtable == NULL)
836 rc->vtable = mono_class_proxy_vtable (domain, rc);
838 mono_domain_unlock (domain);
844 extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
846 /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
848 int current_size = ((remote_class->interface_count / 5) + 1) * 5;
849 remote_class->interface_count += amount;
851 if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
853 int new_size = ((remote_class->interface_count / 5) + 1) * 5;
854 MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
856 if (remote_class->interfaces != NULL)
857 memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
859 remote_class->interfaces = new_array;
865 * mono_upgrade_remote_class:
866 * @domain: the application domain
867 * @remote_class: the remote class
868 * @klass: class to which the remote class can be casted.
870 * Updates the vtable of the remote class by adding the necessary method slots
871 * and interface offsets so it can be safely casted to klass. klass can be a
872 * class or an interface.
874 void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
876 gboolean redo_vtable;
878 mono_domain_lock (domain);
880 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
883 for (i = 0; i < remote_class->interface_count; i++)
884 if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
887 extend_interface_array (domain, remote_class, 1);
888 remote_class->interfaces [remote_class->interface_count-1] = klass;
892 redo_vtable = (remote_class->proxy_class != klass);
893 remote_class->proxy_class = klass;
897 remote_class->vtable = mono_class_proxy_vtable (domain, remote_class);
900 printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
902 for (n=0; n<remote_class->interface_count; n++)
903 printf (" I:%s\n", remote_class->interfaces[n]->name);
906 mono_domain_unlock (domain);
910 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
911 * the instance of a callvirt of method.
914 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
918 MonoMethod *res = NULL;
920 klass = mono_object_class (obj);
921 if (klass == mono_defaults.transparent_proxy_class) {
922 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
928 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
931 vtable = klass->vtable;
933 /* check method->slot is a valid index: perform isinstance? */
934 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
936 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
938 if (method->slot != -1)
939 res = vtable [method->slot];
943 if (!res) res = method; /* It may be an interface or abstract class method */
944 res = mono_marshal_get_remoting_invoke (res);
953 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
955 g_error ("runtime invoke called on uninitialized runtime");
959 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
962 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
964 return default_mono_runtime_invoke (method, obj, params, exc);
968 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
971 gpointer *p = (gpointer*)dest;
978 case MONO_TYPE_BOOLEAN:
981 guint8 *p = (guint8*)dest;
982 *p = *(guint8*)value;
987 case MONO_TYPE_CHAR: {
988 guint16 *p = (guint16*)dest;
989 *p = *(guint16*)value;
992 #if SIZEOF_VOID_P == 4
998 gint32 *p = (gint32*)dest;
999 *p = *(gint32*)value;
1002 #if SIZEOF_VOID_P == 8
1007 case MONO_TYPE_U8: {
1008 gint64 *p = (gint64*)dest;
1009 *p = *(gint64*)value;
1012 case MONO_TYPE_R4: {
1013 float *p = (float*)dest;
1014 *p = *(float*)value;
1017 case MONO_TYPE_R8: {
1018 double *p = (double*)dest;
1019 *p = *(double*)value;
1022 case MONO_TYPE_STRING:
1023 case MONO_TYPE_SZARRAY:
1024 case MONO_TYPE_CLASS:
1025 case MONO_TYPE_OBJECT:
1026 case MONO_TYPE_ARRAY:
1027 case MONO_TYPE_PTR: {
1028 gpointer *p = (gpointer*)dest;
1029 *p = deref_pointer? *(gpointer*)value: value;
1032 case MONO_TYPE_VALUETYPE:
1033 if (type->data.klass->enumtype) {
1034 t = type->data.klass->enum_basetype->type;
1038 size = mono_class_value_size (type->data.klass, NULL);
1039 memcpy (dest, value, size);
1043 g_warning ("got type %x", type->type);
1044 g_assert_not_reached ();
1049 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1053 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1055 dest = (char*)obj + field->offset;
1056 set_value (field->type, dest, value, FALSE);
1060 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1064 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1066 dest = (char*)vt->data + field->offset;
1067 set_value (field->type, dest, value, FALSE);
1071 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1075 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1077 src = (char*)obj + field->offset;
1078 set_value (field->type, value, src, TRUE);
1082 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1086 MonoVTable *vtable = NULL;
1088 gboolean is_static = FALSE;
1089 gboolean is_ref = FALSE;
1091 switch (field->type->type) {
1092 case MONO_TYPE_STRING:
1093 case MONO_TYPE_OBJECT:
1094 case MONO_TYPE_CLASS:
1095 case MONO_TYPE_ARRAY:
1096 case MONO_TYPE_SZARRAY:
1101 case MONO_TYPE_BOOLEAN:
1104 case MONO_TYPE_CHAR:
1113 case MONO_TYPE_VALUETYPE:
1114 is_ref = field->type->byref;
1117 g_error ("type 0x%x not handled in "
1118 "mono_field_get_value_object", field->type->type);
1122 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1124 vtable = mono_class_vtable (domain, field->parent);
1125 if (!vtable->initialized)
1126 mono_runtime_class_init (vtable);
1131 mono_field_static_get_value (vtable, field, &o);
1133 mono_field_get_value (obj, field, &o);
1138 /* boxed value type */
1139 klass = mono_class_from_mono_type (field->type);
1140 o = mono_object_new (domain, klass);
1141 v = ((gchar *) o) + sizeof (MonoObject);
1143 mono_field_static_get_value (vtable, field, v);
1145 mono_field_get_value (obj, field, v);
1153 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1157 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1159 src = (char*)vt->data + field->offset;
1160 set_value (field->type, value, src, TRUE);
1164 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1166 default_mono_runtime_invoke (prop->set, obj, params, exc);
1170 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1172 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1177 mono_get_delegate_invoke (MonoClass *klass)
1184 for (i = 0; i < klass->method.count; ++i) {
1185 if (klass->methods [i]->name[0] == 'I' &&
1186 !strcmp ("Invoke", klass->methods [i]->name)) {
1187 im = klass->methods [i];
1197 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1201 im = mono_get_delegate_invoke (delegate->vtable->klass);
1204 return mono_runtime_invoke (im, delegate, params, exc);
1207 static MonoArray* main_args;
1210 mono_runtime_get_main_args (void)
1216 fire_process_exit_event (void)
1218 MonoClassField *field;
1219 MonoDomain *domain = mono_domain_get ();
1221 MonoObject *delegate, *exc;
1223 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1226 if (domain != mono_get_root_domain ())
1229 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1230 if (delegate == NULL)
1235 mono_runtime_delegate_invoke (delegate, pa, &exc);
1239 * Execute a standard Main() method (argc/argv contains the
1240 * executable name). This method also sets the command line argument value
1241 * needed by System.Environment.
1244 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1248 MonoArray *args = NULL;
1249 MonoDomain *domain = mono_domain_get ();
1250 gchar *utf8_fullpath;
1253 main_thread = mono_thread_current ();
1255 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1257 if (!g_path_is_absolute (argv [0])) {
1258 gchar *basename = g_path_get_basename (argv [0]);
1259 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1263 utf8_fullpath = mono_utf8_from_external (fullpath);
1264 if(utf8_fullpath == NULL) {
1265 /* Printing the arg text will cause glib to
1266 * whinge about "Invalid UTF-8", but at least
1267 * its relevant, and shows the problem text
1270 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1271 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1278 utf8_fullpath = mono_utf8_from_external (argv[0]);
1279 if(utf8_fullpath == NULL) {
1280 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1281 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1286 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1287 g_free (utf8_fullpath);
1289 for (i = 1; i < argc; ++i) {
1293 utf8_arg=mono_utf8_from_external (argv[i]);
1294 if(utf8_arg==NULL) {
1295 /* Ditto the comment about Invalid UTF-8 here */
1296 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1297 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1301 arg = mono_string_new (domain, utf8_arg);
1302 mono_array_set (main_args, gpointer, i, arg);
1306 if (method->signature->param_count) {
1307 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1308 for (i = 0; i < argc; ++i) {
1309 /* The encodings should all work, given that
1310 * we've checked all these args for the
1313 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1314 mono_array_set (args, gpointer, i, arg);
1317 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1320 mono_assembly_set_main (method->klass->image->assembly);
1322 result = mono_runtime_exec_main (method, args, exc);
1323 fire_process_exit_event ();
1327 /* Used in mono_unhandled_exception */
1329 create_unhandled_exception_eventargs (MonoObject *exc)
1333 MonoMethod *method = NULL;
1334 MonoBoolean is_terminating = TRUE;
1338 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1341 mono_class_init (klass);
1343 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1344 for (i = 0; i < klass->method.count; ++i) {
1345 method = klass->methods [i];
1346 if (!strcmp (".ctor", method->name) &&
1347 method->signature->param_count == 2 &&
1348 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1356 args [1] = &is_terminating;
1358 obj = mono_object_new (mono_domain_get (), klass);
1359 mono_runtime_invoke (method, obj, args, NULL);
1365 * We call this function when we detect an unhandled exception
1366 * in the default domain.
1367 * It invokes the * UnhandledException event in AppDomain or prints
1368 * a warning to the console
1371 mono_unhandled_exception (MonoObject *exc)
1373 MonoDomain *domain = mono_domain_get ();
1374 MonoClassField *field;
1375 MonoObject *delegate;
1377 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1378 "UnhandledException");
1381 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1382 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1384 /* set exitcode only in the main thread */
1385 if (mono_thread_current () == main_thread)
1386 mono_environment_exitcode_set (1);
1387 if (domain != mono_get_root_domain () || !delegate) {
1388 mono_print_unhandled_exception (exc);
1390 MonoObject *e = NULL;
1393 pa [0] = domain->domain;
1394 pa [1] = create_unhandled_exception_eventargs (exc);
1395 mono_runtime_delegate_invoke (delegate, pa, &e);
1398 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1399 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1407 * Launch a new thread to start all setup that requires managed code
1410 * main_func is called back from the thread with main_args as the
1411 * parameter. The callback function is expected to start Main()
1412 * eventually. This function then waits for all managed threads to
1416 mono_runtime_exec_managed_code (MonoDomain *domain,
1417 MonoMainThreadFunc main_func,
1420 mono_thread_create (domain, main_func, main_args);
1422 mono_thread_manage ();
1426 * Execute a standard Main() method (args doesn't contain the
1430 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1440 domain = mono_object_domain (args);
1441 if (!domain->entry_assembly) {
1443 gchar *config_suffix;
1444 MonoAssembly *assembly;
1446 assembly = method->klass->image->assembly;
1447 domain->entry_assembly = assembly;
1448 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1450 config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
1451 str = g_build_filename (assembly->basedir, config_suffix, NULL);
1452 g_free (config_suffix);
1453 domain->setup->configuration_file = mono_string_new (domain, str);
1457 /* FIXME: check signature of method */
1458 if (method->signature->ret->type == MONO_TYPE_I4) {
1460 res = mono_runtime_invoke (method, NULL, pa, exc);
1462 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1466 mono_environment_exitcode_set (rval);
1468 mono_runtime_invoke (method, NULL, pa, exc);
1472 /* If the return type of Main is void, only
1473 * set the exitcode if an exception was thrown
1474 * (we don't want to blow away an
1475 * explicitly-set exit code)
1478 mono_environment_exitcode_set (rval);
1486 mono_install_runtime_invoke (MonoInvokeFunc func)
1488 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1492 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1495 MonoMethodSignature *sig = method->signature;
1496 gpointer *pa = NULL;
1499 if (NULL != params) {
1500 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1501 for (i = 0; i < mono_array_length (params); i++) {
1502 if (sig->params [i]->byref) {
1506 switch (sig->params [i]->type) {
1509 case MONO_TYPE_BOOLEAN:
1512 case MONO_TYPE_CHAR:
1521 case MONO_TYPE_VALUETYPE:
1522 if (sig->params [i]->byref) {
1523 /* MS seems to create the objects if a null is passed in */
1524 if (! ((gpointer *)params->vector)[i])
1525 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
1528 g_assert (((gpointer*)params->vector) [i]);
1529 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1531 case MONO_TYPE_STRING:
1532 case MONO_TYPE_OBJECT:
1533 case MONO_TYPE_CLASS:
1534 case MONO_TYPE_ARRAY:
1535 case MONO_TYPE_SZARRAY:
1536 if (sig->params [i]->byref)
1537 pa [i] = &(((gpointer *)params->vector)[i]);
1539 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1542 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1547 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1549 obj = mono_object_new (mono_domain_get (), method->klass);
1550 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1551 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1554 mono_runtime_invoke (method, obj, pa, exc);
1557 return mono_runtime_invoke (method, obj, pa, exc);
1561 out_of_memory (size_t size)
1564 * we could allocate at program startup some memory that we could release
1565 * back to the system at this point if we're really low on memory (ie, size is
1566 * lower than the memory we set apart)
1568 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1572 * mono_object_allocate:
1573 * @size: number of bytes to allocate
1575 * This is a very simplistic routine until we have our GC-aware
1578 * Returns: an allocated object of size @size, or NULL on failure.
1580 static inline void *
1581 mono_object_allocate (size_t size)
1584 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1585 void *o = GC_MALLOC (size);
1587 void *o = calloc (1, size);
1589 mono_stats.new_object_count++;
1592 out_of_memory (size);
1596 #if CREATION_SPEEDUP
1597 static inline void *
1598 mono_object_allocate_spec (size_t size, void *gcdescr)
1600 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1601 void *o = GC_GCJ_MALLOC (size, gcdescr);
1602 mono_stats.new_object_count++;
1605 out_of_memory (size);
1613 * Frees the memory used by the object. Debugging purposes
1614 * only, as we will have our GC system.
1617 mono_object_free (MonoObject *o)
1620 g_error ("mono_object_free called with boehm gc.");
1622 MonoClass *c = o->vtable->klass;
1624 memset (o, 0, c->instance_size);
1631 * @klass: the class of the object that we want to create
1633 * Returns: A newly created object whose definition is
1634 * looked up using @klass
1637 mono_object_new (MonoDomain *domain, MonoClass *klass)
1639 MONO_ARCH_SAVE_REGS;
1640 return mono_object_new_specific (mono_class_vtable (domain, klass));
1644 * mono_object_new_specific:
1645 * @vtable: the vtable of the object that we want to create
1647 * Returns: A newly created object with class and domain specified
1651 mono_object_new_specific (MonoVTable *vtable)
1655 MONO_ARCH_SAVE_REGS;
1660 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1663 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1667 mono_class_init (klass);
1669 for (i = 0; i < klass->method.count; ++i) {
1670 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1671 klass->methods [i]->signature->param_count == 1) {
1672 im = klass->methods [i];
1677 vtable->domain->create_proxy_for_type_method = im;
1680 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1682 o = mono_runtime_invoke (im, NULL, pa, NULL);
1683 if (o != NULL) return o;
1686 return mono_object_new_alloc_specific (vtable);
1690 mono_object_new_fast (MonoVTable *vtable)
1693 MONO_ARCH_SAVE_REGS;
1695 #if CREATION_SPEEDUP
1696 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1697 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1699 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1700 o = mono_object_allocate (vtable->klass->instance_size);
1704 o = mono_object_allocate (vtable->klass->instance_size);
1711 mono_object_new_alloc_specific (MonoVTable *vtable)
1715 #if CREATION_SPEEDUP
1716 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1717 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1719 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1720 o = mono_object_allocate (vtable->klass->instance_size);
1724 o = mono_object_allocate (vtable->klass->instance_size);
1727 if (vtable->klass->has_finalize)
1728 mono_object_register_finalizer (o);
1730 mono_profiler_allocation (o, vtable->klass);
1735 * mono_object_new_from_token:
1736 * @image: Context where the type_token is hosted
1737 * @token: a token of the type that we want to create
1739 * Returns: A newly created object whose definition is
1740 * looked up using @token in the @image image
1743 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1747 class = mono_class_get (image, token);
1749 return mono_object_new (domain, class);
1754 * mono_object_clone:
1755 * @obj: the object to clone
1757 * Returns: A newly created object who is a shallow copy of @obj
1760 mono_object_clone (MonoObject *obj)
1765 size = obj->vtable->klass->instance_size;
1766 o = mono_object_allocate (size);
1767 mono_profiler_allocation (o, obj->vtable->klass);
1769 memcpy (o, obj, size);
1771 if (obj->vtable->klass->has_finalize)
1772 mono_object_register_finalizer (o);
1778 * @array: the array to clone
1780 * Returns: A newly created array who is a shallow copy of @array
1783 mono_array_clone (MonoArray *array)
1788 MonoClass *klass = array->obj.vtable->klass;
1790 MONO_ARCH_SAVE_REGS;
1792 if (array->bounds == NULL) {
1793 size = mono_array_length (array);
1794 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1795 klass, &size, NULL);
1797 size *= mono_array_element_size (klass);
1798 memcpy (o, array, sizeof (MonoArray) + size);
1803 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1804 size = mono_array_element_size (klass);
1805 for (i = 0; i < klass->rank; ++i) {
1806 sizes [i] = array->bounds [i].length;
1807 size *= array->bounds [i].length;
1808 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1810 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1811 klass, sizes, sizes + klass->rank);
1812 memcpy (o, array, sizeof(MonoArray) + size);
1817 /* helper macros to check for overflow when calculating the size of arrays */
1818 #define MYGUINT32_MAX 4294967295U
1819 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1820 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1821 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1822 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1823 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1826 * mono_array_new_full:
1827 * @domain: domain where the object is created
1828 * @array_class: array class
1829 * @lengths: lengths for each dimension in the array
1830 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1832 * This routine creates a new array objects with the given dimensions,
1833 * lower bounds and type.
1836 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1837 guint32 *lengths, guint32 *lower_bounds)
1839 guint32 byte_len, len;
1842 MonoArrayBounds *bounds;
1846 if (!array_class->inited)
1847 mono_class_init (array_class);
1849 byte_len = mono_array_element_size (array_class);
1852 if (array_class->rank == 1 &&
1853 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1858 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1860 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1862 for (i = 0; i < array_class->rank; ++i) {
1863 bounds [i].length = lengths [i];
1864 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1865 out_of_memory (MYGUINT32_MAX);
1870 for (i = 0; i < array_class->rank; ++i)
1871 bounds [i].lower_bound = lower_bounds [i];
1874 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1875 out_of_memory (MYGUINT32_MAX);
1877 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1878 out_of_memory (MYGUINT32_MAX);
1879 byte_len += sizeof (MonoArray);
1881 * Following three lines almost taken from mono_object_new ():
1882 * they need to be kept in sync.
1884 vtable = mono_class_vtable (domain, array_class);
1885 #if CREATION_SPEEDUP
1886 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1887 o = mono_object_allocate_spec (byte_len, vtable);
1889 o = mono_object_allocate (byte_len);
1893 o = mono_object_allocate (byte_len);
1897 array = (MonoArray*)o;
1899 array->bounds = bounds;
1900 array->max_length = len;
1902 mono_profiler_allocation (o, array_class);
1909 * @domain: domain where the object is created
1910 * @eclass: element class
1911 * @n: number of array elements
1913 * This routine creates a new szarray with @n elements of type @eclass.
1916 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1920 MONO_ARCH_SAVE_REGS;
1922 ac = mono_array_class_get (eclass, 1);
1923 g_assert (ac != NULL);
1925 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1929 * mono_array_new_specific:
1930 * @vtable: a vtable in the appropriate domain for an initialized class
1931 * @n: number of array elements
1933 * This routine is a fast alternative to mono_array_new() for code which
1934 * can be sure about the domain it operates in.
1937 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1941 guint32 byte_len, elem_size;
1943 MONO_ARCH_SAVE_REGS;
1945 elem_size = mono_array_element_size (vtable->klass);
1946 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1947 out_of_memory (MYGUINT32_MAX);
1948 byte_len = n * elem_size;
1949 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1950 out_of_memory (MYGUINT32_MAX);
1951 byte_len += sizeof (MonoArray);
1952 #if CREATION_SPEEDUP
1953 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1954 o = mono_object_allocate_spec (byte_len, vtable);
1956 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1957 o = mono_object_allocate (byte_len);
1961 o = mono_object_allocate (byte_len);
1965 ao = (MonoArray *)o;
1968 mono_profiler_allocation (o, vtable->klass);
1974 * mono_string_new_utf16:
1975 * @text: a pointer to an utf16 string
1976 * @len: the length of the string
1978 * Returns: A newly created string object which contains @text.
1981 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1985 s = mono_string_new_size (domain, len);
1986 g_assert (s != NULL);
1988 memcpy (mono_string_chars (s), text, len * 2);
1994 * mono_string_new_size:
1995 * @text: a pointer to an utf16 string
1996 * @len: the length of the string
1998 * Returns: A newly created string object of @len
2001 mono_string_new_size (MonoDomain *domain, gint32 len)
2005 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2007 /* overflow ? can't fit it, can't allocate it! */
2011 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2013 #if CREATION_SPEEDUP
2014 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2015 s = mono_object_allocate_spec (size, vtable);
2017 s = (MonoString*)mono_object_allocate (size);
2018 s->object.vtable = vtable;
2021 s = (MonoString*)mono_object_allocate (size);
2022 s->object.vtable = vtable;
2026 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2032 * mono_string_new_len:
2033 * @text: a pointer to an utf8 string
2034 * @length: number of bytes in @text to consider
2036 * Returns: A newly created string object which contains @text.
2039 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2041 GError *error = NULL;
2042 MonoString *o = NULL;
2044 glong items_written;
2046 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2049 o = mono_string_new_utf16 (domain, ut, items_written);
2051 g_error_free (error);
2060 * @text: a pointer to an utf8 string
2062 * Returns: A newly created string object which contains @text.
2065 mono_string_new (MonoDomain *domain, const char *text)
2067 GError *error = NULL;
2068 MonoString *o = NULL;
2070 glong items_written;
2075 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2078 o = mono_string_new_utf16 (domain, ut, items_written);
2080 g_error_free (error);
2088 * mono_string_new_wrapper:
2089 * @text: pointer to utf8 characters.
2091 * Helper function to create a string object from @text in the current domain.
2094 mono_string_new_wrapper (const char *text)
2096 MonoDomain *domain = mono_domain_get ();
2098 MONO_ARCH_SAVE_REGS;
2101 return mono_string_new (domain, text);
2108 * @class: the class of the value
2109 * @value: a pointer to the unboxed data
2111 * Returns: A newly created object which contains @value.
2114 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2120 g_assert (class->valuetype);
2122 vtable = mono_class_vtable (domain, class);
2123 size = mono_class_instance_size (class);
2124 res = mono_object_allocate (size);
2125 res->vtable = vtable;
2126 mono_profiler_allocation (res, class);
2128 size = size - sizeof (MonoObject);
2130 #if NO_UNALIGNED_ACCESS
2131 memcpy ((char *)res + sizeof (MonoObject), value, size);
2135 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2138 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2141 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2144 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2147 memcpy ((char *)res + sizeof (MonoObject), value, size);
2150 if (class->has_finalize)
2151 mono_object_register_finalizer (res);
2156 mono_object_unbox (MonoObject *obj)
2158 /* add assert for valuetypes? */
2159 return ((char*)obj) + sizeof (MonoObject);
2163 * mono_object_isinst:
2165 * @klass: a pointer to a class
2167 * Returns: @obj if @obj is derived from @klass
2170 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2173 mono_class_init (klass);
2175 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2176 return mono_object_isinst_mbyref (obj, klass);
2181 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2185 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2194 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2195 if ((klass->interface_id <= vt->max_interface_id) &&
2196 (vt->interface_offsets [klass->interface_id] != 0))
2200 MonoClass *oklass = vt->klass;
2201 if ((oklass == mono_defaults.transparent_proxy_class))
2202 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2204 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2208 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2210 MonoDomain *domain = mono_domain_get ();
2212 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2213 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2214 MonoMethod *im = NULL;
2218 for (i = 0; i < rpklass->method.count; ++i) {
2219 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2220 im = rpklass->methods [i];
2225 im = mono_object_get_virtual_method (rp, im);
2228 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2231 res = mono_runtime_invoke (im, rp, pa, NULL);
2233 if (*(MonoBoolean *) mono_object_unbox(res)) {
2234 /* Update the vtable of the remote type, so it can safely cast to this new type */
2235 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2236 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2245 * mono_object_castclass_mbyref:
2247 * @klass: a pointer to a class
2249 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2252 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2254 if (!obj) return NULL;
2255 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2257 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2259 "InvalidCastException"));
2264 MonoDomain *orig_domain;
2270 str_lookup (MonoDomain *domain, gpointer user_data)
2272 LDStrInfo *info = user_data;
2273 if (info->res || domain == info->orig_domain)
2275 mono_domain_lock (domain);
2276 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2277 mono_domain_unlock (domain);
2281 mono_string_is_interned_lookup (MonoString *str, int insert)
2283 MonoGHashTable *ldstr_table;
2286 char *ins = g_malloc (4 + str->length * 2);
2289 /* Encode the length */
2290 /* Same code as in mono_image_insert_string () */
2292 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2295 * ins is stored in the hash table as a key and needs to have the same
2296 * representation as in the metadata: we swap the character bytes on big
2299 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2302 char *p2 = (char *)mono_string_chars (str);
2303 for (i = 0; i < str->length; ++i) {
2310 memcpy (p, mono_string_chars (str), str->length * 2);
2312 domain = ((MonoObject *)str)->vtable->domain;
2313 ldstr_table = domain->ldstr_table;
2314 mono_domain_lock (domain);
2315 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2316 mono_domain_unlock (domain);
2321 mono_g_hash_table_insert (ldstr_table, ins, str);
2322 mono_domain_unlock (domain);
2325 LDStrInfo ldstr_info;
2326 ldstr_info.orig_domain = domain;
2327 ldstr_info.ins = ins;
2328 ldstr_info.res = NULL;
2330 mono_domain_foreach (str_lookup, &ldstr_info);
2331 if (ldstr_info.res) {
2333 * the string was already interned in some other domain:
2334 * intern it in the current one as well.
2336 mono_g_hash_table_insert (ldstr_table, ins, str);
2337 mono_domain_unlock (domain);
2341 mono_domain_unlock (domain);
2347 mono_string_is_interned (MonoString *o)
2349 return mono_string_is_interned_lookup (o, FALSE);
2353 mono_string_intern (MonoString *str)
2355 return mono_string_is_interned_lookup (str, TRUE);
2360 * @domain: the domain where the string will be used.
2361 * @image: a metadata context
2362 * @idx: index into the user string table.
2364 * Implementation for the ldstr opcode.
2367 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2369 const char *str, *sig;
2373 MONO_ARCH_SAVE_REGS;
2376 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2378 sig = str = mono_metadata_user_string (image, idx);
2380 mono_domain_lock (domain);
2381 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2382 mono_domain_unlock (domain);
2386 len2 = mono_metadata_decode_blob_size (str, &str);
2389 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2390 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2393 guint16 *p2 = (guint16*)mono_string_chars (o);
2394 for (i = 0; i < len2; ++i) {
2395 *p2 = GUINT16_FROM_LE (*p2);
2400 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2401 mono_domain_unlock (domain);
2407 * mono_string_to_utf8:
2408 * @s: a System.String
2410 * Return the UTF8 representation for @s.
2411 * the resulting buffer nedds to be freed with g_free().
2414 mono_string_to_utf8 (MonoString *s)
2417 GError *error = NULL;
2423 return g_strdup ("");
2425 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2427 g_warning (error->message);
2428 g_error_free (error);
2435 * mono_string_to_utf16:
2438 * Return an null-terminated array of the utf-16 chars
2439 * contained in @s. The result must be freed with g_free().
2440 * This is a temporary helper until our string implementation
2441 * is reworked to always include the null terminating char.
2444 mono_string_to_utf16 (MonoString *s)
2451 as = g_malloc ((s->length * 2) + 2);
2452 as [(s->length * 2)] = '\0';
2453 as [(s->length * 2) + 1] = '\0';
2456 return (gunichar2 *)(as);
2459 memcpy (as, mono_string_chars(s), s->length * 2);
2460 return (gunichar2 *)(as);
2464 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2467 mono_string_from_utf16 (gunichar2 *data)
2469 MonoDomain *domain = mono_domain_get ();
2475 while (data [len]) len++;
2477 return mono_string_new_utf16 (domain, data, len);
2481 default_ex_handler (MonoException *ex)
2483 MonoObject *o = (MonoObject*)ex;
2484 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2488 static MonoExceptionFunc ex_handler = default_ex_handler;
2491 mono_install_handler (MonoExceptionFunc func)
2493 ex_handler = func? func: default_ex_handler;
2497 * mono_raise_exception:
2498 * @ex: exception object
2500 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2503 mono_raise_exception (MonoException *ex)
2506 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2507 * that will cause gcc to omit the function epilog, causing problems when
2508 * the JIT tries to walk the stack, since the return address on the stack
2509 * will point into the next function in the executable, not this one.
2516 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2518 MonoWaitHandle *res;
2520 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2522 res->handle = handle;
2528 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2530 MonoAsyncResult *res;
2532 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2535 res->async_state = state;
2537 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2539 res->sync_completed = FALSE;
2540 res->completed = FALSE;
2546 mono_message_init (MonoDomain *domain,
2547 MonoMethodMessage *this,
2548 MonoReflectionMethod *method,
2549 MonoArray *out_args)
2551 MonoMethodSignature *sig = method->method->signature;
2557 this->method = method;
2559 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2560 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2561 this->async_result = NULL;
2562 this->call_type = CallType_Sync;
2564 names = g_new (char *, sig->param_count);
2565 mono_method_get_param_names (method->method, (const char **) names);
2566 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2568 for (i = 0; i < sig->param_count; i++) {
2569 name = mono_string_new (domain, names [i]);
2570 mono_array_set (this->names, gpointer, i, name);
2574 for (i = 0, j = 0; i < sig->param_count; i++) {
2576 if (sig->params [i]->byref) {
2578 gpointer arg = mono_array_get (out_args, gpointer, j);
2579 mono_array_set (this->args, gpointer, i, arg);
2583 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2588 mono_array_set (this->arg_types, guint8, i, arg_type);
2593 * mono_remoting_invoke:
2594 * @real_proxy: pointer to a RealProxy object
2595 * @msg: The MonoMethodMessage to execute
2596 * @exc: used to store exceptions
2597 * @out_args: used to store output arguments
2599 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2600 * IMessage interface and it is not trivial to extract results from there. So
2601 * we call an helper method PrivateInvoke instead of calling
2602 * RealProxy::Invoke() directly.
2604 * Returns: the result object.
2607 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2608 MonoObject **exc, MonoArray **out_args)
2610 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2613 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2619 klass = mono_defaults.real_proxy_class;
2621 for (i = 0; i < klass->method.count; ++i) {
2622 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2623 klass->methods [i]->signature->param_count == 4) {
2624 im = klass->methods [i];
2630 real_proxy->vtable->domain->private_invoke_method = im;
2633 pa [0] = real_proxy;
2638 return mono_runtime_invoke (im, NULL, pa, exc);
2642 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2643 MonoObject **exc, MonoArray **out_args)
2647 MonoMethodSignature *sig;
2648 int i, j, outarg_count = 0;
2650 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2652 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2653 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2654 target = tp->rp->unwrapped_server;
2656 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2660 domain = mono_domain_get ();
2661 method = msg->method->method;
2662 sig = method->signature;
2664 for (i = 0; i < sig->param_count; i++) {
2665 if (sig->params [i]->byref)
2669 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2672 for (i = 0, j = 0; i < sig->param_count; i++) {
2673 if (sig->params [i]->byref) {
2675 arg = mono_array_get (msg->args, gpointer, i);
2676 mono_array_set (*out_args, gpointer, j, arg);
2681 return mono_runtime_invoke_array (method, target, msg->args, exc);
2685 mono_print_unhandled_exception (MonoObject *exc)
2687 char *message = (char *) "";
2691 gboolean free_message = FALSE;
2694 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2695 klass = exc->vtable->klass;
2697 while (klass && method == NULL) {
2698 for (i = 0; i < klass->method.count; ++i) {
2699 method = klass->methods [i];
2700 if (!strcmp ("ToString", method->name) &&
2701 method->signature->param_count == 0 &&
2702 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2703 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2710 klass = klass->parent;
2715 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2717 message = mono_string_to_utf8 (str);
2718 free_message = TRUE;
2723 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2724 * exc->vtable->klass->name, message);
2726 g_printerr ("\nUnhandled Exception: %s\n", message);
2733 * mono_delegate_ctor:
2734 * @this: pointer to an uninitialized delegate object
2735 * @target: target object
2736 * @addr: pointer to native code
2738 * This is used to initialize a delegate. We also insert the method_info if
2739 * we find the info with mono_jit_info_table_find().
2742 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2744 MonoDomain *domain = mono_domain_get ();
2745 MonoDelegate *delegate = (MonoDelegate *)this;
2746 MonoMethod *method = NULL;
2753 class = this->vtable->klass;
2755 if ((ji = mono_jit_info_table_find (domain, addr))) {
2756 method = ji->method;
2757 delegate->method_info = mono_method_get_object (domain, method, NULL);
2760 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2762 method = mono_marshal_get_remoting_invoke (method);
2763 delegate->method_ptr = mono_compile_method (method);
2764 delegate->target = target;
2766 delegate->method_ptr = addr;
2767 delegate->target = target;
2772 * mono_method_call_message_new:
2774 * Translates arguments pointers into a Message.
2777 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2778 MonoDelegate **cb, MonoObject **state)
2780 MonoDomain *domain = mono_domain_get ();
2781 MonoMethodSignature *sig = method->signature;
2782 MonoMethodMessage *msg;
2785 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2788 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2789 count = sig->param_count - 2;
2791 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2792 count = sig->param_count;
2795 for (i = 0; i < count; i++) {
2800 if (sig->params [i]->byref)
2801 vpos = *((gpointer *)params [i]);
2805 type = sig->params [i]->type;
2806 class = mono_class_from_mono_type (sig->params [i]);
2808 if (class->valuetype)
2809 arg = mono_value_box (domain, class, vpos);
2811 arg = *((MonoObject **)vpos);
2813 mono_array_set (msg->args, gpointer, i, arg);
2816 if (cb != NULL && state != NULL) {
2817 *cb = *((MonoDelegate **)params [i]);
2819 *state = *((MonoObject **)params [i]);
2826 * mono_method_return_message_restore:
2828 * Restore results from message based processing back to arguments pointers
2831 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2833 MonoMethodSignature *sig = method->signature;
2834 int i, j, type, size;
2835 for (i = 0, j = 0; i < sig->param_count; i++) {
2836 MonoType *pt = sig->params [i];
2839 char *arg = mono_array_get (out_args, gpointer, j);
2843 case MONO_TYPE_VOID:
2844 g_assert_not_reached ();
2848 case MONO_TYPE_BOOLEAN:
2851 case MONO_TYPE_CHAR:
2858 case MONO_TYPE_VALUETYPE: {
2859 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2860 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2863 case MONO_TYPE_STRING:
2864 case MONO_TYPE_CLASS:
2865 case MONO_TYPE_ARRAY:
2866 case MONO_TYPE_SZARRAY:
2867 case MONO_TYPE_OBJECT:
2868 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2871 g_assert_not_reached ();
2880 * mono_load_remote_field:
2881 * @this: pointer to an object
2882 * @klass: klass of the object containing @field
2883 * @field: the field to load
2884 * @res: a storage to store the result
2886 * This method is called by the runtime on attempts to load fields of
2887 * transparent proxy objects. @this points to such TP, @klass is the class of
2888 * the object containing @field. @res is a storage location which can be
2889 * used to store the result.
2891 * Returns: an address pointing to the value of field.
2894 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2896 static MonoMethod *getter = NULL;
2897 MonoDomain *domain = mono_domain_get ();
2898 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2899 MonoClass *field_class;
2900 MonoMethodMessage *msg;
2901 MonoArray *out_args;
2905 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2910 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2911 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2918 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2919 MonoMethod *cm = mono_defaults.object_class->methods [i];
2921 if (!strcmp (cm->name, "FieldGetter")) {
2929 field_class = mono_class_from_mono_type (field->type);
2931 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2932 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2933 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2935 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2936 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2938 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2940 if (exc) mono_raise_exception ((MonoException *)exc);
2942 *res = mono_array_get (out_args, MonoObject *, 0);
2944 if (field_class->valuetype) {
2945 return ((char *)*res) + sizeof (MonoObject);
2951 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2953 static MonoMethod *getter = NULL;
2954 MonoDomain *domain = mono_domain_get ();
2955 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2956 MonoClass *field_class;
2957 MonoMethodMessage *msg;
2958 MonoArray *out_args;
2959 MonoObject *exc, *res;
2961 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2963 field_class = mono_class_from_mono_type (field->type);
2965 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2967 if (field_class->valuetype) {
2968 res = mono_object_new (domain, field_class);
2969 val = ((gchar *) res) + sizeof (MonoObject);
2973 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2980 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2981 MonoMethod *cm = mono_defaults.object_class->methods [i];
2983 if (!strcmp (cm->name, "FieldGetter")) {
2991 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2992 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2993 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2995 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2996 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2998 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3000 if (exc) mono_raise_exception ((MonoException *)exc);
3002 res = mono_array_get (out_args, MonoObject *, 0);
3008 * mono_store_remote_field:
3009 * @this: pointer to an object
3010 * @klass: klass of the object containing @field
3011 * @field: the field to load
3012 * @val: the value/object to store
3014 * This method is called by the runtime on attempts to store fields of
3015 * transparent proxy objects. @this points to such TP, @klass is the class of
3016 * the object containing @field. @val is the new value to store in @field.
3019 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3021 static MonoMethod *setter = NULL;
3022 MonoDomain *domain = mono_domain_get ();
3023 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3024 MonoClass *field_class;
3025 MonoMethodMessage *msg;
3026 MonoArray *out_args;
3030 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3032 field_class = mono_class_from_mono_type (field->type);
3034 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3035 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3036 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3043 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3044 MonoMethod *cm = mono_defaults.object_class->methods [i];
3046 if (!strcmp (cm->name, "FieldSetter")) {
3054 if (field_class->valuetype)
3055 arg = mono_value_box (domain, field_class, val);
3057 arg = *((MonoObject **)val);
3060 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3061 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3063 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3064 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3065 mono_array_set (msg->args, gpointer, 2, arg);
3067 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3069 if (exc) mono_raise_exception ((MonoException *)exc);
3073 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3075 static MonoMethod *setter = NULL;
3076 MonoDomain *domain = mono_domain_get ();
3077 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3078 MonoClass *field_class;
3079 MonoMethodMessage *msg;
3080 MonoArray *out_args;
3083 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3085 field_class = mono_class_from_mono_type (field->type);
3087 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3088 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3089 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3096 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3097 MonoMethod *cm = mono_defaults.object_class->methods [i];
3099 if (!strcmp (cm->name, "FieldSetter")) {
3107 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3108 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3110 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3111 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3112 mono_array_set (msg->args, gpointer, 2, arg);
3114 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3116 if (exc) mono_raise_exception ((MonoException *)exc);