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)
168 MonoClassField *field;
170 guint32 cols [MONO_CONSTANT_SIZE];
177 vt = class->cached_vtable;
178 if (vt && vt->domain == domain)
181 mono_domain_lock (domain);
182 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
183 mono_domain_unlock (domain);
188 mono_class_init (class);
190 mono_stats.used_class_count++;
191 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
193 vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) +
194 class->vtable_size * sizeof (gpointer));
198 if (class->class_size) {
200 vt->data = GC_MALLOC (class->class_size + 8);
201 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
202 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
203 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
205 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
208 mono_stats.class_static_data_size += class->class_size + 8;
211 for (i = class->field.first; i < class->field.last; ++i) {
212 field = &class->fields [i - class->field.first];
213 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
215 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
216 MonoClass *fklass = mono_class_from_mono_type (field->type);
217 t = (char*)vt->data + field->offset;
218 if (fklass->valuetype) {
219 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
221 /* it's a pointer type: add check */
222 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
223 *t = *(char *)field->data;
227 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
229 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1));
231 g_warning ("constant for field %s not found", field->name);
234 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
235 p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
236 len = mono_metadata_decode_blob_size (p, &p);
237 t = (char*)vt->data + field->offset;
238 /* should we check that the type matches? */
239 switch (cols [MONO_CONSTANT_TYPE]) {
240 case MONO_TYPE_BOOLEAN:
248 guint16 *val = (guint16*)t;
254 guint32 *val = (guint32*)t;
260 guint64 *val = (guint64*)t;
265 float *val = (float*)t;
270 double *val = (double*)t;
274 case MONO_TYPE_STRING: {
275 gpointer *val = (gpointer*)t;
276 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
277 gunichar2 *copy = g_malloc (len);
279 for (j = 0; j < len/2; j++) {
280 copy [j] = read16 (p);
283 *val = mono_string_new_utf16 (domain, copy, len/2);
286 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
290 case MONO_TYPE_CLASS:
291 /* nothing to do, we malloc0 the data and the value can be 0 only */
294 g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]);
298 vt->max_interface_id = class->max_interface_id;
300 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
301 sizeof (gpointer) * (class->max_interface_id + 1));
303 /* initialize interface offsets */
304 for (k = class; k ; k = k->parent) {
305 for (i = 0; i < k->interface_count; i++) {
307 MonoClass *ic = k->interfaces [i];
308 slot = class->interface_offsets [ic->interface_id];
309 vt->interface_offsets [ic->interface_id] = &vt->vtable [slot];
314 * arch_create_jit_trampoline () can recursively call this function again
315 * because it compiles icall methods right away.
317 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
318 if (!class->cached_vtable)
319 class->cached_vtable = vt;
321 /* initialize vtable */
322 for (i = 0; i < class->vtable_size; ++i) {
325 if ((cm = class->vtable [i]))
326 vt->vtable [i] = arch_create_jit_trampoline (cm);
329 mono_domain_unlock (domain);
331 /* make sure the the parent is initialized */
333 mono_class_vtable (domain, class->parent);
335 mono_runtime_class_init (class);
337 if (class->contextbound)
346 * mono_class_proxy_vtable:
347 * @domain: the application domain
348 * @class: the class to proxy
350 * Creates a vtable for transparent proxies. It is basically
351 * a copy of the real vtable of @class, but all function pointers invoke
352 * the remoting functions, and vtable->klass points to the
353 * transparent proxy class, and not to @class.
356 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
358 MonoVTable *vt, *pvt;
361 if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
364 vt = mono_class_vtable (domain, class);
365 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
367 mono_stats.class_vtable_size += vtsize;
369 pvt = mono_mempool_alloc (domain->mp, vtsize);
370 memcpy (pvt, vt, vtsize);
372 pvt->klass = mono_defaults.transparent_proxy_class;
374 /* initialize vtable */
375 for (i = 0; i < class->vtable_size; ++i) {
378 if ((cm = class->vtable [i]))
379 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
382 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
388 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
389 * the instance of a callvirt of method.
392 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
398 klass = mono_object_class (obj);
399 if (klass == mono_defaults.transparent_proxy_class) {
400 klass = ((MonoTransparentProxy *)obj)->klass;
406 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
409 vtable = klass->vtable;
411 /* check method->slot is a valid index: perform isinstance? */
412 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
413 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
415 res = vtable [method->slot];
420 return mono_marshal_get_remoting_invoke (res);
426 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
428 g_error ("runtime invoke called on uninitialized runtime");
432 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
435 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
437 return default_mono_runtime_invoke (method, obj, params, exc);
441 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
444 gpointer *p = (gpointer*)dest;
451 case MONO_TYPE_BOOLEAN:
454 guint8 *p = (guint8*)dest;
455 *p = *(guint8*)value;
460 case MONO_TYPE_CHAR: {
461 guint16 *p = (guint16*)dest;
462 *p = *(guint16*)value;
465 #if SIZEOF_VOID_P == 4
471 gint32 *p = (gint32*)dest;
472 *p = *(gint32*)value;
475 #if SIZEOF_VOID_P == 8
481 gint64 *p = (gint64*)dest;
482 *p = *(gint64*)value;
486 float *p = (float*)dest;
491 double *p = (double*)dest;
492 *p = *(double*)value;
495 case MONO_TYPE_STRING:
496 case MONO_TYPE_SZARRAY:
497 case MONO_TYPE_CLASS:
498 case MONO_TYPE_OBJECT:
499 case MONO_TYPE_ARRAY:
500 case MONO_TYPE_PTR: {
501 gpointer *p = (gpointer*)dest;
502 *p = deref_pointer? *(gpointer*)value: value;
505 case MONO_TYPE_VALUETYPE:
506 if (type->data.klass->enumtype) {
507 t = type->data.klass->enum_basetype->type;
511 size = mono_class_value_size (type->data.klass, NULL);
512 memcpy (dest, value, size);
516 g_warning ("got type %x", type->type);
517 g_assert_not_reached ();
522 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
526 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
528 dest = (char*)obj + field->offset;
529 set_value (field->type, dest, value, FALSE);
533 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
537 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
539 dest = (char*)vt->data + field->offset;
540 set_value (field->type, dest, value, FALSE);
544 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
548 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
550 src = (char*)obj + field->offset;
551 set_value (field->type, value, src, TRUE);
555 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
559 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
561 src = (char*)vt->data + field->offset;
562 set_value (field->type, value, src, TRUE);
566 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
568 default_mono_runtime_invoke (prop->set, obj, params, exc);
572 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
574 return default_mono_runtime_invoke (prop->get, obj, params, exc);
579 mono_get_delegate_invoke (MonoClass *klass)
586 for (i = 0; i < klass->method.count; ++i) {
587 if (klass->methods [i]->name[0] == 'I' &&
588 !strcmp ("Invoke", klass->methods [i]->name)) {
589 im = klass->methods [i];
599 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
603 im = mono_get_delegate_invoke (delegate->vtable->klass);
606 return mono_runtime_invoke (im, delegate, params, exc);
609 static MonoArray* main_args;
612 mono_runtime_get_main_args (void)
618 * Execute a standard Main() method (argc/argv contains the
619 * executable name). This method also sets the command line argument value
620 * needed by System.Environment.
623 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
627 MonoArray *args = NULL;
628 MonoDomain *domain = mono_domain_get ();
630 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
632 if (!g_path_is_absolute (argv [0])) {
633 gchar *basename = g_path_get_basename (argv [0]);
634 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
638 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, fullpath));
642 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, argv [0]));
645 for (i = 1; i < argc; ++i) {
646 MonoString *arg = mono_string_new (domain, argv [i]);
647 mono_array_set (main_args, gpointer, i, arg);
651 if (method->signature->param_count) {
652 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
653 for (i = 0; i < argc; ++i) {
654 MonoString *arg = mono_string_new (domain, argv [i]);
655 mono_array_set (args, gpointer, i, arg);
658 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
661 mono_assembly_set_main (method->klass->image->assembly);
663 return mono_runtime_exec_main (method, args, exc);
667 * We call this function when we dectect an unhandled exception. It invokes the
668 * UnhandledException event in AppDomain or print a warning to the console
671 mono_unhandled_exception (MonoObject *exc)
673 MonoDomain *domain = mono_domain_get ();
674 MonoClassField *field;
675 MonoObject *delegate;
677 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
678 "UnhandledException");
681 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
682 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
685 mono_print_unhandled_exception (exc);
687 MonoObject *e = NULL;
690 /* fixme: pass useful arguments */
693 mono_runtime_delegate_invoke (delegate, pa, &e);
696 g_warning ("exception inside UnhandledException handler!");
702 * Launch a new thread to start all setup that requires managed code
705 * main_func is called back from the thread with main_args as the
706 * parameter. The callback function is expected to start Main()
707 * eventually. This function then waits for all managed threads to
711 mono_runtime_exec_managed_code (MonoDomain *domain,
712 MonoMainThreadFunc main_func,
715 mono_thread_create (domain, main_func, main_args);
717 mono_thread_manage ();
721 * Execute a standard Main() method (args doesn't contain the
725 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
735 domain = mono_object_domain (args);
736 if (!domain->entry_assembly) {
737 domain->entry_assembly = method->klass->image->assembly;
738 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
741 /* FIXME: check signature of method */
742 if (method->signature->ret->type == MONO_TYPE_I4) {
744 res = mono_runtime_invoke (method, NULL, pa, exc);
746 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
750 mono_environment_exitcode_set (rval);
752 mono_runtime_invoke (method, NULL, pa, exc);
756 /* If the return type of Main is void, only
757 * set the exitcode if an exception was thrown
758 * (we don't want to blow away an
759 * explicitly-set exit code)
762 mono_environment_exitcode_set (rval);
770 mono_install_runtime_invoke (MonoInvokeFunc func)
772 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
776 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
779 MonoMethodSignature *sig = method->signature;
783 if (NULL != params) {
784 pa = alloca (sizeof (gpointer) * mono_array_length (params));
785 for (i = 0; i < mono_array_length (params); i++) {
786 if (sig->params [i]->byref) {
790 switch (sig->params [i]->type) {
793 case MONO_TYPE_BOOLEAN:
805 case MONO_TYPE_VALUETYPE:
806 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
808 case MONO_TYPE_STRING:
809 case MONO_TYPE_OBJECT:
810 case MONO_TYPE_CLASS:
811 case MONO_TYPE_ARRAY:
812 case MONO_TYPE_SZARRAY:
813 pa [i] = (char *)(((gpointer *)params->vector)[i]);
816 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
821 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
823 obj = mono_object_new (mono_domain_get (), method->klass);
824 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
825 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
828 mono_runtime_invoke (method, obj, pa, exc);
831 return mono_runtime_invoke (method, obj, pa, exc);
835 * mono_object_allocate:
836 * @size: number of bytes to allocate
838 * This is a very simplistic routine until we have our GC-aware
841 * Returns: an allocated object of size @size, or NULL on failure.
844 mono_object_allocate (size_t size)
847 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
848 void *o = GC_MALLOC (size);
850 void *o = calloc (1, size);
853 mono_stats.new_object_count++;
861 * Frees the memory used by the object. Debugging purposes
862 * only, as we will have our GC system.
865 mono_object_free (MonoObject *o)
868 g_error ("mono_object_free called with boehm gc.");
870 MonoClass *c = o->vtable->klass;
872 memset (o, 0, c->instance_size);
879 * @klass: the class of the object that we want to create
881 * Returns: A newly created object whose definition is
882 * looked up using @klass
885 mono_object_new (MonoDomain *domain, MonoClass *klass)
887 return mono_object_new_specific (mono_class_vtable (domain, klass));
891 * mono_object_new_specific:
892 * @vtable: the vtable of the object that we want to create
894 * Returns: A newly created object with class and domain specified
898 mono_object_new_specific (MonoVTable *vtable)
905 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
908 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
912 mono_class_init (klass);
914 for (i = 0; i < klass->method.count; ++i) {
915 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
916 klass->methods [i]->signature->param_count == 1) {
917 im = klass->methods [i];
922 vtable->domain->create_proxy_for_type_method = im;
925 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
927 o = mono_runtime_invoke (im, NULL, pa, NULL);
928 if (o != NULL) return o;
931 return mono_object_new_alloc_specific (vtable);
935 mono_object_new_alloc_specific (MonoVTable *vtable)
937 MonoObject *o = mono_object_allocate (vtable->klass->instance_size);
939 if (vtable->klass->has_finalize)
940 mono_object_register_finalizer (o);
942 mono_profiler_allocation (o, vtable->klass);
947 * mono_object_new_from_token:
948 * @image: Context where the type_token is hosted
949 * @token: a token of the type that we want to create
951 * Returns: A newly created object whose definition is
952 * looked up using @token in the @image image
955 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
959 class = mono_class_get (image, token);
961 return mono_object_new (domain, class);
967 * @obj: the object to clone
969 * Returns: A newly created object who is a shallow copy of @obj
972 mono_object_clone (MonoObject *obj)
977 size = obj->vtable->klass->instance_size;
978 o = mono_object_allocate (size);
979 mono_profiler_allocation (o, obj->vtable->klass);
981 memcpy (o, obj, size);
983 if (obj->vtable->klass->has_finalize)
984 mono_object_register_finalizer (o);
990 * @array: the array to clone
992 * Returns: A newly created array who is a shallow copy of @array
995 mono_array_clone (MonoArray *array)
1000 MonoClass *klass = array->obj.vtable->klass;
1002 MONO_ARCH_SAVE_REGS;
1004 if (array->bounds == NULL) {
1005 size = mono_array_length (array);
1006 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1007 klass, &size, NULL);
1009 size *= mono_array_element_size (klass);
1010 memcpy (o, array, sizeof (MonoArray) + size);
1015 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1016 size = mono_array_element_size (klass);
1017 for (i = 0; i < klass->rank; ++i) {
1018 sizes [i] = array->bounds [i].length;
1019 size *= array->bounds [i].length;
1020 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1022 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1023 klass, sizes, sizes + klass->rank);
1024 memcpy (o, array, sizeof(MonoArray) + size);
1030 * mono_array_new_full:
1031 * @domain: domain where the object is created
1032 * @array_class: array class
1033 * @lengths: lengths for each dimension in the array
1034 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1036 * This routine creates a new array objects with the given dimensions,
1037 * lower bounds and type.
1040 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1041 guint32 *lengths, guint32 *lower_bounds)
1043 guint32 byte_len, len;
1046 MonoArrayBounds *bounds;
1049 if (!array_class->inited)
1050 mono_class_init (array_class);
1052 byte_len = mono_array_element_size (array_class);
1055 if (array_class->rank == 1 &&
1056 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1061 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1063 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1065 for (i = 0; i < array_class->rank; ++i) {
1066 bounds [i].length = lengths [i];
1071 for (i = 0; i < array_class->rank; ++i)
1072 bounds [i].lower_bound = lower_bounds [i];
1077 * Following three lines almost taken from mono_object_new ():
1078 * they need to be kept in sync.
1080 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1083 o->vtable = mono_class_vtable (domain, array_class);
1085 array = (MonoArray*)o;
1087 array->bounds = bounds;
1088 array->max_length = len;
1090 mono_profiler_allocation (o, array_class);
1097 * @domain: domain where the object is created
1098 * @eclass: element class
1099 * @n: number of array elements
1101 * This routine creates a new szarray with @n elements of type @eclass.
1104 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1108 ac = mono_array_class_get (&eclass->byval_arg, 1);
1109 g_assert (ac != NULL);
1111 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1115 * mono_array_new_specific:
1116 * @vtable: a vtable in the appropriate domain for an initialized class
1117 * @n: number of array elements
1119 * This routine is a fast alternative to mono_array_new() for code which
1120 * can be sure about the domain it operates in.
1123 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1129 byte_len = n * mono_array_element_size (vtable->klass);
1130 #if CREATION_SPEEDUP
1131 if (vtable->klass->element_class->byval_arg.type >= MONO_TYPE_BOOLEAN && vtable->klass->element_class->byval_arg.type <= MONO_TYPE_R4) {
1132 o = GC_MALLOC_ATOMIC (sizeof (MonoArray) + byte_len);
1133 o->synchronisation = 0;
1134 memset (((MonoArray*)o)->vector, 0, byte_len);
1136 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1139 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1145 ao = (MonoArray *)o;
1148 mono_profiler_allocation (o, vtable->klass);
1154 * mono_string_new_utf16:
1155 * @text: a pointer to an utf16 string
1156 * @len: the length of the string
1158 * Returns: A newly created string object which contains @text.
1161 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1165 s = mono_string_new_size (domain, len);
1166 g_assert (s != NULL);
1168 memcpy (mono_string_chars (s), text, len * 2);
1174 * mono_string_new_size:
1175 * @text: a pointer to an utf16 string
1176 * @len: the length of the string
1178 * Returns: A newly created string object of @len
1181 mono_string_new_size (MonoDomain *domain, gint32 len)
1185 #if CREATION_SPEEDUP
1186 s = GC_MALLOC_ATOMIC (sizeof (MonoString) + ((len + 1) * 2));
1187 s->object.synchronisation = 0;
1188 mono_string_chars (s) [len] = 0;
1190 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1195 s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class);
1197 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1203 * mono_string_new_len:
1204 * @text: a pointer to an utf8 string
1205 * @length: number of bytes in @text to consider
1207 * Returns: A newly created string object which contains @text.
1210 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1212 GError *error = NULL;
1213 MonoString *o = NULL;
1215 glong items_written;
1218 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1221 o = mono_string_new_utf16 (domain, ut, items_written);
1223 g_error_free (error);
1232 * @text: a pointer to an utf8 string
1234 * Returns: A newly created string object which contains @text.
1237 mono_string_new (MonoDomain *domain, const char *text)
1239 GError *error = NULL;
1240 MonoString *o = NULL;
1242 glong items_written;
1247 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1250 o = mono_string_new_utf16 (domain, ut, items_written);
1252 g_error_free (error);
1260 * mono_string_new_wrapper:
1261 * @text: pointer to utf8 characters.
1263 * Helper function to create a string object from @text in the current domain.
1266 mono_string_new_wrapper (const char *text)
1268 MonoDomain *domain = mono_domain_get ();
1271 return mono_string_new (domain, text);
1278 * @class: the class of the value
1279 * @value: a pointer to the unboxed data
1281 * Returns: A newly created object which contains @value.
1284 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1289 g_assert (class->valuetype);
1291 size = mono_class_instance_size (class);
1292 res = mono_object_allocate (size);
1293 res->vtable = mono_class_vtable (domain, class);
1294 mono_profiler_allocation (res, class);
1296 size = size - sizeof (MonoObject);
1298 #if NO_UNALIGNED_ACCESS
1299 memcpy ((char *)res + sizeof (MonoObject), value, size);
1303 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1306 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1309 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1312 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1315 memcpy ((char *)res + sizeof (MonoObject), value, size);
1318 if (class->has_finalize)
1319 mono_object_register_finalizer (res);
1324 * mono_object_isinst:
1326 * @klass: a pointer to a class
1328 * Returns: @obj if @obj is derived from @klass
1331 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1343 mono_class_init (klass);
1345 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1346 if ((klass->interface_id <= oklass->max_interface_id) &&
1347 vt->interface_offsets [klass->interface_id])
1350 if (oklass == mono_defaults.transparent_proxy_class) {
1351 /* fixme: add check for IRemotingTypeInfo */
1352 oklass = ((MonoTransparentProxy *)obj)->klass;
1355 if (oklass->rank == klass->rank &&
1356 (oklass->cast_class->baseval - klass->cast_class->baseval) <=
1357 klass->cast_class->diffval)
1360 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
1368 mono_string_is_interned_lookup (MonoString *str, int insert)
1370 MonoGHashTable *ldstr_table;
1373 char *ins = g_malloc (4 + str->length * 2);
1377 /* Encode the length */
1379 mono_metadata_encode_value (2 * str->length, p, &p);
1382 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1383 bloblen = (p - ins) + 2 * str->length;
1385 * ins is stored in the hash table as a key and needs to have the same
1386 * representation as in the metadata: we swap the character bytes on big
1389 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1392 char *p2 = mono_string_chars (str);
1393 for (i = 0; i < str->length; ++i) {
1400 memcpy (p, mono_string_chars (str), str->length * 2);
1402 domain = ((MonoObject *)str)->vtable->domain;
1403 ldstr_table = domain->ldstr_table;
1404 mono_domain_lock (domain);
1405 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1406 mono_domain_unlock (domain);
1411 mono_g_hash_table_insert (ldstr_table, ins, str);
1412 mono_domain_unlock (domain);
1415 mono_domain_unlock (domain);
1421 mono_string_is_interned (MonoString *o)
1423 return mono_string_is_interned_lookup (o, FALSE);
1427 mono_string_intern (MonoString *str)
1429 return mono_string_is_interned_lookup (str, TRUE);
1434 * @domain: the domain where the string will be used.
1435 * @image: a metadata context
1436 * @idx: index into the user string table.
1438 * Implementation for the ldstr opcode.
1441 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1443 const char *str, *sig;
1447 MONO_ARCH_SAVE_REGS;
1449 if (image->assembly->dynamic)
1450 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
1452 sig = str = mono_metadata_user_string (image, idx);
1454 mono_domain_lock (domain);
1455 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1456 mono_domain_unlock (domain);
1460 len2 = mono_metadata_decode_blob_size (str, &str);
1463 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1464 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1467 guint16 *p2 = (guint16*)mono_string_chars (o);
1468 for (i = 0; i < len2; ++i) {
1469 *p2 = GUINT16_FROM_LE (*p2);
1474 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1475 mono_domain_unlock (domain);
1481 * mono_string_to_utf8:
1482 * @s: a System.String
1484 * Return the UTF8 representation for @s.
1485 * the resulting buffer nedds to be freed with g_free().
1488 mono_string_to_utf8 (MonoString *s)
1491 GError *error = NULL;
1497 return g_strdup ("");
1499 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1501 g_warning (error->message);
1507 * mono_string_to_utf16:
1510 * Return an null-terminated array of the utf-16 chars
1511 * contained in @s. The result must be freed with g_free().
1512 * This is a temporary helper until our string implementation
1513 * is reworked to always include the null terminating char.
1516 mono_string_to_utf16 (MonoString *s)
1523 as = g_malloc ((s->length * 2) + 2);
1524 as [(s->length * 2)] = '\0';
1525 as [(s->length * 2) + 1] = '\0';
1528 return (gunichar2 *)(as);
1531 memcpy (as, mono_string_chars(s), s->length * 2);
1532 return (gunichar2 *)(as);
1536 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
1539 mono_string_from_utf16 (gunichar2 *data)
1541 MonoDomain *domain = mono_domain_get ();
1547 while (data [len]) len++;
1549 return mono_string_new_utf16 (domain, data, len);
1553 default_ex_handler (MonoException *ex)
1555 MonoObject *o = (MonoObject*)ex;
1556 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1559 static MonoExceptionFunc ex_handler = default_ex_handler;
1562 mono_install_handler (MonoExceptionFunc func)
1564 ex_handler = func? func: default_ex_handler;
1568 * mono_raise_exception:
1569 * @ex: exception object
1571 * Signal the runtime that the exception @ex has been raised in unmanaged code.
1574 mono_raise_exception (MonoException *ex)
1580 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1582 MonoWaitHandle *res;
1584 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1586 res->handle = handle;
1592 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
1594 MonoAsyncResult *res;
1596 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
1599 res->async_state = state;
1600 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
1601 res->sync_completed = FALSE;
1602 res->completed = FALSE;
1608 mono_message_init (MonoDomain *domain,
1609 MonoMethodMessage *this,
1610 MonoReflectionMethod *method,
1611 MonoArray *out_args)
1613 MonoMethodSignature *sig = method->method->signature;
1619 this->method = method;
1621 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
1622 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
1624 names = g_new (char *, sig->param_count);
1625 mono_method_get_param_names (method->method, (const char **) names);
1626 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
1628 for (i = 0; i < sig->param_count; i++) {
1629 name = mono_string_new (domain, names [i]);
1630 mono_array_set (this->names, gpointer, i, name);
1635 for (i = 0, j = 0; i < sig->param_count; i++) {
1637 if (sig->params [i]->byref) {
1639 gpointer arg = mono_array_get (out_args, gpointer, j);
1640 mono_array_set (this->args, gpointer, i, arg);
1644 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
1650 mono_array_set (this->arg_types, guint8, i, arg_type);
1655 * mono_remoting_invoke:
1656 * @real_proxy: pointer to a RealProxy object
1657 * @msg: The MonoMethodMessage to execute
1658 * @exc: used to store exceptions
1659 * @out_args: used to store output arguments
1661 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
1662 * IMessage interface and it is not trivial to extract results from there. So
1663 * we call an helper method PrivateInvoke instead of calling
1664 * RealProxy::Invoke() directly.
1666 * Returns: the result object.
1669 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
1670 MonoObject **exc, MonoArray **out_args)
1672 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
1675 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
1681 klass = mono_defaults.real_proxy_class;
1683 for (i = 0; i < klass->method.count; ++i) {
1684 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
1685 klass->methods [i]->signature->param_count == 4) {
1686 im = klass->methods [i];
1692 real_proxy->vtable->domain->private_invoke_method = im;
1695 pa [0] = real_proxy;
1700 return mono_runtime_invoke (im, NULL, pa, exc);
1704 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
1705 MonoObject **exc, MonoArray **out_args)
1707 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1709 return mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)target)->rp,
1710 msg, exc, out_args);
1713 MonoDomain *domain = mono_domain_get ();
1714 MonoMethod *method = msg->method->method;
1715 MonoMethodSignature *sig = method->signature;
1716 int i, j, outarg_count = 0;
1718 for (i = 0; i < sig->param_count; i++) {
1719 if (sig->params [i]->byref)
1723 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
1726 for (i = 0, j = 0; i < sig->param_count; i++) {
1727 if (sig->params [i]->byref) {
1729 arg = mono_array_get (msg->args, gpointer, i);
1730 mono_array_set (*out_args, gpointer, j, arg);
1735 return mono_runtime_invoke_array (method, target, msg->args, exc);
1740 mono_print_unhandled_exception (MonoObject *exc)
1742 char *message = (char *) "";
1746 gboolean free_message = FALSE;
1749 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1750 klass = exc->vtable->klass;
1752 while (klass && method == NULL) {
1753 for (i = 0; i < klass->method.count; ++i) {
1754 method = klass->methods [i];
1755 if (!strcmp ("ToString", method->name) &&
1756 method->signature->param_count == 0 &&
1757 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
1758 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
1765 klass = klass->parent;
1770 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
1772 message = mono_string_to_utf8 (str);
1773 free_message = TRUE;
1778 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
1779 * exc->vtable->klass->name, message);
1781 g_printerr ("\nUnhandled Exception: %s\n", message);
1788 * mono_delegate_ctor:
1789 * @this: pointer to an uninitialized delegate object
1790 * @target: target object
1791 * @addr: pointer to native code
1793 * This is used to initialize a delegate. We also insert the method_info if
1794 * we find the info with mono_jit_info_table_find().
1797 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
1799 MonoDomain *domain = mono_domain_get ();
1800 MonoDelegate *delegate = (MonoDelegate *)this;
1801 MonoMethod *method = NULL;
1808 class = this->vtable->klass;
1810 if ((ji = mono_jit_info_table_find (domain, addr))) {
1811 method = ji->method;
1812 delegate->method_info = mono_method_get_object (domain, method, NULL);
1815 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1817 method = mono_marshal_get_remoting_invoke (method);
1818 delegate->method_ptr = mono_compile_method (method);
1819 delegate->target = target;
1821 delegate->method_ptr = addr;
1822 delegate->target = target;
1827 * mono_method_call_message_new:
1829 * Translates arguments pointers into a Message.
1832 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
1833 MonoDelegate **cb, MonoObject **state)
1835 MonoDomain *domain = mono_domain_get ();
1836 MonoMethodSignature *sig = method->signature;
1837 MonoMethodMessage *msg;
1840 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1843 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
1844 count = sig->param_count - 2;
1846 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
1847 count = sig->param_count;
1850 for (i = 0; i < count; i++) {
1855 if (sig->params [i]->byref)
1856 vpos = *((gpointer *)params [i]);
1860 type = sig->params [i]->type;
1861 class = mono_class_from_mono_type (sig->params [i]);
1863 if (class->valuetype)
1864 arg = mono_value_box (domain, class, vpos);
1866 arg = *((MonoObject **)vpos);
1868 mono_array_set (msg->args, gpointer, i, arg);
1872 *cb = *((MonoDelegate **)params [i]);
1874 *state = *((MonoObject **)params [i]);
1881 * mono_method_return_message_restore:
1883 * Restore results from message based processing back to arguments pointers
1886 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
1888 MonoMethodSignature *sig = method->signature;
1889 int i, j, type, size;
1891 for (i = 0, j = 0; i < sig->param_count; i++) {
1892 MonoType *pt = sig->params [i];
1894 size = mono_type_stack_size (pt, NULL);
1897 char *arg = mono_array_get (out_args, gpointer, j);
1901 case MONO_TYPE_VOID:
1902 g_assert_not_reached ();
1906 case MONO_TYPE_BOOLEAN:
1909 case MONO_TYPE_CHAR:
1916 case MONO_TYPE_VALUETYPE: {
1917 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
1920 case MONO_TYPE_STRING:
1921 case MONO_TYPE_CLASS:
1922 case MONO_TYPE_ARRAY:
1923 case MONO_TYPE_SZARRAY:
1924 *((MonoObject **)params [i]) = (MonoObject *)arg;
1927 g_assert_not_reached ();
1936 * mono_load_remote_field:
1937 * @this: pointer to an object
1938 * @klass: klass of the object containing @field
1939 * @field: the field to load
1940 * @res: a storage to store the result
1942 * This method is called by the runtime on attempts to load fields of
1943 * transparent proxy objects. @this points to such TP, @klass is the class of
1944 * the object containing @field. @res is a storage location which can be
1945 * used to store the result.
1947 * Returns: an address pointing to the value of field.
1950 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
1952 static MonoMethod *getter = NULL;
1953 MonoDomain *domain = mono_domain_get ();
1954 MonoClass *field_class;
1955 MonoMethodMessage *msg;
1956 MonoArray *out_args;
1960 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
1968 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
1969 MonoMethod *cm = mono_defaults.object_class->methods [i];
1971 if (!strcmp (cm->name, "FieldGetter")) {
1979 field_class = mono_class_from_mono_type (field->type);
1981 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1982 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
1983 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
1985 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
1986 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
1988 mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);
1990 *res = mono_array_get (out_args, MonoObject *, 0);
1992 if (field_class->valuetype) {
1993 return ((char *)*res) + sizeof (MonoObject);
1999 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2001 static MonoMethod *getter = NULL;
2002 MonoDomain *domain = mono_domain_get ();
2003 MonoClass *field_class;
2004 MonoMethodMessage *msg;
2005 MonoArray *out_args;
2006 MonoObject *exc, *res;
2008 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2013 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2014 MonoMethod *cm = mono_defaults.object_class->methods [i];
2016 if (!strcmp (cm->name, "FieldGetter")) {
2024 field_class = mono_class_from_mono_type (field->type);
2026 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2027 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2028 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2030 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2031 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2033 mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);
2035 res = mono_array_get (out_args, MonoObject *, 0);
2041 * mono_store_remote_field:
2042 * @this: pointer to an object
2043 * @klass: klass of the object containing @field
2044 * @field: the field to load
2045 * @val: the value/object to store
2047 * This method is called by the runtime on attempts to store fields of
2048 * transparent proxy objects. @this points to such TP, @klass is the class of
2049 * the object containing @field. @val is the new value to store in @field.
2052 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2054 static MonoMethod *setter = NULL;
2055 MonoDomain *domain = mono_domain_get ();
2056 MonoClass *field_class;
2057 MonoMethodMessage *msg;
2058 MonoArray *out_args;
2062 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2067 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2068 MonoMethod *cm = mono_defaults.object_class->methods [i];
2070 if (!strcmp (cm->name, "FieldSetter")) {
2078 field_class = mono_class_from_mono_type (field->type);
2080 if (field_class->valuetype)
2081 arg = mono_value_box (domain, field_class, val);
2083 arg = *((MonoObject **)val);
2086 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2087 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2089 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2090 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2091 mono_array_set (msg->args, gpointer, 2, arg);
2093 mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);
2097 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2099 static MonoMethod *setter = NULL;
2100 MonoDomain *domain = mono_domain_get ();
2101 MonoMethodMessage *msg;
2102 MonoArray *out_args;
2105 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2110 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2111 MonoMethod *cm = mono_defaults.object_class->methods [i];
2113 if (!strcmp (cm->name, "FieldSetter")) {
2121 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2122 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2124 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2125 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2126 mono_array_set (msg->args, gpointer, 2, arg);
2128 mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);