2 * object.c: Object creation for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
14 #include <mono/metadata/mono-endian.h>
15 #include <mono/metadata/tabledefs.h>
16 #include <mono/metadata/tokentype.h>
17 #include <mono/metadata/loader.h>
18 #include <mono/metadata/object.h>
19 #include <mono/metadata/gc-internal.h>
20 #include <mono/metadata/exception.h>
21 #include <mono/metadata/appdomain.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/threadpool.h>
24 #include <mono/metadata/marshal.h>
25 #include "mono/metadata/debug-helpers.h"
26 #include "mono/metadata/marshal.h"
27 #include <mono/metadata/threads.h>
28 #include <mono/metadata/environment.h>
29 #include "mono/metadata/profiler-private.h"
30 #include <mono/os/gc_wrapper.h>
33 * enable to get a good speedup: we still need to figure out
34 * how the sync structure is freed.
36 #define CREATION_SPEEDUP 0
39 mono_runtime_object_init (MonoObject *this)
42 MonoMethod *method = NULL;
43 MonoClass *klass = this->vtable->klass;
45 for (i = 0; i < klass->method.count; ++i) {
46 if (!strcmp (".ctor", klass->methods [i]->name) &&
47 klass->methods [i]->signature->param_count == 0) {
48 method = klass->methods [i];
55 mono_runtime_invoke (method, this, NULL, NULL);
59 * mono_runtime_class_init:
60 * @klass: klass that needs to be initialized
62 * This routine calls the class constructor for @class.
65 mono_runtime_class_init (MonoClass *klass)
68 MonoException *exc = NULL;
69 MonoException *exc_to_throw;
73 for (i = 0; i < klass->method.count; ++i) {
74 method = klass->methods [i];
75 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
76 (strcmp (".cctor", method->name) == 0)) {
77 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
85 (klass->image == mono_defaults.corlib &&
86 !strcmp (klass->name_space, "System") &&
87 !strcmp (klass->name, "TypeInitializationException")))
88 return; /* No static constructor found or avoid infinite loop */
90 if (klass->name_space && *klass->name_space)
91 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
93 full_name = g_strdup (klass->name);
95 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
98 mono_raise_exception (exc_to_throw);
102 default_trampoline (MonoMethod *method)
108 default_remoting_trampoline (MonoMethod *method)
110 g_error ("remoting not installed");
114 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
115 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
118 mono_install_trampoline (MonoTrampoline func)
120 arch_create_jit_trampoline = func? func: default_trampoline;
124 mono_install_remoting_trampoline (MonoTrampoline func)
126 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
129 static MonoCompileFunc default_mono_compile_method = NULL;
132 mono_install_compile_method (MonoCompileFunc func)
134 default_mono_compile_method = func;
138 mono_compile_method (MonoMethod *method)
140 if (!default_mono_compile_method) {
141 g_error ("compile method called on uninitialized runtime");
144 return default_mono_compile_method (method);
148 #if 0 && HAVE_BOEHM_GC
150 vtable_finalizer (void *obj, void *data) {
151 g_print ("%s finalized (%p)\n", (char*)data, obj);
157 * @domain: the application domain
158 * @class: the class to initialize
160 * VTables are domain specific because we create domain specific code, and
161 * they contain the domain specific static class data.
164 mono_class_vtable (MonoDomain *domain, MonoClass *class)
167 MonoClassField *field;
169 guint32 cols [MONO_CONSTANT_SIZE];
176 vt = class->cached_vtable;
177 if (vt && vt->domain == domain)
180 mono_domain_lock (domain);
181 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
182 mono_domain_unlock (domain);
187 mono_class_init (class);
189 mono_stats.used_class_count++;
190 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
192 vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) +
193 class->vtable_size * sizeof (gpointer));
197 if (class->class_size) {
199 vt->data = GC_MALLOC (class->class_size + 8);
200 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
201 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
202 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
204 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
207 mono_stats.class_static_data_size += class->class_size + 8;
210 for (i = class->field.first; i < class->field.last; ++i) {
211 field = &class->fields [i - class->field.first];
212 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
214 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
215 MonoClass *fklass = mono_class_from_mono_type (field->type);
216 t = (char*)vt->data + field->offset;
217 if (fklass->valuetype) {
218 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
220 /* it's a pointer type: add check */
221 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
222 *t = *(char *)field->data;
226 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
228 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1));
230 g_warning ("constant for field %s not found", field->name);
233 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
234 p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
235 len = mono_metadata_decode_blob_size (p, &p);
236 t = (char*)vt->data + field->offset;
237 /* should we check that the type matches? */
238 switch (cols [MONO_CONSTANT_TYPE]) {
239 case MONO_TYPE_BOOLEAN:
247 guint16 *val = (guint16*)t;
253 guint32 *val = (guint32*)t;
259 guint64 *val = (guint64*)t;
264 float *val = (float*)t;
269 double *val = (double*)t;
273 case MONO_TYPE_STRING: {
274 gpointer *val = (gpointer*)t;
275 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
276 gunichar2 *copy = g_malloc (len);
278 for (j = 0; j < len/2; j++) {
279 copy [j] = read16 (p);
282 *val = mono_string_new_utf16 (domain, copy, len/2);
285 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
289 case MONO_TYPE_CLASS:
290 /* nothing to do, we malloc0 the data and the value can be 0 only */
293 g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]);
297 vt->max_interface_id = class->max_interface_id;
299 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
300 sizeof (gpointer) * (class->max_interface_id + 1));
302 /* initialize interface offsets */
303 for (i = 0; i <= class->max_interface_id; ++i) {
304 int slot = class->interface_offsets [i];
306 vt->interface_offsets [i] = &(vt->vtable [slot]);
310 * arch_create_jit_trampoline () can recursively call this function again
311 * because it compiles icall methods right away.
313 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
314 if (!class->cached_vtable)
315 class->cached_vtable = vt;
317 /* initialize vtable */
318 for (i = 0; i < class->vtable_size; ++i) {
321 if ((cm = class->vtable [i]))
322 vt->vtable [i] = arch_create_jit_trampoline (cm);
325 mono_domain_unlock (domain);
327 /* make sure the the parent is initialized */
329 mono_class_vtable (domain, class->parent);
331 mono_runtime_class_init (class);
333 if (class->contextbound)
342 * mono_class_proxy_vtable:
343 * @domain: the application domain
344 * @class: the class to proxy
346 * Creates a vtable for transparent proxies. It is basically
347 * a copy of the real vtable of @class, but all function pointers invoke
348 * the remoting functions, and vtable->klass points to the
349 * transparent proxy class, and not to @class.
352 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
354 MonoVTable *vt, *pvt;
355 int i, j, vtsize, interface_vtsize = 0;
356 MonoClass* iclass = NULL;
359 if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
362 if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
365 class = mono_defaults.marshalbyrefobject_class;
367 method_count = iclass->method.count;
368 for (i = 0; i < iclass->interface_count; i++)
369 method_count += iclass->interfaces[i]->method.count;
371 interface_vtsize = method_count * sizeof (gpointer);
374 vt = mono_class_vtable (domain, class);
375 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
377 mono_stats.class_vtable_size += vtsize + interface_vtsize;
379 pvt = mono_mempool_alloc (domain->mp, vtsize + interface_vtsize);
380 memcpy (pvt, vt, vtsize);
382 pvt->klass = mono_defaults.transparent_proxy_class;
384 /* initialize vtable */
385 for (i = 0; i < class->vtable_size; ++i) {
388 if ((cm = class->vtable [i]))
389 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
392 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
394 /* create trampolines for abstract methods */
395 for (k = class; k; k = k->parent) {
396 for (i = 0; i < k->method.count; i++) {
397 int slot = k->methods [i]->slot;
398 if (!pvt->vtable [slot])
399 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
409 pvt->max_interface_id = iclass->max_interface_id;
411 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
412 sizeof (gpointer) * (pvt->max_interface_id + 1));
414 /* Create trampolines for the methods of the interfaces */
415 slot = class->vtable_size;
419 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
421 for (j = 0; j < interf->method.count; ++j) {
422 MonoMethod *cm = interf->methods [j];
423 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
425 slot += interf->method.count;
426 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
434 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
440 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
441 * the instance of a callvirt of method.
444 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
450 klass = mono_object_class (obj);
451 if (klass == mono_defaults.transparent_proxy_class) {
452 klass = ((MonoTransparentProxy *)obj)->klass;
458 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
461 vtable = klass->vtable;
463 /* check method->slot is a valid index: perform isinstance? */
464 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
465 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
467 res = vtable [method->slot];
472 return mono_marshal_get_remoting_invoke (res);
478 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
480 g_error ("runtime invoke called on uninitialized runtime");
484 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
487 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
489 return default_mono_runtime_invoke (method, obj, params, exc);
493 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
496 gpointer *p = (gpointer*)dest;
503 case MONO_TYPE_BOOLEAN:
506 guint8 *p = (guint8*)dest;
507 *p = *(guint8*)value;
512 case MONO_TYPE_CHAR: {
513 guint16 *p = (guint16*)dest;
514 *p = *(guint16*)value;
517 #if SIZEOF_VOID_P == 4
523 gint32 *p = (gint32*)dest;
524 *p = *(gint32*)value;
527 #if SIZEOF_VOID_P == 8
533 gint64 *p = (gint64*)dest;
534 *p = *(gint64*)value;
538 float *p = (float*)dest;
543 double *p = (double*)dest;
544 *p = *(double*)value;
547 case MONO_TYPE_STRING:
548 case MONO_TYPE_SZARRAY:
549 case MONO_TYPE_CLASS:
550 case MONO_TYPE_OBJECT:
551 case MONO_TYPE_ARRAY:
552 case MONO_TYPE_PTR: {
553 gpointer *p = (gpointer*)dest;
554 *p = deref_pointer? *(gpointer*)value: value;
557 case MONO_TYPE_VALUETYPE:
558 if (type->data.klass->enumtype) {
559 t = type->data.klass->enum_basetype->type;
563 size = mono_class_value_size (type->data.klass, NULL);
564 memcpy (dest, value, size);
568 g_warning ("got type %x", type->type);
569 g_assert_not_reached ();
574 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
578 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
580 dest = (char*)obj + field->offset;
581 set_value (field->type, dest, value, FALSE);
585 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
589 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
591 dest = (char*)vt->data + field->offset;
592 set_value (field->type, dest, value, FALSE);
596 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
600 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
602 src = (char*)obj + field->offset;
603 set_value (field->type, value, src, TRUE);
607 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
611 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
613 src = (char*)vt->data + field->offset;
614 set_value (field->type, value, src, TRUE);
618 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
620 default_mono_runtime_invoke (prop->set, obj, params, exc);
624 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
626 return default_mono_runtime_invoke (prop->get, obj, params, exc);
631 mono_get_delegate_invoke (MonoClass *klass)
638 for (i = 0; i < klass->method.count; ++i) {
639 if (klass->methods [i]->name[0] == 'I' &&
640 !strcmp ("Invoke", klass->methods [i]->name)) {
641 im = klass->methods [i];
651 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
655 im = mono_get_delegate_invoke (delegate->vtable->klass);
658 return mono_runtime_invoke (im, delegate, params, exc);
661 static MonoArray* main_args;
664 mono_runtime_get_main_args (void)
670 * Execute a standard Main() method (argc/argv contains the
671 * executable name). This method also sets the command line argument value
672 * needed by System.Environment.
675 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
679 MonoArray *args = NULL;
680 MonoDomain *domain = mono_domain_get ();
682 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
684 if (!g_path_is_absolute (argv [0])) {
685 gchar *basename = g_path_get_basename (argv [0]);
686 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
690 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, fullpath));
694 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, argv [0]));
697 for (i = 1; i < argc; ++i) {
698 MonoString *arg = mono_string_new (domain, argv [i]);
699 mono_array_set (main_args, gpointer, i, arg);
703 if (method->signature->param_count) {
704 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
705 for (i = 0; i < argc; ++i) {
706 MonoString *arg = mono_string_new (domain, argv [i]);
707 mono_array_set (args, gpointer, i, arg);
710 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
713 mono_assembly_set_main (method->klass->image->assembly);
715 return mono_runtime_exec_main (method, args, exc);
719 * We call this function when we dectect an unhandled exception. It invokes the
720 * UnhandledException event in AppDomain or print a warning to the console
723 mono_unhandled_exception (MonoObject *exc)
725 MonoDomain *domain = mono_domain_get ();
726 MonoClassField *field;
727 MonoObject *delegate;
729 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
730 "UnhandledException");
733 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
734 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
737 mono_print_unhandled_exception (exc);
739 MonoObject *e = NULL;
742 /* fixme: pass useful arguments */
745 mono_runtime_delegate_invoke (delegate, pa, &e);
748 g_warning ("exception inside UnhandledException handler!");
754 * Launch a new thread to start all setup that requires managed code
757 * main_func is called back from the thread with main_args as the
758 * parameter. The callback function is expected to start Main()
759 * eventually. This function then waits for all managed threads to
763 mono_runtime_exec_managed_code (MonoDomain *domain,
764 MonoMainThreadFunc main_func,
767 mono_thread_create (domain, main_func, main_args);
769 mono_thread_manage ();
773 * Execute a standard Main() method (args doesn't contain the
777 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
787 domain = mono_object_domain (args);
788 if (!domain->entry_assembly) {
789 domain->entry_assembly = method->klass->image->assembly;
790 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
793 /* FIXME: check signature of method */
794 if (method->signature->ret->type == MONO_TYPE_I4) {
796 res = mono_runtime_invoke (method, NULL, pa, exc);
798 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
802 mono_environment_exitcode_set (rval);
804 mono_runtime_invoke (method, NULL, pa, exc);
808 /* If the return type of Main is void, only
809 * set the exitcode if an exception was thrown
810 * (we don't want to blow away an
811 * explicitly-set exit code)
814 mono_environment_exitcode_set (rval);
822 mono_install_runtime_invoke (MonoInvokeFunc func)
824 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
828 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
831 MonoMethodSignature *sig = method->signature;
835 if (NULL != params) {
836 pa = alloca (sizeof (gpointer) * mono_array_length (params));
837 for (i = 0; i < mono_array_length (params); i++) {
838 if (sig->params [i]->byref) {
842 switch (sig->params [i]->type) {
845 case MONO_TYPE_BOOLEAN:
857 case MONO_TYPE_VALUETYPE:
858 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
860 case MONO_TYPE_STRING:
861 case MONO_TYPE_OBJECT:
862 case MONO_TYPE_CLASS:
863 case MONO_TYPE_ARRAY:
864 case MONO_TYPE_SZARRAY:
865 if (sig->params [i]->byref)
866 pa [i] = &(((gpointer *)params->vector)[i]);
868 pa [i] = (char *)(((gpointer *)params->vector)[i]);
871 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
876 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
878 obj = mono_object_new (mono_domain_get (), method->klass);
879 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
880 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
883 mono_runtime_invoke (method, obj, pa, exc);
886 return mono_runtime_invoke (method, obj, pa, exc);
890 * mono_object_allocate:
891 * @size: number of bytes to allocate
893 * This is a very simplistic routine until we have our GC-aware
896 * Returns: an allocated object of size @size, or NULL on failure.
899 mono_object_allocate (size_t size)
902 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
903 void *o = GC_MALLOC (size);
905 void *o = calloc (1, size);
908 mono_stats.new_object_count++;
916 * Frees the memory used by the object. Debugging purposes
917 * only, as we will have our GC system.
920 mono_object_free (MonoObject *o)
923 g_error ("mono_object_free called with boehm gc.");
925 MonoClass *c = o->vtable->klass;
927 memset (o, 0, c->instance_size);
934 * @klass: the class of the object that we want to create
936 * Returns: A newly created object whose definition is
937 * looked up using @klass
940 mono_object_new (MonoDomain *domain, MonoClass *klass)
942 return mono_object_new_specific (mono_class_vtable (domain, klass));
946 * mono_object_new_specific:
947 * @vtable: the vtable of the object that we want to create
949 * Returns: A newly created object with class and domain specified
953 mono_object_new_specific (MonoVTable *vtable)
960 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
963 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
967 mono_class_init (klass);
969 for (i = 0; i < klass->method.count; ++i) {
970 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
971 klass->methods [i]->signature->param_count == 1) {
972 im = klass->methods [i];
977 vtable->domain->create_proxy_for_type_method = im;
980 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
982 o = mono_runtime_invoke (im, NULL, pa, NULL);
983 if (o != NULL) return o;
986 return mono_object_new_alloc_specific (vtable);
990 mono_object_new_alloc_specific (MonoVTable *vtable)
992 MonoObject *o = mono_object_allocate (vtable->klass->instance_size);
994 if (vtable->klass->has_finalize)
995 mono_object_register_finalizer (o);
997 mono_profiler_allocation (o, vtable->klass);
1002 * mono_object_new_from_token:
1003 * @image: Context where the type_token is hosted
1004 * @token: a token of the type that we want to create
1006 * Returns: A newly created object whose definition is
1007 * looked up using @token in the @image image
1010 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1014 class = mono_class_get (image, token);
1016 return mono_object_new (domain, class);
1021 * mono_object_clone:
1022 * @obj: the object to clone
1024 * Returns: A newly created object who is a shallow copy of @obj
1027 mono_object_clone (MonoObject *obj)
1032 size = obj->vtable->klass->instance_size;
1033 o = mono_object_allocate (size);
1034 mono_profiler_allocation (o, obj->vtable->klass);
1036 memcpy (o, obj, size);
1038 if (obj->vtable->klass->has_finalize)
1039 mono_object_register_finalizer (o);
1045 * @array: the array to clone
1047 * Returns: A newly created array who is a shallow copy of @array
1050 mono_array_clone (MonoArray *array)
1055 MonoClass *klass = array->obj.vtable->klass;
1057 MONO_ARCH_SAVE_REGS;
1059 if (array->bounds == NULL) {
1060 size = mono_array_length (array);
1061 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1062 klass, &size, NULL);
1064 size *= mono_array_element_size (klass);
1065 memcpy (o, array, sizeof (MonoArray) + size);
1070 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1071 size = mono_array_element_size (klass);
1072 for (i = 0; i < klass->rank; ++i) {
1073 sizes [i] = array->bounds [i].length;
1074 size *= array->bounds [i].length;
1075 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1077 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1078 klass, sizes, sizes + klass->rank);
1079 memcpy (o, array, sizeof(MonoArray) + size);
1085 * mono_array_new_full:
1086 * @domain: domain where the object is created
1087 * @array_class: array class
1088 * @lengths: lengths for each dimension in the array
1089 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1091 * This routine creates a new array objects with the given dimensions,
1092 * lower bounds and type.
1095 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1096 guint32 *lengths, guint32 *lower_bounds)
1098 guint32 byte_len, len;
1101 MonoArrayBounds *bounds;
1104 if (!array_class->inited)
1105 mono_class_init (array_class);
1107 byte_len = mono_array_element_size (array_class);
1110 if (array_class->rank == 1 &&
1111 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1116 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1118 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1120 for (i = 0; i < array_class->rank; ++i) {
1121 bounds [i].length = lengths [i];
1126 for (i = 0; i < array_class->rank; ++i)
1127 bounds [i].lower_bound = lower_bounds [i];
1132 * Following three lines almost taken from mono_object_new ():
1133 * they need to be kept in sync.
1135 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1138 o->vtable = mono_class_vtable (domain, array_class);
1140 array = (MonoArray*)o;
1142 array->bounds = bounds;
1143 array->max_length = len;
1145 mono_profiler_allocation (o, array_class);
1152 * @domain: domain where the object is created
1153 * @eclass: element class
1154 * @n: number of array elements
1156 * This routine creates a new szarray with @n elements of type @eclass.
1159 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1163 ac = mono_array_class_get (&eclass->byval_arg, 1);
1164 g_assert (ac != NULL);
1166 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1170 * mono_array_new_specific:
1171 * @vtable: a vtable in the appropriate domain for an initialized class
1172 * @n: number of array elements
1174 * This routine is a fast alternative to mono_array_new() for code which
1175 * can be sure about the domain it operates in.
1178 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1184 byte_len = n * mono_array_element_size (vtable->klass);
1185 #if CREATION_SPEEDUP
1186 if (vtable->klass->element_class->byval_arg.type >= MONO_TYPE_BOOLEAN && vtable->klass->element_class->byval_arg.type <= MONO_TYPE_R4) {
1187 o = GC_MALLOC_ATOMIC (sizeof (MonoArray) + byte_len);
1188 o->synchronisation = 0;
1189 memset (((MonoArray*)o)->vector, 0, byte_len);
1191 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1194 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1200 ao = (MonoArray *)o;
1203 mono_profiler_allocation (o, vtable->klass);
1209 * mono_string_new_utf16:
1210 * @text: a pointer to an utf16 string
1211 * @len: the length of the string
1213 * Returns: A newly created string object which contains @text.
1216 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1220 s = mono_string_new_size (domain, len);
1221 g_assert (s != NULL);
1223 memcpy (mono_string_chars (s), text, len * 2);
1229 * mono_string_new_size:
1230 * @text: a pointer to an utf16 string
1231 * @len: the length of the string
1233 * Returns: A newly created string object of @len
1236 mono_string_new_size (MonoDomain *domain, gint32 len)
1240 #if CREATION_SPEEDUP
1241 s = GC_MALLOC_ATOMIC (sizeof (MonoString) + ((len + 1) * 2));
1242 s->object.synchronisation = 0;
1243 mono_string_chars (s) [len] = 0;
1245 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1250 s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class);
1252 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1258 * mono_string_new_len:
1259 * @text: a pointer to an utf8 string
1260 * @length: number of bytes in @text to consider
1262 * Returns: A newly created string object which contains @text.
1265 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1267 GError *error = NULL;
1268 MonoString *o = NULL;
1270 glong items_written;
1273 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1276 o = mono_string_new_utf16 (domain, ut, items_written);
1278 g_error_free (error);
1287 * @text: a pointer to an utf8 string
1289 * Returns: A newly created string object which contains @text.
1292 mono_string_new (MonoDomain *domain, const char *text)
1294 GError *error = NULL;
1295 MonoString *o = NULL;
1297 glong items_written;
1302 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1305 o = mono_string_new_utf16 (domain, ut, items_written);
1307 g_error_free (error);
1315 * mono_string_new_wrapper:
1316 * @text: pointer to utf8 characters.
1318 * Helper function to create a string object from @text in the current domain.
1321 mono_string_new_wrapper (const char *text)
1323 MonoDomain *domain = mono_domain_get ();
1326 return mono_string_new (domain, text);
1333 * @class: the class of the value
1334 * @value: a pointer to the unboxed data
1336 * Returns: A newly created object which contains @value.
1339 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1344 g_assert (class->valuetype);
1346 size = mono_class_instance_size (class);
1347 res = mono_object_allocate (size);
1348 res->vtable = mono_class_vtable (domain, class);
1349 mono_profiler_allocation (res, class);
1351 size = size - sizeof (MonoObject);
1353 #if NO_UNALIGNED_ACCESS
1354 memcpy ((char *)res + sizeof (MonoObject), value, size);
1358 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1361 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1364 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1367 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1370 memcpy ((char *)res + sizeof (MonoObject), value, size);
1373 if (class->has_finalize)
1374 mono_object_register_finalizer (res);
1379 * mono_object_isinst:
1381 * @klass: a pointer to a class
1383 * Returns: @obj if @obj is derived from @klass
1386 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1398 mono_class_init (klass);
1400 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1401 if ((klass->interface_id <= vt->max_interface_id) &&
1402 vt->interface_offsets [klass->interface_id])
1405 if (oklass == mono_defaults.transparent_proxy_class) {
1406 /* fixme: add check for IRemotingTypeInfo */
1407 oklass = ((MonoTransparentProxy *)obj)->klass;
1410 if (oklass->rank == klass->rank &&
1411 (oklass->cast_class->baseval - klass->cast_class->baseval) <=
1412 klass->cast_class->diffval)
1415 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
1423 mono_string_is_interned_lookup (MonoString *str, int insert)
1425 MonoGHashTable *ldstr_table;
1428 char *ins = g_malloc (4 + str->length * 2);
1432 /* Encode the length */
1434 mono_metadata_encode_value (2 * str->length, p, &p);
1437 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1438 bloblen = (p - ins) + 2 * str->length;
1440 * ins is stored in the hash table as a key and needs to have the same
1441 * representation as in the metadata: we swap the character bytes on big
1444 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1447 char *p2 = mono_string_chars (str);
1448 for (i = 0; i < str->length; ++i) {
1455 memcpy (p, mono_string_chars (str), str->length * 2);
1457 domain = ((MonoObject *)str)->vtable->domain;
1458 ldstr_table = domain->ldstr_table;
1459 mono_domain_lock (domain);
1460 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1461 mono_domain_unlock (domain);
1466 mono_g_hash_table_insert (ldstr_table, ins, str);
1467 mono_domain_unlock (domain);
1470 mono_domain_unlock (domain);
1476 mono_string_is_interned (MonoString *o)
1478 return mono_string_is_interned_lookup (o, FALSE);
1482 mono_string_intern (MonoString *str)
1484 return mono_string_is_interned_lookup (str, TRUE);
1489 * @domain: the domain where the string will be used.
1490 * @image: a metadata context
1491 * @idx: index into the user string table.
1493 * Implementation for the ldstr opcode.
1496 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1498 const char *str, *sig;
1502 MONO_ARCH_SAVE_REGS;
1504 if (image->assembly->dynamic)
1505 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
1507 sig = str = mono_metadata_user_string (image, idx);
1509 mono_domain_lock (domain);
1510 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1511 mono_domain_unlock (domain);
1515 len2 = mono_metadata_decode_blob_size (str, &str);
1518 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1519 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1522 guint16 *p2 = (guint16*)mono_string_chars (o);
1523 for (i = 0; i < len2; ++i) {
1524 *p2 = GUINT16_FROM_LE (*p2);
1529 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1530 mono_domain_unlock (domain);
1536 * mono_string_to_utf8:
1537 * @s: a System.String
1539 * Return the UTF8 representation for @s.
1540 * the resulting buffer nedds to be freed with g_free().
1543 mono_string_to_utf8 (MonoString *s)
1546 GError *error = NULL;
1552 return g_strdup ("");
1554 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1556 g_warning (error->message);
1562 * mono_string_to_utf16:
1565 * Return an null-terminated array of the utf-16 chars
1566 * contained in @s. The result must be freed with g_free().
1567 * This is a temporary helper until our string implementation
1568 * is reworked to always include the null terminating char.
1571 mono_string_to_utf16 (MonoString *s)
1578 as = g_malloc ((s->length * 2) + 2);
1579 as [(s->length * 2)] = '\0';
1580 as [(s->length * 2) + 1] = '\0';
1583 return (gunichar2 *)(as);
1586 memcpy (as, mono_string_chars(s), s->length * 2);
1587 return (gunichar2 *)(as);
1591 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
1594 mono_string_from_utf16 (gunichar2 *data)
1596 MonoDomain *domain = mono_domain_get ();
1602 while (data [len]) len++;
1604 return mono_string_new_utf16 (domain, data, len);
1608 default_ex_handler (MonoException *ex)
1610 MonoObject *o = (MonoObject*)ex;
1611 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1614 static MonoExceptionFunc ex_handler = default_ex_handler;
1617 mono_install_handler (MonoExceptionFunc func)
1619 ex_handler = func? func: default_ex_handler;
1623 * mono_raise_exception:
1624 * @ex: exception object
1626 * Signal the runtime that the exception @ex has been raised in unmanaged code.
1629 mono_raise_exception (MonoException *ex)
1635 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1637 MonoWaitHandle *res;
1639 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1641 res->handle = handle;
1647 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
1649 MonoAsyncResult *res;
1651 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
1654 res->async_state = state;
1655 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
1656 res->sync_completed = FALSE;
1657 res->completed = FALSE;
1663 mono_message_init (MonoDomain *domain,
1664 MonoMethodMessage *this,
1665 MonoReflectionMethod *method,
1666 MonoArray *out_args)
1668 MonoMethodSignature *sig = method->method->signature;
1674 this->method = method;
1676 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
1677 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
1679 names = g_new (char *, sig->param_count);
1680 mono_method_get_param_names (method->method, (const char **) names);
1681 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
1683 for (i = 0; i < sig->param_count; i++) {
1684 name = mono_string_new (domain, names [i]);
1685 mono_array_set (this->names, gpointer, i, name);
1690 for (i = 0, j = 0; i < sig->param_count; i++) {
1692 if (sig->params [i]->byref) {
1694 gpointer arg = mono_array_get (out_args, gpointer, j);
1695 mono_array_set (this->args, gpointer, i, arg);
1699 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
1705 mono_array_set (this->arg_types, guint8, i, arg_type);
1710 * mono_remoting_invoke:
1711 * @real_proxy: pointer to a RealProxy object
1712 * @msg: The MonoMethodMessage to execute
1713 * @exc: used to store exceptions
1714 * @out_args: used to store output arguments
1716 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
1717 * IMessage interface and it is not trivial to extract results from there. So
1718 * we call an helper method PrivateInvoke instead of calling
1719 * RealProxy::Invoke() directly.
1721 * Returns: the result object.
1724 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
1725 MonoObject **exc, MonoArray **out_args)
1727 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
1730 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
1736 klass = mono_defaults.real_proxy_class;
1738 for (i = 0; i < klass->method.count; ++i) {
1739 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
1740 klass->methods [i]->signature->param_count == 4) {
1741 im = klass->methods [i];
1747 real_proxy->vtable->domain->private_invoke_method = im;
1750 pa [0] = real_proxy;
1755 return mono_runtime_invoke (im, NULL, pa, exc);
1759 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
1760 MonoObject **exc, MonoArray **out_args)
1764 MonoMethodSignature *sig;
1765 int i, j, outarg_count = 0;
1767 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1769 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
1770 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
1771 target = tp->rp->unwrapped_server;
1773 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
1777 domain = mono_domain_get ();
1778 method = msg->method->method;
1779 sig = method->signature;
1781 for (i = 0; i < sig->param_count; i++) {
1782 if (sig->params [i]->byref)
1786 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
1789 for (i = 0, j = 0; i < sig->param_count; i++) {
1790 if (sig->params [i]->byref) {
1792 arg = mono_array_get (msg->args, gpointer, i);
1793 mono_array_set (*out_args, gpointer, j, arg);
1798 return mono_runtime_invoke_array (method, target, msg->args, exc);
1802 mono_print_unhandled_exception (MonoObject *exc)
1804 char *message = (char *) "";
1808 gboolean free_message = FALSE;
1811 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1812 klass = exc->vtable->klass;
1814 while (klass && method == NULL) {
1815 for (i = 0; i < klass->method.count; ++i) {
1816 method = klass->methods [i];
1817 if (!strcmp ("ToString", method->name) &&
1818 method->signature->param_count == 0 &&
1819 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
1820 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
1827 klass = klass->parent;
1832 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
1834 message = mono_string_to_utf8 (str);
1835 free_message = TRUE;
1840 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
1841 * exc->vtable->klass->name, message);
1843 g_printerr ("\nUnhandled Exception: %s\n", message);
1850 * mono_delegate_ctor:
1851 * @this: pointer to an uninitialized delegate object
1852 * @target: target object
1853 * @addr: pointer to native code
1855 * This is used to initialize a delegate. We also insert the method_info if
1856 * we find the info with mono_jit_info_table_find().
1859 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
1861 MonoDomain *domain = mono_domain_get ();
1862 MonoDelegate *delegate = (MonoDelegate *)this;
1863 MonoMethod *method = NULL;
1870 class = this->vtable->klass;
1872 if ((ji = mono_jit_info_table_find (domain, addr))) {
1873 method = ji->method;
1874 delegate->method_info = mono_method_get_object (domain, method, NULL);
1877 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1879 method = mono_marshal_get_remoting_invoke (method);
1880 delegate->method_ptr = mono_compile_method (method);
1881 delegate->target = target;
1883 delegate->method_ptr = addr;
1884 delegate->target = target;
1889 * mono_method_call_message_new:
1891 * Translates arguments pointers into a Message.
1894 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
1895 MonoDelegate **cb, MonoObject **state)
1897 MonoDomain *domain = mono_domain_get ();
1898 MonoMethodSignature *sig = method->signature;
1899 MonoMethodMessage *msg;
1902 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1905 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
1906 count = sig->param_count - 2;
1908 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
1909 count = sig->param_count;
1912 for (i = 0; i < count; i++) {
1917 if (sig->params [i]->byref)
1918 vpos = *((gpointer *)params [i]);
1922 type = sig->params [i]->type;
1923 class = mono_class_from_mono_type (sig->params [i]);
1925 if (class->valuetype)
1926 arg = mono_value_box (domain, class, vpos);
1928 arg = *((MonoObject **)vpos);
1930 mono_array_set (msg->args, gpointer, i, arg);
1934 *cb = *((MonoDelegate **)params [i]);
1936 *state = *((MonoObject **)params [i]);
1943 * mono_method_return_message_restore:
1945 * Restore results from message based processing back to arguments pointers
1948 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
1950 MonoMethodSignature *sig = method->signature;
1951 int i, j, type, size;
1953 for (i = 0, j = 0; i < sig->param_count; i++) {
1954 MonoType *pt = sig->params [i];
1956 size = mono_type_stack_size (pt, NULL);
1959 char *arg = mono_array_get (out_args, gpointer, j);
1963 case MONO_TYPE_VOID:
1964 g_assert_not_reached ();
1968 case MONO_TYPE_BOOLEAN:
1971 case MONO_TYPE_CHAR:
1978 case MONO_TYPE_VALUETYPE: {
1979 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
1982 case MONO_TYPE_STRING:
1983 case MONO_TYPE_CLASS:
1984 case MONO_TYPE_ARRAY:
1985 case MONO_TYPE_SZARRAY:
1986 **((MonoObject ***)params [i]) = (MonoObject *)arg;
1989 g_assert_not_reached ();
1998 * mono_load_remote_field:
1999 * @this: pointer to an object
2000 * @klass: klass of the object containing @field
2001 * @field: the field to load
2002 * @res: a storage to store the result
2004 * This method is called by the runtime on attempts to load fields of
2005 * transparent proxy objects. @this points to such TP, @klass is the class of
2006 * the object containing @field. @res is a storage location which can be
2007 * used to store the result.
2009 * Returns: an address pointing to the value of field.
2012 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2014 static MonoMethod *getter = NULL;
2015 MonoDomain *domain = mono_domain_get ();
2016 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2017 MonoClass *field_class;
2018 MonoMethodMessage *msg;
2019 MonoArray *out_args;
2023 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2028 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2029 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2036 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2037 MonoMethod *cm = mono_defaults.object_class->methods [i];
2039 if (!strcmp (cm->name, "FieldGetter")) {
2047 field_class = mono_class_from_mono_type (field->type);
2049 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2050 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2051 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2053 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2054 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2056 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2058 *res = mono_array_get (out_args, MonoObject *, 0);
2060 if (field_class->valuetype) {
2061 return ((char *)*res) + sizeof (MonoObject);
2067 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2069 static MonoMethod *getter = NULL;
2070 MonoDomain *domain = mono_domain_get ();
2071 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2072 MonoClass *field_class;
2073 MonoMethodMessage *msg;
2074 MonoArray *out_args;
2075 MonoObject *exc, *res;
2077 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2079 field_class = mono_class_from_mono_type (field->type);
2081 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2083 if (field_class->valuetype) {
2084 res = mono_object_new (domain, field_class);
2085 val = ((gchar *) res) + sizeof (MonoObject);
2089 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2096 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2097 MonoMethod *cm = mono_defaults.object_class->methods [i];
2099 if (!strcmp (cm->name, "FieldGetter")) {
2107 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2108 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2109 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2111 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2112 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2114 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2116 res = mono_array_get (out_args, MonoObject *, 0);
2122 * mono_store_remote_field:
2123 * @this: pointer to an object
2124 * @klass: klass of the object containing @field
2125 * @field: the field to load
2126 * @val: the value/object to store
2128 * This method is called by the runtime on attempts to store fields of
2129 * transparent proxy objects. @this points to such TP, @klass is the class of
2130 * the object containing @field. @val is the new value to store in @field.
2133 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2135 static MonoMethod *setter = NULL;
2136 MonoDomain *domain = mono_domain_get ();
2137 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2138 MonoClass *field_class;
2139 MonoMethodMessage *msg;
2140 MonoArray *out_args;
2144 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2146 field_class = mono_class_from_mono_type (field->type);
2148 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2149 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
2150 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
2157 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2158 MonoMethod *cm = mono_defaults.object_class->methods [i];
2160 if (!strcmp (cm->name, "FieldSetter")) {
2168 if (field_class->valuetype)
2169 arg = mono_value_box (domain, field_class, val);
2171 arg = *((MonoObject **)val);
2174 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2175 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2177 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2178 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2179 mono_array_set (msg->args, gpointer, 2, arg);
2181 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2185 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2187 static MonoMethod *setter = NULL;
2188 MonoDomain *domain = mono_domain_get ();
2189 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2190 MonoClass *field_class;
2191 MonoMethodMessage *msg;
2192 MonoArray *out_args;
2195 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2197 field_class = mono_class_from_mono_type (field->type);
2199 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2200 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
2201 else mono_field_set_value (tp->rp->unwrapped_server, field, &arg);
2208 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2209 MonoMethod *cm = mono_defaults.object_class->methods [i];
2211 if (!strcmp (cm->name, "FieldSetter")) {
2219 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2220 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2222 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2223 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2224 mono_array_set (msg->args, gpointer, 2, arg);
2226 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);