2 * object.c: Object creation for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001-2004 Ximian, Inc.
15 #include <mono/metadata/mono-endian.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/metadata/tokentype.h>
18 #include <mono/metadata/loader.h>
19 #include <mono/metadata/object.h>
20 #include <mono/metadata/gc-internal.h>
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/domain-internals.h>
23 #include "mono/metadata/metadata-internals.h"
24 #include "mono/metadata/class-internals.h"
25 #include <mono/metadata/assembly.h>
26 #include <mono/metadata/threadpool.h>
27 #include <mono/metadata/marshal.h>
28 #include "mono/metadata/debug-helpers.h"
29 #include "mono/metadata/marshal.h"
30 #include <mono/metadata/threads.h>
31 #include <mono/metadata/threads-types.h>
32 #include <mono/metadata/environment.h>
33 #include "mono/metadata/profiler-private.h"
34 #include "mono/metadata/security-manager.h"
35 #include "mono/metadata/mono-debug-debugger.h"
36 #include <mono/os/gc_wrapper.h>
37 #include <mono/utils/strenc.h>
40 #define NEED_TO_ZERO_PTRFREE 1
41 #define ALLOC_PTRFREE(obj,vt,size) do { (obj) = GC_MALLOC_ATOMIC ((size)); (obj)->vtable = (vt); (obj)->synchronisation = NULL;} while (0)
42 #define ALLOC_OBJECT(obj,vt,size) do { (obj) = GC_MALLOC ((size)); (obj)->vtable = (vt);} while (0)
43 #ifdef HAVE_GC_GCJ_MALLOC
44 #define CREATION_SPEEDUP 1
45 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
46 #define ALLOC_TYPED(dest,size,type) do { (dest) = GC_GCJ_MALLOC ((size),(type)); } while (0)
47 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) GC_make_descriptor((GC_bitmap)(bitmap),(sz))
48 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) GC_make_descriptor((GC_bitmap)(bitmap),(sz))
50 #define GC_NO_DESCRIPTOR (NULL)
51 #define ALLOC_TYPED(dest,size,type) do { (dest) = GC_MALLOC ((size)); *(gpointer*)dest = (type);} while (0)
52 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) NULL
53 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) NULL
57 #define GC_NO_DESCRIPTOR (NULL)
58 #define ALLOC_PTRFREE(obj,vt,size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0)
59 #define ALLOC_OBJECT(obj,vt,size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0)
60 #define ALLOC_TYPED(dest,size,type) do { (dest) = mono_gc_alloc_obj (type, size);} while (0)
61 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) mono_gc_make_descr_for_string ()
62 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) mono_gc_make_descr_for_object ((bitmap), (sz), (objsize))
64 #define NEED_TO_ZERO_PTRFREE 1
65 #define GC_NO_DESCRIPTOR (NULL)
66 #define ALLOC_PTRFREE(obj,vt,size) do { (obj) = malloc ((size)); (obj)->vtable = (vt); (obj)->synchronisation = NULL;} while (0)
67 #define ALLOC_OBJECT(obj,vt,size) do { (obj) = calloc (1, (size)); (obj)->vtable = (vt);} while (0)
68 #define ALLOC_TYPED(dest,size,type) do { (dest) = calloc (1, (size)); *(gpointer*)dest = (type);} while (0)
69 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) NULL
70 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) NULL
74 static MonoObject
* mono_object_new_ptrfree (MonoVTable
*vtable
);
75 static MonoObject
* mono_object_new_ptrfree_box (MonoVTable
*vtable
);
78 get_default_field_value (MonoDomain
* domain
, MonoClassField
*field
, void *value
);
81 mono_ldstr_metdata_sig (MonoDomain
*domain
, const char* sig
);
83 #define ldstr_lock() EnterCriticalSection (&ldstr_section)
84 #define ldstr_unlock() LeaveCriticalSection (&ldstr_section)
85 static CRITICAL_SECTION ldstr_section
;
88 mono_runtime_object_init (MonoObject
*this)
90 MonoMethod
*method
= NULL
;
91 MonoClass
*klass
= this->vtable
->klass
;
93 method
= mono_class_get_method_from_name (klass
, ".ctor", 0);
96 if (method
->klass
->valuetype
)
97 this = mono_object_unbox (this);
98 mono_runtime_invoke (method
, this, NULL
, NULL
);
101 /* The pseudo algorithm for type initialization from the spec
102 Note it doesn't say anything about domains - only threads.
104 2. If the type is initialized you are done.
105 2.1. If the type is not yet initialized, try to take an
107 2.2. If successful, record this thread as responsible for
108 initializing the type and proceed to step 2.3.
109 2.2.1. If not, see whether this thread or any thread
110 waiting for this thread to complete already holds the lock.
111 2.2.2. If so, return since blocking would create a deadlock. This thread
112 will now see an incompletely initialized state for the type,
113 but no deadlock will arise.
114 2.2.3 If not, block until the type is initialized then return.
115 2.3 Initialize the parent type and then all interfaces implemented
117 2.4 Execute the type initialization code for this type.
118 2.5 Mark the type as initialized, release the initialization lock,
119 awaken any threads waiting for this type to be initialized,
126 guint32 initializing_tid
;
127 guint32 waiting_count
;
129 CRITICAL_SECTION initialization_section
;
130 } TypeInitializationLock
;
132 /* for locking access to type_initialization_hash and blocked_thread_hash */
133 #define mono_type_initialization_lock() EnterCriticalSection (&type_initialization_section)
134 #define mono_type_initialization_unlock() LeaveCriticalSection (&type_initialization_section)
135 static CRITICAL_SECTION type_initialization_section
;
137 /* from vtable to lock */
138 static GHashTable
*type_initialization_hash
;
140 /* from thread id to thread id being waited on */
141 static GHashTable
*blocked_thread_hash
;
144 static MonoThread
*main_thread
;
147 * mono_thread_set_main:
148 * @thread: thread to set as the main thread
150 * This function can be used to instruct the runtime to treat @thread
151 * as the main thread, ie, the thread that would normally execute the Main()
152 * method. This basically means that at the end of @thread, the runtime will
153 * wait for the existing foreground threads to quit and other such details.
156 mono_thread_set_main (MonoThread
*thread
)
158 main_thread
= thread
;
162 mono_thread_get_main (void)
168 mono_type_initialization_init (void)
170 InitializeCriticalSection (&type_initialization_section
);
171 type_initialization_hash
= g_hash_table_new (NULL
, NULL
);
172 blocked_thread_hash
= g_hash_table_new (NULL
, NULL
);
173 InitializeCriticalSection (&ldstr_section
);
177 mono_type_initialization_cleanup (void)
180 /* This is causing race conditions with
181 * mono_release_type_locks
183 DeleteCriticalSection (&type_initialization_section
);
185 DeleteCriticalSection (&ldstr_section
);
189 * get_type_init_exception_for_vtable:
191 * Return the stored type initialization exception for VTABLE.
193 static MonoException
*
194 get_type_init_exception_for_vtable (MonoVTable
*vtable
)
196 MonoDomain
*domain
= vtable
->domain
;
197 MonoClass
*klass
= vtable
->klass
;
201 g_assert (vtable
->init_failed
);
204 * If the initializing thread was rudely aborted, the exception is not stored
208 mono_domain_lock (domain
);
209 if (domain
->type_init_exception_hash
)
210 ex
= mono_g_hash_table_lookup (domain
->type_init_exception_hash
, klass
);
211 mono_domain_unlock (domain
);
214 if (klass
->name_space
&& *klass
->name_space
)
215 full_name
= g_strdup_printf ("%s.%s", klass
->name_space
, klass
->name
);
217 full_name
= g_strdup (klass
->name
);
218 ex
= mono_get_exception_type_initialization (full_name
, NULL
);
226 * mono_runtime_class_init:
227 * @vtable: vtable that needs to be initialized
229 * This routine calls the class constructor for @vtable.
232 mono_runtime_class_init (MonoVTable
*vtable
)
235 MonoException
*exc_to_throw
;
236 MonoMethod
*method
= NULL
;
242 if (vtable
->initialized
)
246 klass
= vtable
->klass
;
248 if (!klass
->image
->checked_module_cctor
) {
249 mono_image_check_for_module_cctor (klass
->image
);
250 if (klass
->image
->has_module_cctor
) {
251 MonoClass
*module_klass
= mono_class_get (klass
->image
, MONO_TOKEN_TYPE_DEF
| 1);
252 mono_runtime_class_init (mono_class_vtable (vtable
->domain
, module_klass
));
255 method
= mono_class_get_cctor (klass
);
258 MonoDomain
*domain
= vtable
->domain
;
259 TypeInitializationLock
*lock
;
260 guint32 tid
= GetCurrentThreadId();
261 int do_initialization
= 0;
262 MonoDomain
*last_domain
= NULL
;
264 mono_type_initialization_lock ();
265 /* double check... */
266 if (vtable
->initialized
) {
267 mono_type_initialization_unlock ();
270 if (vtable
->init_failed
) {
271 mono_type_initialization_unlock ();
273 /* The type initialization already failed once, rethrow the same exception */
274 mono_raise_exception (get_type_init_exception_for_vtable (vtable
));
277 lock
= g_hash_table_lookup (type_initialization_hash
, vtable
);
279 /* This thread will get to do the initialization */
280 if (mono_domain_get () != domain
) {
281 /* Transfer into the target domain */
282 last_domain
= mono_domain_get ();
283 if (!mono_domain_set (domain
, FALSE
)) {
284 vtable
->initialized
= 1;
285 mono_type_initialization_unlock ();
286 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
289 lock
= g_malloc (sizeof(TypeInitializationLock
));
290 InitializeCriticalSection (&lock
->initialization_section
);
291 lock
->initializing_tid
= tid
;
292 lock
->waiting_count
= 1;
294 /* grab the vtable lock while this thread still owns type_initialization_section */
295 EnterCriticalSection (&lock
->initialization_section
);
296 g_hash_table_insert (type_initialization_hash
, vtable
, lock
);
297 do_initialization
= 1;
300 TypeInitializationLock
*pending_lock
;
302 if (lock
->initializing_tid
== tid
|| lock
->done
) {
303 mono_type_initialization_unlock ();
306 /* see if the thread doing the initialization is already blocked on this thread */
307 blocked
= GUINT_TO_POINTER (lock
->initializing_tid
);
308 while ((pending_lock
= (TypeInitializationLock
*) g_hash_table_lookup (blocked_thread_hash
, blocked
))) {
309 if (pending_lock
->initializing_tid
== tid
) {
310 if (!pending_lock
->done
) {
311 mono_type_initialization_unlock ();
314 /* the thread doing the initialization is blocked on this thread,
315 but on a lock that has already been freed. It just hasn't got
320 blocked
= GUINT_TO_POINTER (pending_lock
->initializing_tid
);
322 ++lock
->waiting_count
;
323 /* record the fact that we are waiting on the initializing thread */
324 g_hash_table_insert (blocked_thread_hash
, GUINT_TO_POINTER (tid
), lock
);
326 mono_type_initialization_unlock ();
328 if (do_initialization
) {
329 mono_runtime_invoke (method
, NULL
, NULL
, (MonoObject
**) &exc
);
331 /* If the initialization failed, mark the class as unusable. */
332 /* Avoid infinite loops */
334 (klass
->image
== mono_defaults
.corlib
&&
335 !strcmp (klass
->name_space
, "System") &&
336 !strcmp (klass
->name
, "TypeInitializationException")))) {
337 vtable
->init_failed
= 1;
339 if (klass
->name_space
&& *klass
->name_space
)
340 full_name
= g_strdup_printf ("%s.%s", klass
->name_space
, klass
->name
);
342 full_name
= g_strdup (klass
->name
);
343 exc_to_throw
= mono_get_exception_type_initialization (full_name
, exc
);
347 * Store the exception object so it could be thrown on subsequent
350 mono_domain_lock (domain
);
351 if (!domain
->type_init_exception_hash
)
352 domain
->type_init_exception_hash
= mono_g_hash_table_new_type (mono_aligned_addr_hash
, NULL
, MONO_HASH_VALUE_GC
);
353 mono_g_hash_table_insert (domain
->type_init_exception_hash
, klass
, exc_to_throw
);
354 mono_domain_unlock (domain
);
358 mono_domain_set (last_domain
, TRUE
);
360 LeaveCriticalSection (&lock
->initialization_section
);
362 /* this just blocks until the initializing thread is done */
363 EnterCriticalSection (&lock
->initialization_section
);
364 LeaveCriticalSection (&lock
->initialization_section
);
367 mono_type_initialization_lock ();
368 if (lock
->initializing_tid
!= tid
)
369 g_hash_table_remove (blocked_thread_hash
, GUINT_TO_POINTER (tid
));
370 --lock
->waiting_count
;
371 if (lock
->waiting_count
== 0) {
372 DeleteCriticalSection (&lock
->initialization_section
);
373 g_hash_table_remove (type_initialization_hash
, vtable
);
376 if (!vtable
->init_failed
)
377 vtable
->initialized
= 1;
378 mono_type_initialization_unlock ();
380 if (vtable
->init_failed
) {
381 /* Either we were the initializing thread or we waited for the initialization */
382 mono_raise_exception (get_type_init_exception_for_vtable (vtable
));
385 vtable
->initialized
= 1;
391 gboolean
release_type_locks (gpointer key
, gpointer value
, gpointer user
)
393 MonoVTable
*vtable
= (MonoVTable
*)key
;
395 TypeInitializationLock
*lock
= (TypeInitializationLock
*) value
;
396 if (lock
->initializing_tid
== GPOINTER_TO_UINT (user
) && !lock
->done
) {
399 * Have to set this since it cannot be set by the normal code in
400 * mono_runtime_class_init (). In this case, the exception object is not stored,
401 * and get_type_init_exception_for_class () needs to be aware of this.
403 vtable
->init_failed
= 1;
404 LeaveCriticalSection (&lock
->initialization_section
);
405 --lock
->waiting_count
;
406 if (lock
->waiting_count
== 0) {
407 DeleteCriticalSection (&lock
->initialization_section
);
416 mono_release_type_locks (MonoThread
*thread
)
418 mono_type_initialization_lock ();
419 g_hash_table_foreach_remove (type_initialization_hash
, release_type_locks
, (gpointer
)(gsize
)(thread
->tid
));
420 mono_type_initialization_unlock ();
424 default_trampoline (MonoMethod
*method
)
430 default_remoting_trampoline (MonoMethod
*method
, MonoRemotingTarget target
)
432 g_error ("remoting not installed");
437 default_delegate_trampoline (MonoMethod
*method
, gpointer addr
)
439 g_assert_not_reached ();
443 static MonoTrampoline arch_create_jit_trampoline
= default_trampoline
;
444 static MonoRemotingTrampoline arch_create_remoting_trampoline
= default_remoting_trampoline
;
445 static MonoDelegateTrampoline arch_create_delegate_trampoline
= default_delegate_trampoline
;
448 mono_install_trampoline (MonoTrampoline func
)
450 arch_create_jit_trampoline
= func
? func
: default_trampoline
;
454 mono_install_remoting_trampoline (MonoRemotingTrampoline func
)
456 arch_create_remoting_trampoline
= func
? func
: default_remoting_trampoline
;
460 mono_install_delegate_trampoline (MonoDelegateTrampoline func
)
462 arch_create_delegate_trampoline
= func
? func
: default_delegate_trampoline
;
465 static MonoCompileFunc default_mono_compile_method
= NULL
;
468 * mono_install_compile_method:
469 * @func: function to install
471 * This is a VM internal routine
474 mono_install_compile_method (MonoCompileFunc func
)
476 default_mono_compile_method
= func
;
480 * mono_compile_method:
481 * @method: The method to compile.
483 * This JIT-compiles the method, and returns the pointer to the native code
487 mono_compile_method (MonoMethod
*method
)
489 if (!default_mono_compile_method
) {
490 g_error ("compile method called on uninitialized runtime");
493 return default_mono_compile_method (method
);
496 static MonoFreeMethodFunc default_mono_free_method
= NULL
;
499 * mono_install_free_method:
500 * @func: pointer to the MonoFreeMethodFunc used to release a method
502 * This is an internal VM routine, it is used for the engines to
503 * register a handler to release the resources associated with a method.
505 * Methods are freed when no more references to the delegate that holds
509 mono_install_free_method (MonoFreeMethodFunc func
)
511 default_mono_free_method
= func
;
515 * mono_runtime_free_method:
516 * @domain; domain where the method is hosted
517 * @method: method to release
519 * This routine is invoked to free the resources associated with
520 * a method that has been JIT compiled. This is used to discard
521 * methods that were used only temporarily (for example, used in marshalling)
525 mono_runtime_free_method (MonoDomain
*domain
, MonoMethod
*method
)
527 if (default_mono_free_method
!= NULL
)
528 default_mono_free_method (domain
, method
);
530 mono_free_method (method
);
533 static MonoInitVTableFunc init_vtable_func
= NULL
;
536 * mono_install_init_vtable:
537 * @func: pointer to the function to be installed
539 * Register a function which will be called by the runtime to initialize the
540 * method pointers inside a vtable. The JIT can use this function to load the
541 * vtable from the AOT file for example.
544 mono_install_init_vtable (MonoInitVTableFunc func
)
546 init_vtable_func
= func
;
550 * The vtables in the root appdomain are assumed to be reachable by other
551 * roots, and we don't use typed allocation in the other domains.
554 /* The sync block is no longer a GC pointer */
555 #define GC_HEADER_BITMAP (0)
557 #define BITMAP_EL_SIZE (sizeof (gsize) * 8)
560 compute_class_bitmap (MonoClass
*class, gsize
*bitmap
, int size
, int offset
, int *max_set
, gboolean static_fields
)
562 MonoClassField
*field
;
568 max_size
= mono_class_data_size (class) / sizeof (gpointer
);
570 max_size
= class->instance_size
/ sizeof (gpointer
);
571 if (max_size
>= size
) {
572 bitmap
= g_malloc0 (sizeof (gsize
) * ((max_size
) + 1));
575 for (p
= class; p
!= NULL
; p
= p
->parent
) {
576 gpointer iter
= NULL
;
577 while ((field
= mono_class_get_fields (p
, &iter
))) {
581 if (!(field
->type
->attrs
& (FIELD_ATTRIBUTE_STATIC
| FIELD_ATTRIBUTE_HAS_FIELD_RVA
)))
584 if (field
->type
->attrs
& (FIELD_ATTRIBUTE_STATIC
| FIELD_ATTRIBUTE_HAS_FIELD_RVA
))
587 /* FIXME: should not happen, flag as type load error */
588 if (field
->type
->byref
)
591 pos
= field
->offset
/ sizeof (gpointer
);
594 type
= mono_type_get_underlying_type (field
->type
);
595 switch (type
->type
) {
598 case MONO_TYPE_FNPTR
:
600 /* only UIntPtr is allowed to be GC-tracked and only in mscorlib */
605 if (class->image
!= mono_defaults
.corlib
)
608 case MONO_TYPE_STRING
:
609 case MONO_TYPE_SZARRAY
:
610 case MONO_TYPE_CLASS
:
611 case MONO_TYPE_OBJECT
:
612 case MONO_TYPE_ARRAY
:
613 g_assert ((field
->offset
% sizeof(gpointer
)) == 0);
615 bitmap
[pos
/ BITMAP_EL_SIZE
] |= ((gsize
)1) << (pos
% BITMAP_EL_SIZE
);
616 *max_set
= MAX (*max_set
, pos
);
618 case MONO_TYPE_GENERICINST
:
619 if (!mono_type_generic_inst_is_valuetype (type
)) {
620 g_assert ((field
->offset
% sizeof(gpointer
)) == 0);
622 bitmap
[pos
/ BITMAP_EL_SIZE
] |= ((gsize
)1) << (pos
% BITMAP_EL_SIZE
);
623 *max_set
= MAX (*max_set
, pos
);
628 case MONO_TYPE_VALUETYPE
: {
629 MonoClass
*fclass
= mono_class_from_mono_type (field
->type
);
630 if (fclass
->has_references
) {
631 /* remove the object header */
632 compute_class_bitmap (fclass
, bitmap
, size
, pos
- (sizeof (MonoObject
) / sizeof (gpointer
)), max_set
, FALSE
);
646 case MONO_TYPE_BOOLEAN
:
650 g_assert_not_reached ();
662 * similar to the above, but sets the bits in the bitmap for any non-ref field
663 * and ignores static fields
666 compute_class_non_ref_bitmap (MonoClass
*class, gsize
*bitmap
, int size
, int offset
)
668 MonoClassField
*field
;
673 max_size
= class->instance_size
/ sizeof (gpointer
);
674 if (max_size
>= size
) {
675 bitmap
= g_malloc0 (sizeof (gsize
) * ((max_size
) + 1));
678 for (p
= class; p
!= NULL
; p
= p
->parent
) {
679 gpointer iter
= NULL
;
680 while ((field
= mono_class_get_fields (p
, &iter
))) {
683 if (field
->type
->attrs
& (FIELD_ATTRIBUTE_STATIC
| FIELD_ATTRIBUTE_HAS_FIELD_RVA
))
685 /* FIXME: should not happen, flag as type load error */
686 if (field
->type
->byref
)
689 pos
= field
->offset
/ sizeof (gpointer
);
692 type
= mono_type_get_underlying_type (field
->type
);
693 switch (type
->type
) {
694 #if SIZEOF_VOID_P == 8
698 case MONO_TYPE_FNPTR
:
703 if ((((field
->offset
+ 7) / sizeof (gpointer
)) + offset
) != pos
) {
704 pos2
= ((field
->offset
+ 7) / sizeof (gpointer
)) + offset
;
705 bitmap
[pos2
/ BITMAP_EL_SIZE
] |= ((gsize
)1) << (pos2
% BITMAP_EL_SIZE
);
708 #if SIZEOF_VOID_P == 4
712 case MONO_TYPE_FNPTR
:
717 if ((((field
->offset
+ 3) / sizeof (gpointer
)) + offset
) != pos
) {
718 pos2
= ((field
->offset
+ 3) / sizeof (gpointer
)) + offset
;
719 bitmap
[pos2
/ BITMAP_EL_SIZE
] |= ((gsize
)1) << (pos2
% BITMAP_EL_SIZE
);
725 if ((((field
->offset
+ 1) / sizeof (gpointer
)) + offset
) != pos
) {
726 pos2
= ((field
->offset
+ 1) / sizeof (gpointer
)) + offset
;
727 bitmap
[pos2
/ BITMAP_EL_SIZE
] |= ((gsize
)1) << (pos2
% BITMAP_EL_SIZE
);
730 case MONO_TYPE_BOOLEAN
:
733 bitmap
[pos
/ BITMAP_EL_SIZE
] |= ((gsize
)1) << (pos
% BITMAP_EL_SIZE
);
735 case MONO_TYPE_STRING
:
736 case MONO_TYPE_SZARRAY
:
737 case MONO_TYPE_CLASS
:
738 case MONO_TYPE_OBJECT
:
739 case MONO_TYPE_ARRAY
:
741 case MONO_TYPE_GENERICINST
:
742 if (!mono_type_generic_inst_is_valuetype (type
)) {
747 case MONO_TYPE_VALUETYPE
: {
748 MonoClass
*fclass
= mono_class_from_mono_type (field
->type
);
749 /* remove the object header */
750 compute_class_non_ref_bitmap (fclass
, bitmap
, size
, pos
- (sizeof (MonoObject
) / sizeof (gpointer
)));
754 g_assert_not_reached ();
763 * mono_class_insecure_overlapping:
764 * check if a class with explicit layout has references and non-references
765 * fields overlapping.
767 * Returns: TRUE if it is insecure to load the type.
770 mono_class_insecure_overlapping (MonoClass
*klass
)
774 gsize default_bitmap
[4] = {0};
776 gsize default_nrbitmap
[4] = {0};
777 int i
, insecure
= FALSE
;
780 bitmap
= compute_class_bitmap (klass
, default_bitmap
, sizeof (default_bitmap
) * 8, 0, &max_set
, FALSE
);
781 nrbitmap
= compute_class_non_ref_bitmap (klass
, default_nrbitmap
, sizeof (default_nrbitmap
) * 8, 0);
783 for (i
= 0; i
<= max_set
; i
+= sizeof (bitmap
[0]) * 8) {
784 int idx
= i
% (sizeof (bitmap
[0]) * 8);
785 if (bitmap
[idx
] & nrbitmap
[idx
]) {
790 if (bitmap
!= default_bitmap
)
792 if (nrbitmap
!= default_nrbitmap
)
795 g_print ("class %s.%s in assembly %s has overlapping references\n", klass
->name_space
, klass
->name
, klass
->image
->name
);
803 mono_class_compute_gc_descriptor (MonoClass
*class)
807 gsize default_bitmap
[4] = {0};
808 static gboolean gcj_inited
= FALSE
;
813 mono_register_jit_icall (mono_object_new_ptrfree
, "mono_object_new_ptrfree", mono_create_icall_signature ("object ptr"), FALSE
);
814 mono_register_jit_icall (mono_object_new_ptrfree_box
, "mono_object_new_ptrfree_box", mono_create_icall_signature ("object ptr"), FALSE
);
815 mono_register_jit_icall (mono_object_new_fast
, "mono_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE
);
817 #ifdef HAVE_GC_GCJ_MALLOC
819 GC_init_gcj_malloc (5, NULL
);
821 #ifdef GC_REDIRECT_TO_LOCAL
822 mono_register_jit_icall (GC_local_gcj_malloc
, "GC_local_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE
);
823 mono_register_jit_icall (GC_local_gcj_fast_malloc
, "GC_local_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE
);
825 mono_register_jit_icall (GC_gcj_malloc
, "GC_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE
);
826 mono_register_jit_icall (GC_gcj_fast_malloc
, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE
);
829 mono_loader_unlock ();
833 mono_class_init (class);
835 if (class->gc_descr_inited
)
838 class->gc_descr_inited
= TRUE
;
839 class->gc_descr
= GC_NO_DESCRIPTOR
;
841 bitmap
= default_bitmap
;
842 if (class == mono_defaults
.string_class
) {
843 class->gc_descr
= (gpointer
)MAKE_STRING_DESCRIPTOR (bitmap
, 2);
844 } else if (class->rank
) {
845 mono_class_compute_gc_descriptor (class->element_class
);
847 /* libgc has no usable support for arrays... */
848 if (!class->element_class
->valuetype
) {
850 class->gc_descr
= mono_gc_make_descr_for_array (TRUE
, &abm
, 1, sizeof (gpointer
));
851 /*printf ("new array descriptor: 0x%x for %s.%s\n", class->gc_descr,
852 class->name_space, class->name);*/
854 /* remove the object header */
855 bitmap
= compute_class_bitmap (class->element_class
, default_bitmap
, sizeof (default_bitmap
) * 8, - (sizeof (MonoObject
) / sizeof (gpointer
)), &max_set
, FALSE
);
856 class->gc_descr
= mono_gc_make_descr_for_array (TRUE
, bitmap
, mono_array_element_size (class) / sizeof (gpointer
), mono_array_element_size (class));
857 /*printf ("new vt array descriptor: 0x%x for %s.%s\n", class->gc_descr,
858 class->name_space, class->name);*/
859 if (bitmap
!= default_bitmap
)
864 /*static int count = 0;
867 bitmap
= compute_class_bitmap (class, default_bitmap
, sizeof (default_bitmap
) * 8, 0, &max_set
, FALSE
);
869 /* It seems there are issues when the bitmap doesn't fit: play it safe */
871 /*g_print ("disabling typed alloc (%d) for %s.%s\n", max_set, class->name_space, class->name);*/
872 if (bitmap
!= default_bitmap
)
877 class->gc_descr
= (gpointer
)MAKE_DESCRIPTOR (bitmap
, max_set
+ 1, class->instance_size
);
878 /*printf ("new descriptor: %p 0x%x for %s.%s\n", class->gc_descr, bitmap [0], class->name_space, class->name);*/
879 if (bitmap
!= default_bitmap
)
885 * field_is_special_static:
886 * @fklass: The MonoClass to look up.
887 * @field: The MonoClassField describing the field.
889 * Returns: SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
890 * SPECIAL_STATIC_NONE otherwise.
893 field_is_special_static (MonoClass
*fklass
, MonoClassField
*field
)
895 MonoCustomAttrInfo
*ainfo
;
897 ainfo
= mono_custom_attrs_from_field (fklass
, field
);
900 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
901 MonoClass
*klass
= ainfo
->attrs
[i
].ctor
->klass
;
902 if (klass
->image
== mono_defaults
.corlib
) {
903 if (strcmp (klass
->name
, "ThreadStaticAttribute") == 0) {
904 mono_custom_attrs_free (ainfo
);
905 return SPECIAL_STATIC_THREAD
;
907 else if (strcmp (klass
->name
, "ContextStaticAttribute") == 0) {
908 mono_custom_attrs_free (ainfo
);
909 return SPECIAL_STATIC_CONTEXT
;
913 mono_custom_attrs_free (ainfo
);
914 return SPECIAL_STATIC_NONE
;
917 static MonoVTable
*mono_class_create_runtime_vtable (MonoDomain
*domain
, MonoClass
*class);
921 * @domain: the application domain
922 * @class: the class to initialize
924 * VTables are domain specific because we create domain specific code, and
925 * they contain the domain specific static class data.
928 mono_class_vtable (MonoDomain
*domain
, MonoClass
*class)
930 MonoClassRuntimeInfo
*runtime_info
;
934 /* this check can be inlined in jitted code, too */
935 runtime_info
= class->runtime_info
;
936 if (runtime_info
&& runtime_info
->max_domain
>= domain
->domain_id
&& runtime_info
->domain_vtables
[domain
->domain_id
])
937 return runtime_info
->domain_vtables
[domain
->domain_id
];
938 return mono_class_create_runtime_vtable (domain
, class);
942 mono_class_create_runtime_vtable (MonoDomain
*domain
, MonoClass
*class)
945 MonoClassRuntimeInfo
*runtime_info
, *old_info
;
946 MonoClassField
*field
;
949 gboolean inited
= FALSE
;
950 guint32 vtable_size
, class_size
;
952 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
954 gpointer
*interface_offsets
;
956 mono_domain_lock (domain
);
957 runtime_info
= class->runtime_info
;
958 if (runtime_info
&& runtime_info
->max_domain
>= domain
->domain_id
&& runtime_info
->domain_vtables
[domain
->domain_id
]) {
959 mono_domain_unlock (domain
);
960 return runtime_info
->domain_vtables
[domain
->domain_id
];
962 if (!class->inited
|| class->exception_type
) {
963 if (!mono_class_init (class) || class->exception_type
){
965 mono_domain_unlock (domain
);
966 exc
= mono_class_get_exception_for_failure (class);
968 mono_raise_exception (exc
);
972 mono_class_init (class);
974 /* FIXME: This should be done by mono_class_init () for dynamic classes as well */
975 if (class->image
->dynamic
)
976 mono_class_setup_vtable (class);
978 vtable_size
= sizeof (gpointer
) * (class->max_interface_id
+ 1) +
979 sizeof (MonoVTable
) + class->vtable_size
* sizeof (gpointer
);
981 mono_stats
.used_class_count
++;
982 mono_stats
.class_vtable_size
+= vtable_size
;
983 interface_offsets
= mono_mempool_alloc0 (domain
->mp
, vtable_size
);
985 vt
= (MonoVTable
*) (interface_offsets
+ class->max_interface_id
+ 1);
987 vt
->rank
= class->rank
;
990 mono_class_compute_gc_descriptor (class);
992 * We can't use typed allocation in the non-root domains, since the
993 * collector needs the GC descriptor stored in the vtable even after
994 * the mempool containing the vtable is destroyed when the domain is
995 * unloaded. An alternative might be to allocate vtables in the GC
996 * heap, but this does not seem to work (it leads to crashes inside
997 * libgc). If that approach is tried, two gc descriptors need to be
998 * allocated for each class: one for the root domain, and one for all
999 * other domains. The second descriptor should contain a bit for the
1000 * vtable field in MonoObject, since we can no longer assume the
1001 * vtable is reachable by other roots after the appdomain is unloaded.
1003 #ifdef HAVE_BOEHM_GC
1004 if (domain
!= mono_get_root_domain ())
1005 vt
->gc_descr
= GC_NO_DESCRIPTOR
;
1008 vt
->gc_descr
= class->gc_descr
;
1010 if ((class_size
= mono_class_data_size (class))) {
1011 if (class->has_static_refs
) {
1012 gpointer statics_gc_descr
;
1014 gsize default_bitmap
[4] = {0};
1017 bitmap
= compute_class_bitmap (class, default_bitmap
, sizeof (default_bitmap
) * 8, 0, &max_set
, TRUE
);
1018 /*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class_size);*/
1019 statics_gc_descr
= mono_gc_make_descr_from_bitmap (bitmap
, max_set
? max_set
+ 1: 0);
1020 vt
->data
= mono_gc_alloc_fixed (class_size
, statics_gc_descr
);
1021 mono_domain_add_class_static_data (domain
, class, vt
->data
, NULL
);
1022 if (bitmap
!= default_bitmap
)
1025 vt
->data
= mono_mempool_alloc0 (domain
->mp
, class_size
);
1027 mono_stats
.class_static_data_size
+= class_size
;
1032 while ((field
= mono_class_get_fields (class, &iter
))) {
1033 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
))
1035 if (mono_field_is_deleted (field
))
1037 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_LITERAL
)) {
1038 gint32 special_static
= class->no_special_static_fields
? SPECIAL_STATIC_NONE
: field_is_special_static (class, field
);
1039 if (special_static
!= SPECIAL_STATIC_NONE
) {
1040 guint32 size
, offset
;
1042 size
= mono_type_size (field
->type
, &align
);
1043 offset
= mono_alloc_special_static_data (special_static
, size
, align
);
1044 if (!domain
->special_static_fields
)
1045 domain
->special_static_fields
= g_hash_table_new (NULL
, NULL
);
1046 g_hash_table_insert (domain
->special_static_fields
, field
, GUINT_TO_POINTER (offset
));
1050 if ((field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
)) {
1051 MonoClass
*fklass
= mono_class_from_mono_type (field
->type
);
1052 g_assert (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
));
1053 t
= (char*)vt
->data
+ field
->offset
;
1054 if (fklass
->valuetype
) {
1055 memcpy (t
, field
->data
, mono_class_value_size (fklass
, NULL
));
1057 /* it's a pointer type: add check */
1058 g_assert ((fklass
->byval_arg
.type
== MONO_TYPE_PTR
) || (fklass
->byval_arg
.type
== MONO_TYPE_FNPTR
));
1059 *t
= *(char *)field
->data
;
1063 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
))
1066 /* later do this only on demand if needed */
1068 cindex
= mono_metadata_get_constant_index (class->image
, mono_class_get_field_token (field
), cindex
+ 1);
1070 g_assert (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
));
1072 mono_metadata_decode_row (&class->image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
1073 field
->def_type
= constant_cols
[MONO_CONSTANT_TYPE
];
1074 field
->data
= (gpointer
)mono_metadata_blob_heap (class->image
, constant_cols
[MONO_CONSTANT_VALUE
]);
1079 vt
->max_interface_id
= class->max_interface_id
;
1081 /* initialize interface offsets */
1082 for (i
= 0; i
<= class->max_interface_id
; ++i
) {
1083 int slot
= class->interface_offsets
[i
];
1085 interface_offsets
[class->max_interface_id
- i
] = &(vt
->vtable
[slot
]);
1089 * arch_create_jit_trampoline () can recursively call this function again
1090 * because it compiles icall methods right away.
1092 /* FIXME: class_vtable_hash is basically obsolete now: remove as soon
1093 * as we change the code in appdomain.c to invalidate vtables by
1094 * looking at the possible MonoClasses created for the domain.
1096 g_hash_table_insert (domain
->class_vtable_hash
, class, vt
);
1097 /* class->runtime_info is protected by the loader lock, both when
1098 * it it enlarged and when it is stored info.
1100 mono_loader_lock ();
1101 old_info
= class->runtime_info
;
1102 if (old_info
&& old_info
->max_domain
>= domain
->domain_id
) {
1103 /* someone already created a large enough runtime info */
1104 old_info
->domain_vtables
[domain
->domain_id
] = vt
;
1106 int new_size
= domain
->domain_id
;
1108 new_size
= MAX (new_size
, old_info
->max_domain
);
1110 /* make the new size a power of two */
1112 while (new_size
> i
)
1115 /* this is a bounded memory retention issue: may want to
1116 * handle it differently when we'll have a rcu-like system.
1118 runtime_info
= mono_mempool_alloc0 (class->image
->mempool
, sizeof (MonoClassRuntimeInfo
) + new_size
* sizeof (gpointer
));
1119 runtime_info
->max_domain
= new_size
- 1;
1120 /* copy the stuff from the older info */
1122 memcpy (runtime_info
->domain_vtables
, old_info
->domain_vtables
, (old_info
->max_domain
+ 1) * sizeof (gpointer
));
1124 runtime_info
->domain_vtables
[domain
->domain_id
] = vt
;
1125 /* keep this last (add membarrier) */
1126 class->runtime_info
= runtime_info
;
1128 mono_loader_unlock ();
1130 /* initialize vtable */
1131 if (init_vtable_func
)
1132 inited
= init_vtable_func (vt
);
1135 mono_class_setup_vtable (class);
1137 for (i
= 0; i
< class->vtable_size
; ++i
) {
1140 if ((cm
= class->vtable
[i
])) {
1141 if (mono_method_signature (cm
)->generic_param_count
)
1142 vt
->vtable
[i
] = cm
;
1144 vt
->vtable
[i
] = arch_create_jit_trampoline (cm
);
1149 mono_domain_unlock (domain
);
1151 /* Initialization is now complete, we can throw if the InheritanceDemand aren't satisfied */
1152 if (mono_is_security_manager_active () && (class->exception_type
== MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND
)) {
1153 MonoException
*exc
= mono_class_get_exception_for_failure (class);
1155 mono_raise_exception (exc
);
1158 /* make sure the the parent is initialized */
1160 mono_class_vtable (domain
, class->parent
);
1162 vt
->type
= mono_type_get_object (domain
, &class->byval_arg
);
1163 if (class->contextbound
)
1172 * mono_class_proxy_vtable:
1173 * @domain: the application domain
1174 * @remove_class: the remote class
1176 * Creates a vtable for transparent proxies. It is basically
1177 * a copy of the real vtable of the class wrapped in @remote_class,
1178 * but all function pointers invoke the remoting functions, and
1179 * vtable->klass points to the transparent proxy class, and not to @class.
1182 mono_class_proxy_vtable (MonoDomain
*domain
, MonoRemoteClass
*remote_class
, MonoRemotingTarget target_type
)
1184 MonoVTable
*vt
, *pvt
;
1185 int i
, j
, vtsize
, max_interface_id
, extra_interface_vtsize
= 0;
1187 GSList
*extra_interfaces
= NULL
;
1188 MonoClass
*class = remote_class
->proxy_class
;
1189 gpointer
*interface_offsets
;
1191 vt
= mono_class_vtable (domain
, class);
1192 max_interface_id
= vt
->max_interface_id
;
1194 /* Calculate vtable space for extra interfaces */
1195 for (j
= 0; j
< remote_class
->interface_count
; j
++) {
1196 MonoClass
* iclass
= remote_class
->interfaces
[j
];
1200 if (iclass
->interface_id
<= class->max_interface_id
&& class->interface_offsets
[iclass
->interface_id
] != -1)
1201 continue; /* interface implemented by the class */
1202 if (g_slist_find (extra_interfaces
, iclass
))
1205 extra_interfaces
= g_slist_prepend (extra_interfaces
, iclass
);
1207 method_count
= mono_class_num_methods (iclass
);
1209 ifaces
= mono_class_get_implemented_interfaces (iclass
);
1211 for (i
= 0; i
< ifaces
->len
; ++i
) {
1212 MonoClass
*ic
= g_ptr_array_index (ifaces
, i
);
1213 if (ic
->interface_id
<= class->max_interface_id
&& class->interface_offsets
[ic
->interface_id
] != -1)
1214 continue; /* interface implemented by the class */
1215 if (g_slist_find (extra_interfaces
, ic
))
1217 extra_interfaces
= g_slist_prepend (extra_interfaces
, ic
);
1218 method_count
+= mono_class_num_methods (ic
);
1220 g_ptr_array_free (ifaces
, TRUE
);
1223 extra_interface_vtsize
+= method_count
* sizeof (gpointer
);
1224 if (iclass
->max_interface_id
> max_interface_id
) max_interface_id
= iclass
->max_interface_id
;
1227 vtsize
= sizeof (gpointer
) * (max_interface_id
+ 1) +
1228 sizeof (MonoVTable
) + class->vtable_size
* sizeof (gpointer
);
1230 mono_stats
.class_vtable_size
+= vtsize
+ extra_interface_vtsize
;
1232 interface_offsets
= mono_mempool_alloc0 (domain
->mp
, vtsize
+ extra_interface_vtsize
);
1233 pvt
= (MonoVTable
*)(interface_offsets
+ max_interface_id
+ 1);
1234 memcpy (pvt
, vt
, sizeof (MonoVTable
) + class->vtable_size
* sizeof (gpointer
));
1236 pvt
->klass
= mono_defaults
.transparent_proxy_class
;
1237 /* we need to keep the GC descriptor for a transparent proxy or we confuse the precise GC */
1238 pvt
->gc_descr
= mono_defaults
.transparent_proxy_class
->gc_descr
;
1240 /* initialize vtable */
1241 mono_class_setup_vtable (class);
1242 for (i
= 0; i
< class->vtable_size
; ++i
) {
1245 if ((cm
= class->vtable
[i
]))
1246 pvt
->vtable
[i
] = arch_create_remoting_trampoline (cm
, target_type
);
1249 if (class->flags
& TYPE_ATTRIBUTE_ABSTRACT
) {
1250 /* create trampolines for abstract methods */
1251 for (k
= class; k
; k
= k
->parent
) {
1253 gpointer iter
= NULL
;
1254 while ((m
= mono_class_get_methods (k
, &iter
)))
1255 if (!pvt
->vtable
[m
->slot
])
1256 pvt
->vtable
[m
->slot
] = arch_create_remoting_trampoline (m
, target_type
);
1260 pvt
->max_interface_id
= max_interface_id
;
1262 /* initialize interface offsets */
1263 for (i
= 0; i
<= class->max_interface_id
; ++i
) {
1264 int slot
= class->interface_offsets
[i
];
1266 interface_offsets
[max_interface_id
- i
] = &(pvt
->vtable
[slot
]);
1269 if (extra_interfaces
) {
1270 int slot
= class->vtable_size
;
1276 /* Create trampolines for the methods of the interfaces */
1277 for (list_item
= extra_interfaces
; list_item
!= NULL
; list_item
=list_item
->next
) {
1278 interf
= list_item
->data
;
1279 interface_offsets
[max_interface_id
- interf
->interface_id
] = &pvt
->vtable
[slot
];
1283 while ((cm
= mono_class_get_methods (interf
, &iter
)))
1284 pvt
->vtable
[slot
+ j
++] = arch_create_remoting_trampoline (cm
, target_type
);
1286 slot
+= mono_class_num_methods (interf
);
1288 g_slist_free (extra_interfaces
);
1295 * mono_class_has_special_static_fields:
1297 * Returns whenever @klass has any thread/context static fields.
1300 mono_class_has_special_static_fields (MonoClass
*klass
)
1302 MonoClassField
*field
;
1306 while ((field
= mono_class_get_fields (klass
, &iter
))) {
1307 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
))
1309 if (mono_field_is_deleted (field
))
1311 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_LITERAL
)) {
1312 if (field_is_special_static (klass
, field
) != SPECIAL_STATIC_NONE
)
1321 * create_remote_class_key:
1322 * Creates an array of pointers that can be used as a hash key for a remote class.
1323 * The first element of the array is the number of pointers.
1326 create_remote_class_key (MonoRemoteClass
*remote_class
, MonoClass
*extra_class
)
1331 if (remote_class
== NULL
) {
1332 if (extra_class
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
1333 key
= g_malloc (sizeof(gpointer
) * 3);
1334 key
[0] = GINT_TO_POINTER (2);
1335 key
[1] = mono_defaults
.marshalbyrefobject_class
;
1336 key
[2] = extra_class
;
1338 key
= g_malloc (sizeof(gpointer
) * 2);
1339 key
[0] = GINT_TO_POINTER (1);
1340 key
[1] = extra_class
;
1343 if (extra_class
!= NULL
&& (extra_class
->flags
& TYPE_ATTRIBUTE_INTERFACE
)) {
1344 key
= g_malloc (sizeof(gpointer
) * (remote_class
->interface_count
+ 3));
1345 key
[0] = GINT_TO_POINTER (remote_class
->interface_count
+ 2);
1346 key
[1] = remote_class
->proxy_class
;
1348 // Keep the list of interfaces sorted
1349 for (i
= 0, j
= 2; i
< remote_class
->interface_count
; i
++, j
++) {
1350 if (extra_class
&& remote_class
->interfaces
[i
] > extra_class
) {
1351 key
[j
++] = extra_class
;
1354 key
[j
] = remote_class
->interfaces
[i
];
1357 key
[j
] = extra_class
;
1359 // Replace the old class. The interface list is the same
1360 key
= g_malloc (sizeof(gpointer
) * (remote_class
->interface_count
+ 2));
1361 key
[0] = GINT_TO_POINTER (remote_class
->interface_count
+ 1);
1362 key
[1] = extra_class
!= NULL
? extra_class
: remote_class
->proxy_class
;
1363 for (i
= 0; i
< remote_class
->interface_count
; i
++)
1364 key
[2 + i
] = remote_class
->interfaces
[i
];
1372 * copy_remote_class_key:
1374 * Make a copy of KEY in the mempool MP and return the copy.
1377 copy_remote_class_key (MonoMemPool
*mp
, gpointer
*key
)
1379 int key_size
= (GPOINTER_TO_UINT (key
[0]) + 1) * sizeof (gpointer
);
1380 gpointer
*mp_key
= mono_mempool_alloc (mp
, key_size
);
1382 memcpy (mp_key
, key
, key_size
);
1388 * mono_remote_class:
1389 * @domain: the application domain
1390 * @class_name: name of the remote class
1392 * Creates and initializes a MonoRemoteClass object for a remote type.
1396 mono_remote_class (MonoDomain
*domain
, MonoString
*class_name
, MonoClass
*proxy_class
)
1398 MonoRemoteClass
*rc
;
1399 gpointer
* key
, *mp_key
;
1401 key
= create_remote_class_key (NULL
, proxy_class
);
1403 mono_domain_lock (domain
);
1404 rc
= g_hash_table_lookup (domain
->proxy_vtable_hash
, key
);
1408 mono_domain_unlock (domain
);
1412 mp_key
= copy_remote_class_key (domain
->mp
, key
);
1416 if (proxy_class
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
1417 rc
= mono_mempool_alloc (domain
->mp
, sizeof(MonoRemoteClass
) + sizeof(MonoClass
*));
1418 rc
->interface_count
= 1;
1419 rc
->interfaces
[0] = proxy_class
;
1420 rc
->proxy_class
= mono_defaults
.marshalbyrefobject_class
;
1422 rc
= mono_mempool_alloc (domain
->mp
, sizeof(MonoRemoteClass
));
1423 rc
->interface_count
= 0;
1424 rc
->proxy_class
= proxy_class
;
1427 rc
->default_vtable
= NULL
;
1428 rc
->xdomain_vtable
= NULL
;
1429 rc
->proxy_class_name
= mono_string_to_utf8_mp (domain
->mp
, class_name
);
1431 g_hash_table_insert (domain
->proxy_vtable_hash
, key
, rc
);
1433 mono_domain_unlock (domain
);
1438 * clone_remote_class:
1439 * Creates a copy of the remote_class, adding the provided class or interface
1441 static MonoRemoteClass
*
1442 clone_remote_class (MonoDomain
*domain
, MonoRemoteClass
* remote_class
, MonoClass
*extra_class
)
1444 MonoRemoteClass
*rc
;
1445 gpointer
* key
, *mp_key
;
1447 key
= create_remote_class_key (remote_class
, extra_class
);
1448 rc
= g_hash_table_lookup (domain
->proxy_vtable_hash
, key
);
1454 mp_key
= copy_remote_class_key (domain
->mp
, key
);
1458 if (extra_class
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
1460 rc
= mono_mempool_alloc (domain
->mp
, sizeof(MonoRemoteClass
) + sizeof(MonoClass
*) * (remote_class
->interface_count
+ 1));
1461 rc
->proxy_class
= remote_class
->proxy_class
;
1462 rc
->interface_count
= remote_class
->interface_count
+ 1;
1464 // Keep the list of interfaces sorted, since the hash key of
1465 // the remote class depends on this
1466 for (i
= 0, j
= 0; i
< remote_class
->interface_count
; i
++, j
++) {
1467 if (remote_class
->interfaces
[i
] > extra_class
&& i
== j
)
1468 rc
->interfaces
[j
++] = extra_class
;
1469 rc
->interfaces
[j
] = remote_class
->interfaces
[i
];
1472 rc
->interfaces
[j
] = extra_class
;
1474 // Replace the old class. The interface array is the same
1475 rc
= mono_mempool_alloc (domain
->mp
, sizeof(MonoRemoteClass
) + sizeof(MonoClass
*) * remote_class
->interface_count
);
1476 rc
->proxy_class
= extra_class
;
1477 rc
->interface_count
= remote_class
->interface_count
;
1478 if (rc
->interface_count
> 0)
1479 memcpy (rc
->interfaces
, remote_class
->interfaces
, rc
->interface_count
* sizeof (MonoClass
*));
1482 rc
->default_vtable
= NULL
;
1483 rc
->xdomain_vtable
= NULL
;
1484 rc
->proxy_class_name
= remote_class
->proxy_class_name
;
1486 g_hash_table_insert (domain
->proxy_vtable_hash
, key
, rc
);
1492 mono_remote_class_vtable (MonoDomain
*domain
, MonoRemoteClass
*remote_class
, MonoRealProxy
*rp
)
1494 mono_domain_lock (domain
);
1495 if (rp
->target_domain_id
!= -1) {
1496 if (remote_class
->xdomain_vtable
== NULL
)
1497 remote_class
->xdomain_vtable
= mono_class_proxy_vtable (domain
, remote_class
, MONO_REMOTING_TARGET_APPDOMAIN
);
1498 mono_domain_unlock (domain
);
1499 return remote_class
->xdomain_vtable
;
1501 if (remote_class
->default_vtable
== NULL
) {
1504 type
= ((MonoReflectionType
*)rp
->class_to_proxy
)->type
;
1505 klass
= mono_class_from_mono_type (type
);
1506 if ((klass
->is_com_object
|| (mono_defaults
.com_object_class
&& klass
== mono_defaults
.com_object_class
)) && !mono_class_vtable (mono_domain_get (), klass
)->remote
)
1507 remote_class
->default_vtable
= mono_class_proxy_vtable (domain
, remote_class
, MONO_REMOTING_TARGET_COMINTEROP
);
1509 remote_class
->default_vtable
= mono_class_proxy_vtable (domain
, remote_class
, MONO_REMOTING_TARGET_UNKNOWN
);
1512 mono_domain_unlock (domain
);
1513 return remote_class
->default_vtable
;
1517 * mono_upgrade_remote_class:
1518 * @domain: the application domain
1519 * @tproxy: the proxy whose remote class has to be upgraded.
1520 * @klass: class to which the remote class can be casted.
1522 * Updates the vtable of the remote class by adding the necessary method slots
1523 * and interface offsets so it can be safely casted to klass. klass can be a
1524 * class or an interface.
1527 mono_upgrade_remote_class (MonoDomain
*domain
, MonoObject
*proxy_object
, MonoClass
*klass
)
1529 MonoTransparentProxy
*tproxy
;
1530 MonoRemoteClass
*remote_class
;
1531 gboolean redo_vtable
;
1533 mono_domain_lock (domain
);
1535 tproxy
= (MonoTransparentProxy
*) proxy_object
;
1536 remote_class
= tproxy
->remote_class
;
1538 if (klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
1541 for (i
= 0; i
< remote_class
->interface_count
&& redo_vtable
; i
++)
1542 if (remote_class
->interfaces
[i
] == klass
)
1543 redo_vtable
= FALSE
;
1546 redo_vtable
= (remote_class
->proxy_class
!= klass
);
1550 tproxy
->remote_class
= clone_remote_class (domain
, remote_class
, klass
);
1551 proxy_object
->vtable
= mono_remote_class_vtable (domain
, tproxy
->remote_class
, tproxy
->rp
);
1554 mono_domain_unlock (domain
);
1559 * mono_object_get_virtual_method:
1560 * @obj: object to operate on.
1563 * Retrieves the MonoMethod that would be called on obj if obj is passed as
1564 * the instance of a callvirt of method.
1567 mono_object_get_virtual_method (MonoObject
*obj
, MonoMethod
*method
)
1570 MonoMethod
**vtable
;
1572 MonoMethod
*res
= NULL
;
1574 klass
= mono_object_class (obj
);
1575 if (klass
== mono_defaults
.transparent_proxy_class
) {
1576 klass
= ((MonoTransparentProxy
*)obj
)->remote_class
->proxy_class
;
1582 if (!is_proxy
&& ((method
->flags
& METHOD_ATTRIBUTE_FINAL
) || !(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)))
1585 mono_class_setup_vtable (klass
);
1586 vtable
= klass
->vtable
;
1588 /* check method->slot is a valid index: perform isinstance? */
1589 if (method
->klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
1591 res
= vtable
[klass
->interface_offsets
[method
->klass
->interface_id
] + method
->slot
];
1593 if (method
->slot
!= -1)
1594 res
= vtable
[method
->slot
];
1598 if (!res
) res
= method
; /* It may be an interface or abstract class method */
1599 res
= mono_marshal_get_remoting_invoke (res
);
1608 dummy_mono_runtime_invoke (MonoMethod
*method
, void *obj
, void **params
, MonoObject
**exc
)
1610 g_error ("runtime invoke called on uninitialized runtime");
1614 static MonoInvokeFunc default_mono_runtime_invoke
= dummy_mono_runtime_invoke
;
1617 * mono_runtime_invoke:
1618 * @method: method to invoke
1619 * @obJ: object instance
1620 * @params: arguments to the method
1621 * @exc: exception information.
1623 * Invokes the method represented by @method on the object @obj.
1625 * obj is the 'this' pointer, it should be NULL for static
1626 * methods, a MonoObject* for object instances and a pointer to
1627 * the value type for value types.
1629 * The params array contains the arguments to the method with the
1630 * same convention: MonoObject* pointers for object instances and
1631 * pointers to the value type otherwise.
1633 * From unmanaged code you'll usually use the
1634 * mono_runtime_invoke() variant.
1636 * Note that this function doesn't handle virtual methods for
1637 * you, it will exec the exact method you pass: we still need to
1638 * expose a function to lookup the derived class implementation
1639 * of a virtual method (there are examples of this in the code,
1642 * You can pass NULL as the exc argument if you don't want to
1643 * catch exceptions, otherwise, *exc will be set to the exception
1644 * thrown, if any. if an exception is thrown, you can't use the
1645 * MonoObject* result from the function.
1647 * If the method returns a value type, it is boxed in an object
1651 mono_runtime_invoke (MonoMethod
*method
, void *obj
, void **params
, MonoObject
**exc
)
1653 return default_mono_runtime_invoke (method
, obj
, params
, exc
);
1657 set_value (MonoType
*type
, void *dest
, void *value
, int deref_pointer
)
1661 gpointer
*p
= (gpointer
*)dest
;
1668 case MONO_TYPE_BOOLEAN
:
1670 case MONO_TYPE_U1
: {
1671 guint8
*p
= (guint8
*)dest
;
1672 *p
= value
? *(guint8
*)value
: 0;
1677 case MONO_TYPE_CHAR
: {
1678 guint16
*p
= (guint16
*)dest
;
1679 *p
= value
? *(guint16
*)value
: 0;
1682 #if SIZEOF_VOID_P == 4
1687 case MONO_TYPE_U4
: {
1688 gint32
*p
= (gint32
*)dest
;
1689 *p
= value
? *(gint32
*)value
: 0;
1692 #if SIZEOF_VOID_P == 8
1697 case MONO_TYPE_U8
: {
1698 gint64
*p
= (gint64
*)dest
;
1699 *p
= value
? *(gint64
*)value
: 0;
1702 case MONO_TYPE_R4
: {
1703 float *p
= (float*)dest
;
1704 *p
= value
? *(float*)value
: 0;
1707 case MONO_TYPE_R8
: {
1708 double *p
= (double*)dest
;
1709 *p
= value
? *(double*)value
: 0;
1712 case MONO_TYPE_STRING
:
1713 case MONO_TYPE_SZARRAY
:
1714 case MONO_TYPE_CLASS
:
1715 case MONO_TYPE_OBJECT
:
1716 case MONO_TYPE_ARRAY
:
1717 mono_gc_wbarrier_generic_store (dest
, deref_pointer
? *(gpointer
*)value
: value
);
1719 case MONO_TYPE_FNPTR
:
1720 case MONO_TYPE_PTR
: {
1721 gpointer
*p
= (gpointer
*)dest
;
1722 *p
= deref_pointer
? *(gpointer
*)value
: value
;
1725 case MONO_TYPE_VALUETYPE
:
1726 /* note that 't' and 'type->type' can be different */
1727 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
1728 t
= type
->data
.klass
->enum_basetype
->type
;
1732 size
= mono_class_value_size (mono_class_from_mono_type (type
), NULL
);
1734 memset (dest
, 0, size
);
1736 memcpy (dest
, value
, size
);
1739 case MONO_TYPE_GENERICINST
:
1740 t
= type
->data
.generic_class
->container_class
->byval_arg
.type
;
1743 g_warning ("got type %x", type
->type
);
1744 g_assert_not_reached ();
1749 * mono_field_set_value:
1750 * @obj: Instance object
1751 * @field: MonoClassField describing the field to set
1752 * @value: The value to be set
1754 * Sets the value of the field described by @field in the object instance @obj
1755 * to the value passed in @value. This method should only be used for instance
1756 * fields. For static fields, use mono_field_static_set_value.
1758 * The value must be on the native format of the field type.
1761 mono_field_set_value (MonoObject
*obj
, MonoClassField
*field
, void *value
)
1765 g_return_if_fail (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
));
1767 dest
= (char*)obj
+ field
->offset
;
1768 set_value (field
->type
, dest
, value
, FALSE
);
1772 * mono_field_static_set_value:
1773 * @field: MonoClassField describing the field to set
1774 * @value: The value to be set
1776 * Sets the value of the static field described by @field
1777 * to the value passed in @value.
1779 * The value must be on the native format of the field type.
1782 mono_field_static_set_value (MonoVTable
*vt
, MonoClassField
*field
, void *value
)
1786 g_return_if_fail (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
);
1787 /* you cant set a constant! */
1788 g_return_if_fail (!(field
->type
->attrs
& FIELD_ATTRIBUTE_LITERAL
));
1790 dest
= (char*)vt
->data
+ field
->offset
;
1791 set_value (field
->type
, dest
, value
, FALSE
);
1794 /* Used by the debugger */
1796 mono_vtable_get_static_field_data (MonoVTable
*vt
)
1802 * mono_field_get_value:
1803 * @obj: Object instance
1804 * @field: MonoClassField describing the field to fetch information from
1805 * @value: pointer to the location where the value will be stored
1807 * Use this routine to get the value of the field @field in the object
1810 * The pointer provided by value must be of the field type, for reference
1811 * types this is a MonoObject*, for value types its the actual pointer to
1816 * mono_field_get_value (obj, int_field, &i);
1819 mono_field_get_value (MonoObject
*obj
, MonoClassField
*field
, void *value
)
1823 g_return_if_fail (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
));
1825 src
= (char*)obj
+ field
->offset
;
1826 set_value (field
->type
, value
, src
, TRUE
);
1830 * mono_field_get_value_object:
1831 * @domain: domain where the object will be created (if boxing)
1832 * @field: MonoClassField describing the field to fetch information from
1833 * @obj: The object instance for the field.
1835 * Returns: a new MonoObject with the value from the given field. If the
1836 * field represents a value type, the value is boxed.
1840 mono_field_get_value_object (MonoDomain
*domain
, MonoClassField
*field
, MonoObject
*obj
)
1844 MonoVTable
*vtable
= NULL
;
1846 gboolean is_static
= FALSE
;
1847 gboolean is_ref
= FALSE
;
1849 switch (field
->type
->type
) {
1850 case MONO_TYPE_STRING
:
1851 case MONO_TYPE_OBJECT
:
1852 case MONO_TYPE_CLASS
:
1853 case MONO_TYPE_ARRAY
:
1854 case MONO_TYPE_SZARRAY
:
1859 case MONO_TYPE_BOOLEAN
:
1862 case MONO_TYPE_CHAR
:
1871 case MONO_TYPE_VALUETYPE
:
1872 is_ref
= field
->type
->byref
;
1874 case MONO_TYPE_GENERICINST
:
1875 is_ref
= !field
->type
->data
.generic_class
->container_class
->valuetype
;
1878 g_error ("type 0x%x not handled in "
1879 "mono_field_get_value_object", field
->type
->type
);
1883 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
1885 vtable
= mono_class_vtable (domain
, field
->parent
);
1886 if (!vtable
->initialized
)
1887 mono_runtime_class_init (vtable
);
1892 mono_field_static_get_value (vtable
, field
, &o
);
1894 mono_field_get_value (obj
, field
, &o
);
1899 /* boxed value type */
1900 klass
= mono_class_from_mono_type (field
->type
);
1901 o
= mono_object_new (domain
, klass
);
1902 v
= ((gchar
*) o
) + sizeof (MonoObject
);
1904 mono_field_static_get_value (vtable
, field
, v
);
1906 mono_field_get_value (obj
, field
, v
);
1913 mono_get_constant_value_from_blob (MonoDomain
* domain
, MonoTypeEnum type
, const char *blob
, void *value
)
1916 const char *p
= blob
;
1917 mono_metadata_decode_blob_size (p
, &p
);
1920 case MONO_TYPE_BOOLEAN
:
1923 *(guint8
*) value
= *p
;
1925 case MONO_TYPE_CHAR
:
1928 *(guint16
*) value
= read16 (p
);
1932 *(guint32
*) value
= read32 (p
);
1936 *(guint64
*) value
= read64 (p
);
1939 readr4 (p
, (float*) value
);
1942 readr8 (p
, (double*) value
);
1944 case MONO_TYPE_STRING
:
1945 *(gpointer
*) value
= mono_ldstr_metdata_sig (domain
, blob
);
1947 case MONO_TYPE_CLASS
:
1948 *(gpointer
*) value
= NULL
;
1952 g_warning ("type 0x%02x should not be in constant table", type
);
1958 get_default_field_value (MonoDomain
* domain
, MonoClassField
*field
, void *value
)
1960 g_return_if_fail (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
);
1961 mono_get_constant_value_from_blob (domain
, field
->def_type
, field
->data
, value
);
1965 * mono_field_static_get_value:
1966 * @vt: vtable to the object
1967 * @field: MonoClassField describing the field to fetch information from
1968 * @value: where the value is returned
1970 * Use this routine to get the value of the static field @field value.
1972 * The pointer provided by value must be of the field type, for reference
1973 * types this is a MonoObject*, for value types its the actual pointer to
1978 * mono_field_static_get_value (vt, int_field, &i);
1981 mono_field_static_get_value (MonoVTable
*vt
, MonoClassField
*field
, void *value
)
1985 g_return_if_fail (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
);
1987 if (field
->type
->attrs
& FIELD_ATTRIBUTE_LITERAL
) {
1988 get_default_field_value (vt
->domain
, field
, value
);
1992 src
= (char*)vt
->data
+ field
->offset
;
1993 set_value (field
->type
, value
, src
, TRUE
);
1997 * mono_property_set_value:
1998 * @prop: MonoProperty to set
1999 * @obj: instance object on which to act
2000 * @params: parameters to pass to the propery
2001 * @exc: optional exception
2003 * Invokes the property's set method with the given arguments on the
2004 * object instance obj (or NULL for static properties).
2006 * You can pass NULL as the exc argument if you don't want to
2007 * catch exceptions, otherwise, *exc will be set to the exception
2008 * thrown, if any. if an exception is thrown, you can't use the
2009 * MonoObject* result from the function.
2012 mono_property_set_value (MonoProperty
*prop
, void *obj
, void **params
, MonoObject
**exc
)
2014 default_mono_runtime_invoke (prop
->set
, obj
, params
, exc
);
2018 * mono_property_get_value:
2019 * @prop: MonoProperty to fetch
2020 * @obj: instance object on which to act
2021 * @params: parameters to pass to the propery
2022 * @exc: optional exception
2024 * Invokes the property's get method with the given arguments on the
2025 * object instance obj (or NULL for static properties).
2027 * You can pass NULL as the exc argument if you don't want to
2028 * catch exceptions, otherwise, *exc will be set to the exception
2029 * thrown, if any. if an exception is thrown, you can't use the
2030 * MonoObject* result from the function.
2032 * Returns: the value from invoking the get method on the property.
2035 mono_property_get_value (MonoProperty
*prop
, void *obj
, void **params
, MonoObject
**exc
)
2037 return default_mono_runtime_invoke (prop
->get
, obj
, params
, exc
);
2041 * mono_nullable_init:
2042 * @buf: The nullable structure to initialize.
2043 * @value: the value to initialize from
2044 * @klass: the type for the object
2046 * Initialize the nullable structure pointed to by @buf from @value which
2047 * should be a boxed value type. The size of @buf should be able to hold
2048 * as much data as the @klass->instance_size (which is the number of bytes
2049 * that will be copies).
2051 * Since Nullables have variable structure, we can not define a C
2052 * structure for them.
2055 mono_nullable_init (guint8
*buf
, MonoObject
*value
, MonoClass
*klass
)
2057 MonoClass
*param_class
= klass
->cast_class
;
2059 g_assert (mono_class_from_mono_type (klass
->fields
[0].type
) == param_class
);
2060 g_assert (mono_class_from_mono_type (klass
->fields
[1].type
) == mono_defaults
.boolean_class
);
2062 *(guint8
*)(buf
+ klass
->fields
[1].offset
- sizeof (MonoObject
)) = value
? 1 : 0;
2064 memcpy (buf
+ klass
->fields
[0].offset
- sizeof (MonoObject
), mono_object_unbox (value
), mono_class_value_size (param_class
, NULL
));
2066 memset (buf
+ klass
->fields
[0].offset
- sizeof (MonoObject
), 0, mono_class_value_size (param_class
, NULL
));
2070 * mono_nullable_box:
2071 * @buf: The buffer representing the data to be boxed
2072 * @klass: the type to box it as.
2074 * Creates a boxed vtype or NULL from the Nullable structure pointed to by
2078 mono_nullable_box (guint8
*buf
, MonoClass
*klass
)
2080 MonoClass
*param_class
= klass
->cast_class
;
2082 g_assert (mono_class_from_mono_type (klass
->fields
[0].type
) == param_class
);
2083 g_assert (mono_class_from_mono_type (klass
->fields
[1].type
) == mono_defaults
.boolean_class
);
2085 if (*(guint8
*)(buf
+ klass
->fields
[1].offset
- sizeof (MonoObject
))) {
2086 MonoObject
*o
= mono_object_new (mono_domain_get (), param_class
);
2087 memcpy (mono_object_unbox (o
), buf
+ klass
->fields
[0].offset
- sizeof (MonoObject
), mono_class_value_size (param_class
, NULL
));
2095 * mono_get_delegate_invoke:
2096 * @klass: The delegate class
2098 * Returns: the MonoMethod for the "Invoke" method in the delegate klass
2101 mono_get_delegate_invoke (MonoClass
*klass
)
2105 im
= mono_class_get_method_from_name (klass
, "Invoke", -1);
2112 * mono_runtime_delegate_invoke:
2113 * @delegate: pointer to a delegate object.
2114 * @params: parameters for the delegate.
2115 * @exc: Pointer to the exception result.
2117 * Invokes the delegate method @delegate with the parameters provided.
2119 * You can pass NULL as the exc argument if you don't want to
2120 * catch exceptions, otherwise, *exc will be set to the exception
2121 * thrown, if any. if an exception is thrown, you can't use the
2122 * MonoObject* result from the function.
2125 mono_runtime_delegate_invoke (MonoObject
*delegate
, void **params
, MonoObject
**exc
)
2129 im
= mono_get_delegate_invoke (delegate
->vtable
->klass
);
2132 return mono_runtime_invoke (im
, delegate
, params
, exc
);
2135 static char **main_args
= NULL
;
2136 static int num_main_args
;
2139 * mono_runtime_get_main_args:
2141 * Returns: a MonoArray with the arguments passed to the main program
2144 mono_runtime_get_main_args (void)
2148 MonoDomain
*domain
= mono_domain_get ();
2153 res
= (MonoArray
*)mono_array_new (domain
, mono_defaults
.string_class
, num_main_args
);
2155 for (i
= 0; i
< num_main_args
; ++i
)
2156 mono_array_setref (res
, i
, mono_string_new (domain
, main_args
[i
]));
2162 fire_process_exit_event (void)
2164 MonoClassField
*field
;
2165 MonoDomain
*domain
= mono_domain_get ();
2167 MonoObject
*delegate
, *exc
;
2169 field
= mono_class_get_field_from_name (mono_defaults
.appdomain_class
, "ProcessExit");
2172 if (domain
!= mono_get_root_domain ())
2175 delegate
= *(MonoObject
**)(((char *)domain
->domain
) + field
->offset
);
2176 if (delegate
== NULL
)
2181 mono_runtime_delegate_invoke (delegate
, pa
, &exc
);
2185 * mono_runtime_run_main:
2186 * @method: the method to start the application with (usually Main)
2187 * @argc: number of arguments from the command line
2188 * @argv: array of strings from the command line
2189 * @exc: excetption results
2191 * Execute a standard Main() method (argc/argv contains the
2192 * executable name). This method also sets the command line argument value
2193 * needed by System.Environment.
2198 mono_runtime_run_main (MonoMethod
*method
, int argc
, char* argv
[],
2202 MonoArray
*args
= NULL
;
2203 MonoDomain
*domain
= mono_domain_get ();
2204 gchar
*utf8_fullpath
;
2207 g_assert (method
!= NULL
);
2209 mono_thread_set_main (mono_thread_current ());
2211 main_args
= g_new0 (char*, argc
);
2212 num_main_args
= argc
;
2214 if (!g_path_is_absolute (argv
[0])) {
2215 gchar
*basename
= g_path_get_basename (argv
[0]);
2216 gchar
*fullpath
= g_build_filename (method
->klass
->image
->assembly
->basedir
,
2220 utf8_fullpath
= mono_utf8_from_external (fullpath
);
2221 if(utf8_fullpath
== NULL
) {
2222 /* Printing the arg text will cause glib to
2223 * whinge about "Invalid UTF-8", but at least
2224 * its relevant, and shows the problem text
2227 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath
);
2228 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
2235 utf8_fullpath
= mono_utf8_from_external (argv
[0]);
2236 if(utf8_fullpath
== NULL
) {
2237 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv
[0]);
2238 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
2243 main_args
[0] = utf8_fullpath
;
2245 for (i
= 1; i
< argc
; ++i
) {
2248 utf8_arg
=mono_utf8_from_external (argv
[i
]);
2249 if(utf8_arg
==NULL
) {
2250 /* Ditto the comment about Invalid UTF-8 here */
2251 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i
, argv
[i
]);
2252 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
2256 main_args
[i
] = utf8_arg
;
2260 if (mono_method_signature (method
)->param_count
) {
2261 args
= (MonoArray
*)mono_array_new (domain
, mono_defaults
.string_class
, argc
);
2262 for (i
= 0; i
< argc
; ++i
) {
2263 /* The encodings should all work, given that
2264 * we've checked all these args for the
2267 gchar
*str
= mono_utf8_from_external (argv
[i
]);
2268 MonoString
*arg
= mono_string_new (domain
, str
);
2269 mono_array_setref (args
, i
, arg
);
2273 args
= (MonoArray
*)mono_array_new (domain
, mono_defaults
.string_class
, 0);
2276 mono_assembly_set_main (method
->klass
->image
->assembly
);
2278 result
= mono_runtime_exec_main (method
, args
, exc
);
2279 fire_process_exit_event ();
2283 /* Used in mono_unhandled_exception */
2285 create_unhandled_exception_eventargs (MonoObject
*exc
)
2289 MonoMethod
*method
= NULL
;
2290 MonoBoolean is_terminating
= TRUE
;
2293 klass
= mono_class_from_name (mono_defaults
.corlib
, "System", "UnhandledExceptionEventArgs");
2296 mono_class_init (klass
);
2298 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
2299 method
= mono_class_get_method_from_name_flags (klass
, ".ctor", 2, METHOD_ATTRIBUTE_PUBLIC
);
2303 args
[1] = &is_terminating
;
2305 obj
= mono_object_new (mono_domain_get (), klass
);
2306 mono_runtime_invoke (method
, obj
, args
, NULL
);
2312 * mono_unhandled_exception:
2313 * @exc: exception thrown
2315 * This is a VM internal routine.
2317 * We call this function when we detect an unhandled exception
2318 * in the default domain.
2320 * It invokes the * UnhandledException event in AppDomain or prints
2321 * a warning to the console
2324 mono_unhandled_exception (MonoObject
*exc
)
2326 MonoDomain
*domain
= mono_domain_get ();
2327 MonoClassField
*field
;
2328 MonoObject
*delegate
;
2330 field
=mono_class_get_field_from_name(mono_defaults
.appdomain_class
,
2331 "UnhandledException");
2334 if (exc
->vtable
->klass
!= mono_defaults
.threadabortexception_class
) {
2335 delegate
= *(MonoObject
**)(((char *)domain
->domain
) + field
->offset
);
2337 /* set exitcode only in the main thread */
2338 if (mono_thread_current () == main_thread
)
2339 mono_environment_exitcode_set (1);
2340 if (domain
!= mono_get_root_domain () || !delegate
) {
2341 mono_print_unhandled_exception (exc
);
2343 MonoObject
*e
= NULL
;
2346 pa
[0] = domain
->domain
;
2347 pa
[1] = create_unhandled_exception_eventargs (exc
);
2348 mono_runtime_delegate_invoke (delegate
, pa
, &e
);
2351 gchar
*msg
= mono_string_to_utf8 (((MonoException
*) e
)->message
);
2352 g_warning ("exception inside UnhandledException handler: %s\n", msg
);
2360 * Launch a new thread to execute a function
2362 * main_func is called back from the thread with main_args as the
2363 * parameter. The callback function is expected to start Main()
2364 * eventually. This function then waits for all managed threads to
2366 * It is not necesseray anymore to execute managed code in a subthread,
2367 * so this function should not be used anymore by default: just
2368 * execute the code and then call mono_thread_manage ().
2371 mono_runtime_exec_managed_code (MonoDomain
*domain
,
2372 MonoMainThreadFunc main_func
,
2375 mono_thread_create (domain
, main_func
, main_args
);
2377 mono_thread_manage ();
2381 * Execute a standard Main() method (args doesn't contain the
2385 mono_runtime_exec_main (MonoMethod
*method
, MonoArray
*args
, MonoObject
**exc
)
2395 domain
= mono_object_domain (args
);
2396 if (!domain
->entry_assembly
) {
2398 MonoAssembly
*assembly
;
2400 assembly
= method
->klass
->image
->assembly
;
2401 domain
->entry_assembly
= assembly
;
2402 MONO_OBJECT_SETREF (domain
->setup
, application_base
, mono_string_new (domain
, assembly
->basedir
));
2404 str
= g_strconcat (assembly
->image
->name
, ".config", NULL
);
2405 MONO_OBJECT_SETREF (domain
->setup
, configuration_file
, mono_string_new (domain
, str
));
2409 /* FIXME: check signature of method */
2410 if (mono_method_signature (method
)->ret
->type
== MONO_TYPE_I4
) {
2412 res
= mono_runtime_invoke (method
, NULL
, pa
, exc
);
2414 rval
= *(guint32
*)((char *)res
+ sizeof (MonoObject
));
2418 mono_environment_exitcode_set (rval
);
2420 mono_runtime_invoke (method
, NULL
, pa
, exc
);
2424 /* If the return type of Main is void, only
2425 * set the exitcode if an exception was thrown
2426 * (we don't want to blow away an
2427 * explicitly-set exit code)
2430 mono_environment_exitcode_set (rval
);
2438 * mono_install_runtime_invoke:
2439 * @func: Function to install
2441 * This is a VM internal routine
2444 mono_install_runtime_invoke (MonoInvokeFunc func
)
2446 default_mono_runtime_invoke
= func
? func
: dummy_mono_runtime_invoke
;
2450 * mono_runtime_invoke_array:
2451 * @method: method to invoke
2452 * @obJ: object instance
2453 * @params: arguments to the method
2454 * @exc: exception information.
2456 * Invokes the method represented by @method on the object @obj.
2458 * obj is the 'this' pointer, it should be NULL for static
2459 * methods, a MonoObject* for object instances and a pointer to
2460 * the value type for value types.
2462 * The params array contains the arguments to the method with the
2463 * same convention: MonoObject* pointers for object instances and
2464 * pointers to the value type otherwise. The _invoke_array
2465 * variant takes a C# object[] as the params argument (MonoArray
2466 * *params): in this case the value types are boxed inside the
2467 * respective reference representation.
2469 * From unmanaged code you'll usually use the
2470 * mono_runtime_invoke() variant.
2472 * Note that this function doesn't handle virtual methods for
2473 * you, it will exec the exact method you pass: we still need to
2474 * expose a function to lookup the derived class implementation
2475 * of a virtual method (there are examples of this in the code,
2478 * You can pass NULL as the exc argument if you don't want to
2479 * catch exceptions, otherwise, *exc will be set to the exception
2480 * thrown, if any. if an exception is thrown, you can't use the
2481 * MonoObject* result from the function.
2483 * If the method returns a value type, it is boxed in an object
2487 mono_runtime_invoke_array (MonoMethod
*method
, void *obj
, MonoArray
*params
,
2490 MonoMethodSignature
*sig
= mono_method_signature (method
);
2491 gpointer
*pa
= NULL
;
2494 if (NULL
!= params
) {
2495 pa
= alloca (sizeof (gpointer
) * mono_array_length (params
));
2496 for (i
= 0; i
< mono_array_length (params
); i
++) {
2497 MonoType
*t
= sig
->params
[i
];
2503 case MONO_TYPE_BOOLEAN
:
2506 case MONO_TYPE_CHAR
:
2515 case MONO_TYPE_VALUETYPE
:
2516 if (t
->type
== MONO_TYPE_VALUETYPE
&& mono_class_is_nullable (mono_class_from_mono_type (sig
->params
[i
]))) {
2519 g_assert_not_reached ();
2520 /* The runtime invoke wrapper needs the original boxed vtype */
2521 pa
[i
] = (char *)(((gpointer
*)params
->vector
)[i
]);
2523 /* MS seems to create the objects if a null is passed in */
2524 if (!((gpointer
*)params
->vector
)[i
])
2525 ((gpointer
*)params
->vector
)[i
] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig
->params
[i
]));
2529 * We can't pass the unboxed vtype byref to the callee, since
2530 * that would mean the callee would be able to modify boxed
2531 * primitive types. So we (and MS) make a copy of the boxed
2532 * object, pass that to the callee, and replace the original
2533 * boxed object in the arg array with the copy.
2535 MonoObject
*orig
= mono_array_get (params
, MonoObject
*, i
);
2536 MonoObject
*copy
= mono_value_box (mono_domain_get (), orig
->vtable
->klass
, mono_object_unbox (orig
));
2537 mono_array_setref (params
, i
, copy
);
2540 pa
[i
] = (char *)(((gpointer
*)params
->vector
)[i
]) + sizeof (MonoObject
);
2543 case MONO_TYPE_STRING
:
2544 case MONO_TYPE_OBJECT
:
2545 case MONO_TYPE_CLASS
:
2546 case MONO_TYPE_ARRAY
:
2547 case MONO_TYPE_SZARRAY
:
2549 pa
[i
] = &(((gpointer
*)params
->vector
)[i
]);
2551 pa
[i
] = (char *)(((gpointer
*)params
->vector
)[i
]);
2553 case MONO_TYPE_GENERICINST
:
2554 t
= &t
->data
.generic_class
->container_class
->byval_arg
;
2557 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig
->params
[i
]->type
);
2562 if (!strcmp (method
->name
, ".ctor") && method
->klass
!= mono_defaults
.string_class
) {
2565 if (mono_class_is_nullable (method
->klass
)) {
2566 /* Need to create a boxed vtype instead */
2572 return mono_value_box (mono_domain_get (), method
->klass
->cast_class
, pa
[0]);
2576 obj
= mono_object_new (mono_domain_get (), method
->klass
);
2577 if (mono_object_class(obj
) == mono_defaults
.transparent_proxy_class
) {
2578 method
= mono_marshal_get_remoting_invoke (method
->slot
== -1 ? method
: method
->klass
->vtable
[method
->slot
]);
2580 if (method
->klass
->valuetype
)
2581 o
= mono_object_unbox (obj
);
2585 else if (method
->klass
->valuetype
)
2586 obj
= mono_value_box (mono_domain_get (), method
->klass
, obj
);
2588 mono_runtime_invoke (method
, o
, pa
, exc
);
2591 /* obj must be already unboxed if needed */
2592 return mono_runtime_invoke (method
, obj
, pa
, exc
);
2597 arith_overflow (void)
2599 mono_raise_exception (mono_get_exception_overflow ());
2603 * mono_object_allocate:
2604 * @size: number of bytes to allocate
2606 * This is a very simplistic routine until we have our GC-aware
2609 * Returns: an allocated object of size @size, or NULL on failure.
2611 static inline void *
2612 mono_object_allocate (size_t size
, MonoVTable
*vtable
)
2615 mono_stats
.new_object_count
++;
2616 ALLOC_OBJECT (o
, vtable
, size
);
2622 * mono_object_allocate_ptrfree:
2623 * @size: number of bytes to allocate
2625 * Note that the memory allocated is not zeroed.
2626 * Returns: an allocated object of size @size, or NULL on failure.
2628 static inline void *
2629 mono_object_allocate_ptrfree (size_t size
, MonoVTable
*vtable
)
2632 mono_stats
.new_object_count
++;
2633 ALLOC_PTRFREE (o
, vtable
, size
);
2637 static inline void *
2638 mono_object_allocate_spec (size_t size
, MonoVTable
*vtable
)
2641 ALLOC_TYPED (o
, size
, vtable
);
2642 mono_stats
.new_object_count
++;
2649 * @klass: the class of the object that we want to create
2651 * Returns: a newly created object whose definition is
2652 * looked up using @klass. This will not invoke any constructors,
2653 * so the consumer of this routine has to invoke any constructors on
2654 * its own to initialize the object.
2657 mono_object_new (MonoDomain
*domain
, MonoClass
*klass
)
2659 MONO_ARCH_SAVE_REGS
;
2660 return mono_object_new_specific (mono_class_vtable (domain
, klass
));
2664 * mono_object_new_specific:
2665 * @vtable: the vtable of the object that we want to create
2667 * Returns: A newly created object with class and domain specified
2671 mono_object_new_specific (MonoVTable
*vtable
)
2675 MONO_ARCH_SAVE_REGS
;
2677 /* check for is_com_object for COM Interop */
2678 if (vtable
->remote
|| vtable
->klass
->is_com_object
)
2681 MonoMethod
*im
= vtable
->domain
->create_proxy_for_type_method
;
2684 MonoClass
*klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Runtime.Remoting.Activation", "ActivationServices");
2687 mono_class_init (klass
);
2689 im
= mono_class_get_method_from_name (klass
, "CreateProxyForType", 1);
2691 vtable
->domain
->create_proxy_for_type_method
= im
;
2694 pa
[0] = mono_type_get_object (mono_domain_get (), &vtable
->klass
->byval_arg
);
2696 o
= mono_runtime_invoke (im
, NULL
, pa
, NULL
);
2697 if (o
!= NULL
) return o
;
2700 return mono_object_new_alloc_specific (vtable
);
2704 mono_object_new_alloc_specific (MonoVTable
*vtable
)
2708 if (!vtable
->klass
->has_references
) {
2709 o
= mono_object_new_ptrfree (vtable
);
2710 } else if (vtable
->gc_descr
!= GC_NO_DESCRIPTOR
) {
2711 o
= mono_object_allocate_spec (vtable
->klass
->instance_size
, vtable
);
2713 /* printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2714 o
= mono_object_allocate (vtable
->klass
->instance_size
, vtable
);
2716 if (vtable
->klass
->has_finalize
)
2717 mono_object_register_finalizer (o
);
2719 mono_profiler_allocation (o
, vtable
->klass
);
2724 mono_object_new_fast (MonoVTable
*vtable
)
2727 ALLOC_TYPED (o
, vtable
->klass
->instance_size
, vtable
);
2732 mono_object_new_ptrfree (MonoVTable
*vtable
)
2735 ALLOC_PTRFREE (obj
, vtable
, vtable
->klass
->instance_size
);
2736 #if NEED_TO_ZERO_PTRFREE
2737 /* an inline memset is much faster for the common vcase of small objects
2738 * note we assume the allocated size is a multiple of sizeof (void*).
2740 if (vtable
->klass
->instance_size
< 128) {
2742 end
= (gpointer
*)((char*)obj
+ vtable
->klass
->instance_size
);
2743 p
= (gpointer
*)((char*)obj
+ sizeof (MonoObject
));
2749 memset ((char*)obj
+ sizeof (MonoObject
), 0, vtable
->klass
->instance_size
- sizeof (MonoObject
));
2756 mono_object_new_ptrfree_box (MonoVTable
*vtable
)
2759 ALLOC_PTRFREE (obj
, vtable
, vtable
->klass
->instance_size
);
2760 /* the object will be boxed right away, no need to memzero it */
2765 * mono_class_get_allocation_ftn:
2767 * @for_box: the object will be used for boxing
2768 * @pass_size_in_words:
2770 * Return the allocation function appropriate for the given class.
2774 mono_class_get_allocation_ftn (MonoVTable
*vtable
, gboolean for_box
, gboolean
*pass_size_in_words
)
2776 *pass_size_in_words
= FALSE
;
2778 if (vtable
->klass
->has_finalize
|| vtable
->klass
->marshalbyref
|| (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS
))
2779 return mono_object_new_specific
;
2781 if (!vtable
->klass
->has_references
) {
2782 //g_print ("ptrfree for %s.%s\n", vtable->klass->name_space, vtable->klass->name);
2784 return mono_object_new_ptrfree_box
;
2785 return mono_object_new_ptrfree
;
2788 if (vtable
->gc_descr
!= GC_NO_DESCRIPTOR
) {
2790 return mono_object_new_fast
;
2793 * FIXME: This is actually slower than mono_object_new_fast, because
2794 * of the overhead of parameter passing.
2797 *pass_size_in_words = TRUE;
2798 #ifdef GC_REDIRECT_TO_LOCAL
2799 return GC_local_gcj_fast_malloc;
2801 return GC_gcj_fast_malloc;
2806 return mono_object_new_specific
;
2810 * mono_object_new_from_token:
2811 * @image: Context where the type_token is hosted
2812 * @token: a token of the type that we want to create
2814 * Returns: A newly created object whose definition is
2815 * looked up using @token in the @image image
2818 mono_object_new_from_token (MonoDomain
*domain
, MonoImage
*image
, guint32 token
)
2822 class = mono_class_get (image
, token
);
2824 return mono_object_new (domain
, class);
2829 * mono_object_clone:
2830 * @obj: the object to clone
2832 * Returns: A newly created object who is a shallow copy of @obj
2835 mono_object_clone (MonoObject
*obj
)
2840 size
= obj
->vtable
->klass
->instance_size
;
2841 o
= mono_object_allocate (size
, obj
->vtable
);
2842 /* do not copy the sync state */
2843 memcpy ((char*)o
+ sizeof (MonoObject
), (char*)obj
+ sizeof (MonoObject
), size
- sizeof (MonoObject
));
2846 if (obj
->vtable
->klass
->has_references
)
2847 mono_gc_wbarrier_object (o
);
2849 mono_profiler_allocation (o
, obj
->vtable
->klass
);
2851 if (obj
->vtable
->klass
->has_finalize
)
2852 mono_object_register_finalizer (o
);
2857 * mono_array_full_copy:
2858 * @src: source array to copy
2859 * @dest: destination array
2861 * Copies the content of one array to another with exactly the same type and size.
2864 mono_array_full_copy (MonoArray
*src
, MonoArray
*dest
)
2867 MonoClass
*klass
= src
->obj
.vtable
->klass
;
2869 MONO_ARCH_SAVE_REGS
;
2871 g_assert (klass
== dest
->obj
.vtable
->klass
);
2873 size
= mono_array_length (src
);
2874 g_assert (size
== mono_array_length (dest
));
2875 size
*= mono_array_element_size (klass
);
2877 if (klass
->valuetype
) {
2878 if (klass
->has_references
)
2879 mono_value_copy_array (dest
, 0, src
, mono_array_length (src
));
2881 memcpy (&dest
->vector
, &src
->vector
, size
);
2883 mono_array_memcpy_refs (dest
, 0, src
, 0, mono_array_length (src
));
2886 memcpy (&dest
->vector
, &src
->vector
, size
);
2891 * mono_array_clone_in_domain:
2892 * @domain: the domain in which the array will be cloned into
2893 * @array: the array to clone
2895 * This routine returns a copy of the array that is hosted on the
2896 * specified MonoDomain.
2899 mono_array_clone_in_domain (MonoDomain
*domain
, MonoArray
*array
)
2904 MonoClass
*klass
= array
->obj
.vtable
->klass
;
2906 MONO_ARCH_SAVE_REGS
;
2908 if (array
->bounds
== NULL
) {
2909 size
= mono_array_length (array
);
2910 o
= mono_array_new_full (domain
, klass
, &size
, NULL
);
2912 size
*= mono_array_element_size (klass
);
2914 if (klass
->valuetype
) {
2915 if (klass
->has_references
)
2916 mono_value_copy_array (o
, 0, array
, mono_array_length (array
));
2918 memcpy (&o
->vector
, &array
->vector
, size
);
2920 mono_array_memcpy_refs (o
, 0, array
, 0, mono_array_length (array
));
2923 memcpy (&o
->vector
, &array
->vector
, size
);
2928 sizes
= alloca (klass
->rank
* sizeof(guint32
) * 2);
2929 size
= mono_array_element_size (klass
);
2930 for (i
= 0; i
< klass
->rank
; ++i
) {
2931 sizes
[i
] = array
->bounds
[i
].length
;
2932 size
*= array
->bounds
[i
].length
;
2933 sizes
[i
+ klass
->rank
] = array
->bounds
[i
].lower_bound
;
2935 o
= mono_array_new_full (domain
, klass
, sizes
, sizes
+ klass
->rank
);
2937 if (klass
->valuetype
) {
2938 if (klass
->has_references
)
2939 mono_value_copy_array (o
, 0, array
, mono_array_length (array
));
2941 memcpy (&o
->vector
, &array
->vector
, size
);
2943 mono_array_memcpy_refs (o
, 0, array
, 0, mono_array_length (array
));
2946 memcpy (&o
->vector
, &array
->vector
, size
);
2954 * @array: the array to clone
2956 * Returns: A newly created array who is a shallow copy of @array
2959 mono_array_clone (MonoArray
*array
)
2961 return mono_array_clone_in_domain (((MonoObject
*)array
)->vtable
->domain
, array
);
2964 /* helper macros to check for overflow when calculating the size of arrays */
2965 #define MYGUINT32_MAX 4294967295U
2966 #define CHECK_ADD_OVERFLOW_UN(a,b) \
2967 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
2968 #define CHECK_MUL_OVERFLOW_UN(a,b) \
2969 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
2970 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
2973 * mono_array_new_full:
2974 * @domain: domain where the object is created
2975 * @array_class: array class
2976 * @lengths: lengths for each dimension in the array
2977 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
2979 * This routine creates a new array objects with the given dimensions,
2980 * lower bounds and type.
2983 mono_array_new_full (MonoDomain
*domain
, MonoClass
*array_class
, guint32
*lengths
, guint32
*lower_bounds
)
2985 guint32 byte_len
, len
, bounds_size
;
2991 if (!array_class
->inited
)
2992 mono_class_init (array_class
);
2994 byte_len
= mono_array_element_size (array_class
);
2997 /* A single dimensional array with a 0 lower bound is the same as an szarray */
2998 if (array_class
->rank
== 1 && ((array_class
->byval_arg
.type
== MONO_TYPE_SZARRAY
) || (lower_bounds
&& lower_bounds
[0] == 0))) {
3004 bounds_size
= sizeof (MonoArrayBounds
) * array_class
->rank
;
3006 for (i
= 0; i
< array_class
->rank
; ++i
) {
3007 if ((int) lengths
[i
] < 0)
3009 if (CHECK_MUL_OVERFLOW_UN (len
, lengths
[i
]))
3010 mono_gc_out_of_memory (MYGUINT32_MAX
);
3015 if (CHECK_MUL_OVERFLOW_UN (byte_len
, len
))
3016 mono_gc_out_of_memory (MYGUINT32_MAX
);
3018 if (CHECK_ADD_OVERFLOW_UN (byte_len
, sizeof (MonoArray
)))
3019 mono_gc_out_of_memory (MYGUINT32_MAX
);
3020 byte_len
+= sizeof (MonoArray
);
3023 if (CHECK_ADD_OVERFLOW_UN (byte_len
, 3))
3024 mono_gc_out_of_memory (MYGUINT32_MAX
);
3025 byte_len
= (byte_len
+ 3) & ~3;
3026 if (CHECK_ADD_OVERFLOW_UN (byte_len
, bounds_size
))
3027 mono_gc_out_of_memory (MYGUINT32_MAX
);
3028 byte_len
+= bounds_size
;
3031 * Following three lines almost taken from mono_object_new ():
3032 * they need to be kept in sync.
3034 vtable
= mono_class_vtable (domain
, array_class
);
3035 if (!array_class
->has_references
) {
3036 o
= mono_object_allocate_ptrfree (byte_len
, vtable
);
3037 #if NEED_TO_ZERO_PTRFREE
3038 memset ((char*)o
+ sizeof (MonoObject
), 0, byte_len
- sizeof (MonoObject
));
3040 } else if (vtable
->gc_descr
!= GC_NO_DESCRIPTOR
) {
3041 o
= mono_object_allocate_spec (byte_len
, vtable
);
3043 o
= mono_object_allocate (byte_len
, vtable
);
3046 array
= (MonoArray
*)o
;
3047 array
->max_length
= len
;
3050 MonoArrayBounds
*bounds
= (MonoArrayBounds
*)((char*)array
+ byte_len
- bounds_size
);
3051 array
->bounds
= bounds
;
3052 for (i
= 0; i
< array_class
->rank
; ++i
) {
3053 bounds
[i
].length
= lengths
[i
];
3055 bounds
[i
].lower_bound
= lower_bounds
[i
];
3059 mono_profiler_allocation (o
, array_class
);
3066 * @domain: domain where the object is created
3067 * @eclass: element class
3068 * @n: number of array elements
3070 * This routine creates a new szarray with @n elements of type @eclass.
3073 mono_array_new (MonoDomain
*domain
, MonoClass
*eclass
, guint32 n
)
3077 MONO_ARCH_SAVE_REGS
;
3079 ac
= mono_array_class_get (eclass
, 1);
3080 g_assert (ac
!= NULL
);
3082 return mono_array_new_specific (mono_class_vtable (domain
, ac
), n
);
3086 * mono_array_new_specific:
3087 * @vtable: a vtable in the appropriate domain for an initialized class
3088 * @n: number of array elements
3090 * This routine is a fast alternative to mono_array_new() for code which
3091 * can be sure about the domain it operates in.
3094 mono_array_new_specific (MonoVTable
*vtable
, guint32 n
)
3098 guint32 byte_len
, elem_size
;
3100 MONO_ARCH_SAVE_REGS
;
3105 elem_size
= mono_array_element_size (vtable
->klass
);
3106 if (CHECK_MUL_OVERFLOW_UN (n
, elem_size
))
3107 mono_gc_out_of_memory (MYGUINT32_MAX
);
3108 byte_len
= n
* elem_size
;
3109 if (CHECK_ADD_OVERFLOW_UN (byte_len
, sizeof (MonoArray
)))
3110 mono_gc_out_of_memory (MYGUINT32_MAX
);
3111 byte_len
+= sizeof (MonoArray
);
3112 if (!vtable
->klass
->has_references
) {
3113 o
= mono_object_allocate_ptrfree (byte_len
, vtable
);
3114 #if NEED_TO_ZERO_PTRFREE
3115 memset ((char*)o
+ sizeof (MonoObject
), 0, byte_len
- sizeof (MonoObject
));
3117 } else if (vtable
->gc_descr
!= GC_NO_DESCRIPTOR
) {
3118 o
= mono_object_allocate_spec (byte_len
, vtable
);
3120 /* printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
3121 o
= mono_object_allocate (byte_len
, vtable
);
3124 ao
= (MonoArray
*)o
;
3127 mono_profiler_allocation (o
, vtable
->klass
);
3133 * mono_string_new_utf16:
3134 * @text: a pointer to an utf16 string
3135 * @len: the length of the string
3137 * Returns: A newly created string object which contains @text.
3140 mono_string_new_utf16 (MonoDomain
*domain
, const guint16
*text
, gint32 len
)
3144 s
= mono_string_new_size (domain
, len
);
3145 g_assert (s
!= NULL
);
3147 memcpy (mono_string_chars (s
), text
, len
* 2);
3153 * mono_string_new_size:
3154 * @text: a pointer to an utf16 string
3155 * @len: the length of the string
3157 * Returns: A newly created string object of @len
3160 mono_string_new_size (MonoDomain
*domain
, gint32 len
)
3164 size_t size
= (sizeof (MonoString
) + ((len
+ 1) * 2));
3166 /* overflow ? can't fit it, can't allocate it! */
3168 mono_gc_out_of_memory (-1);
3170 vtable
= mono_class_vtable (domain
, mono_defaults
.string_class
);
3172 s
= mono_object_allocate_ptrfree (size
, vtable
);
3175 #if NEED_TO_ZERO_PTRFREE
3178 mono_profiler_allocation ((MonoObject
*)s
, mono_defaults
.string_class
);
3184 * mono_string_new_len:
3185 * @text: a pointer to an utf8 string
3186 * @length: number of bytes in @text to consider
3188 * Returns: A newly created string object which contains @text.
3191 mono_string_new_len (MonoDomain
*domain
, const char *text
, guint length
)
3193 GError
*error
= NULL
;
3194 MonoString
*o
= NULL
;
3196 glong items_written
;
3198 ut
= g_utf8_to_utf16 (text
, length
, NULL
, &items_written
, &error
);
3201 o
= mono_string_new_utf16 (domain
, ut
, items_written
);
3203 g_error_free (error
);
3212 * @text: a pointer to an utf8 string
3214 * Returns: A newly created string object which contains @text.
3217 mono_string_new (MonoDomain
*domain
, const char *text
)
3219 GError
*error
= NULL
;
3220 MonoString
*o
= NULL
;
3222 glong items_written
;
3227 ut
= g_utf8_to_utf16 (text
, l
, NULL
, &items_written
, &error
);
3230 o
= mono_string_new_utf16 (domain
, ut
, items_written
);
3232 g_error_free (error
);
3240 * mono_string_new_wrapper:
3241 * @text: pointer to utf8 characters.
3243 * Helper function to create a string object from @text in the current domain.
3246 mono_string_new_wrapper (const char *text
)
3248 MonoDomain
*domain
= mono_domain_get ();
3250 MONO_ARCH_SAVE_REGS
;
3253 return mono_string_new (domain
, text
);
3260 * @class: the class of the value
3261 * @value: a pointer to the unboxed data
3263 * Returns: A newly created object which contains @value.
3266 mono_value_box (MonoDomain
*domain
, MonoClass
*class, gpointer value
)
3272 g_assert (class->valuetype
);
3274 vtable
= mono_class_vtable (domain
, class);
3275 size
= mono_class_instance_size (class);
3276 res
= mono_object_allocate (size
, vtable
);
3277 mono_profiler_allocation (res
, class);
3279 size
= size
- sizeof (MonoObject
);
3282 mono_gc_wbarrier_value_copy ((char *)res
+ sizeof (MonoObject
), value
, 1, class);
3285 #if NO_UNALIGNED_ACCESS
3286 memcpy ((char *)res
+ sizeof (MonoObject
), value
, size
);
3290 *((guint8
*) res
+ sizeof (MonoObject
)) = *(guint8
*) value
;
3293 *(guint16
*)((guint8
*) res
+ sizeof (MonoObject
)) = *(guint16
*) value
;
3296 *(guint32
*)((guint8
*) res
+ sizeof (MonoObject
)) = *(guint32
*) value
;
3299 *(guint64
*)((guint8
*) res
+ sizeof (MonoObject
)) = *(guint64
*) value
;
3302 memcpy ((char *)res
+ sizeof (MonoObject
), value
, size
);
3305 if (class->has_finalize
)
3306 mono_object_register_finalizer (res
);
3312 * @dest: destination pointer
3313 * @src: source pointer
3314 * @klass: a valuetype class
3316 * Copy a valuetype from @src to @dest. This function must be used
3317 * when @klass contains references fields.
3320 mono_value_copy (gpointer dest
, gpointer src
, MonoClass
*klass
)
3322 int size
= mono_class_value_size (klass
, NULL
);
3323 mono_gc_wbarrier_value_copy (dest
, src
, 1, klass
);
3324 memcpy (dest
, src
, size
);
3328 * mono_value_copy_array:
3329 * @dest: destination array
3330 * @dest_idx: index in the @dest array
3331 * @src: source pointer
3332 * @count: number of items
3334 * Copy @count valuetype items from @src to @dest. This function must be used
3335 * when @klass contains references fields.
3336 * Overlap is handled.
3339 mono_value_copy_array (MonoArray
*dest
, int dest_idx
, gpointer src
, int count
)
3341 int size
= mono_array_element_size (dest
->obj
.vtable
->klass
);
3342 char *d
= mono_array_addr_with_size (dest
, size
, dest_idx
);
3343 mono_gc_wbarrier_value_copy (d
, src
, count
, mono_object_class (dest
)->element_class
);
3344 memmove (d
, src
, size
* count
);
3348 * mono_object_get_domain:
3349 * @obj: object to query
3351 * Returns: the MonoDomain where the object is hosted
3354 mono_object_get_domain (MonoObject
*obj
)
3356 return mono_object_domain (obj
);
3360 * mono_object_get_class:
3361 * @obj: object to query
3363 * Returns: the MonOClass of the object.
3366 mono_object_get_class (MonoObject
*obj
)
3368 return mono_object_class (obj
);
3371 * mono_object_get_size:
3372 * @o: object to query
3374 * Returns: the size, in bytes, of @o
3377 mono_object_get_size (MonoObject
* o
)
3379 MonoClass
* klass
= mono_object_class (o
);
3380 if (klass
== mono_defaults
.string_class
) {
3381 return sizeof (MonoString
) + 2 * mono_string_length ((MonoString
*) o
) + 2;
3382 } else if (o
->vtable
->rank
) {
3383 MonoArray
*array
= (MonoArray
*)o
;
3384 size_t size
= sizeof (MonoArray
) + mono_array_element_size (klass
) * mono_array_length (array
);
3385 if (array
->bounds
) {
3388 size
+= sizeof (MonoArrayBounds
) * o
->vtable
->rank
;
3392 return mono_class_instance_size (klass
);
3397 * mono_object_unbox:
3398 * @obj: object to unbox
3400 * Returns: a pointer to the start of the valuetype boxed in this
3403 * This method will assert if the object passed is not a valuetype.
3406 mono_object_unbox (MonoObject
*obj
)
3408 /* add assert for valuetypes? */
3409 g_assert (obj
->vtable
->klass
->valuetype
);
3410 return ((char*)obj
) + sizeof (MonoObject
);
3414 * mono_object_isinst:
3416 * @klass: a pointer to a class
3418 * Returns: @obj if @obj is derived from @klass
3421 mono_object_isinst (MonoObject
*obj
, MonoClass
*klass
)
3424 mono_class_init (klass
);
3426 if (klass
->marshalbyref
|| klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
)
3427 return mono_object_isinst_mbyref (obj
, klass
);
3432 return mono_class_is_assignable_from (klass
, obj
->vtable
->klass
) ? obj
: NULL
;
3436 mono_object_isinst_mbyref (MonoObject
*obj
, MonoClass
*klass
)
3445 if (klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
3446 if (klass
->interface_id
<= vt
->max_interface_id
) {
3447 /* the interface_offsets array is stored before the vtable */
3448 gpointer
*interface_offsets
= (gpointer
*)vt
;
3449 if (interface_offsets
[- (klass
->interface_id
+ 1)] != NULL
)
3453 MonoClass
*oklass
= vt
->klass
;
3454 if ((oklass
== mono_defaults
.transparent_proxy_class
))
3455 oklass
= ((MonoTransparentProxy
*)obj
)->remote_class
->proxy_class
;
3457 if ((oklass
->idepth
>= klass
->idepth
) && (oklass
->supertypes
[klass
->idepth
- 1] == klass
))
3461 if (vt
->klass
== mono_defaults
.transparent_proxy_class
&& ((MonoTransparentProxy
*)obj
)->custom_type_info
)
3463 MonoDomain
*domain
= mono_domain_get ();
3465 MonoObject
*rp
= (MonoObject
*)((MonoTransparentProxy
*)obj
)->rp
;
3466 MonoClass
*rpklass
= mono_defaults
.iremotingtypeinfo_class
;
3467 MonoMethod
*im
= NULL
;
3470 im
= mono_class_get_method_from_name (rpklass
, "CanCastTo", -1);
3471 im
= mono_object_get_virtual_method (rp
, im
);
3474 pa
[0] = mono_type_get_object (domain
, &klass
->byval_arg
);
3477 res
= mono_runtime_invoke (im
, rp
, pa
, NULL
);
3479 if (*(MonoBoolean
*) mono_object_unbox(res
)) {
3480 /* Update the vtable of the remote type, so it can safely cast to this new type */
3481 mono_upgrade_remote_class (domain
, obj
, klass
);
3490 * mono_object_castclass_mbyref:
3492 * @klass: a pointer to a class
3494 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
3497 mono_object_castclass_mbyref (MonoObject
*obj
, MonoClass
*klass
)
3499 if (!obj
) return NULL
;
3500 if (mono_object_isinst_mbyref (obj
, klass
)) return obj
;
3502 mono_raise_exception (mono_exception_from_name (mono_defaults
.corlib
,
3504 "InvalidCastException"));
3509 MonoDomain
*orig_domain
;
3515 str_lookup (MonoDomain
*domain
, gpointer user_data
)
3517 LDStrInfo
*info
= user_data
;
3518 if (info
->res
|| domain
== info
->orig_domain
)
3520 info
->res
= mono_g_hash_table_lookup (domain
->ldstr_table
, info
->ins
);
3526 mono_string_get_pinned (MonoString
*str
)
3530 size
= sizeof (MonoString
) + 2 * (mono_string_length (str
) + 1);
3531 news
= mono_gc_alloc_pinned_obj (((MonoObject
*)str
)->vtable
, size
);
3532 memcpy (mono_string_chars (news
), mono_string_chars (str
), mono_string_length (str
) * 2);
3533 news
->length
= mono_string_length (str
);
3538 #define mono_string_get_pinned(str) (str)
3542 mono_string_is_interned_lookup (MonoString
*str
, int insert
)
3544 MonoGHashTable
*ldstr_table
;
3548 domain
= ((MonoObject
*)str
)->vtable
->domain
;
3549 ldstr_table
= domain
->ldstr_table
;
3551 if ((res
= mono_g_hash_table_lookup (ldstr_table
, str
))) {
3556 str
= mono_string_get_pinned (str
);
3557 mono_g_hash_table_insert (ldstr_table
, str
, str
);
3561 LDStrInfo ldstr_info
;
3562 ldstr_info
.orig_domain
= domain
;
3563 ldstr_info
.ins
= str
;
3564 ldstr_info
.res
= NULL
;
3566 mono_domain_foreach (str_lookup
, &ldstr_info
);
3567 if (ldstr_info
.res
) {
3569 * the string was already interned in some other domain:
3570 * intern it in the current one as well.
3572 mono_g_hash_table_insert (ldstr_table
, str
, str
);
3582 * mono_string_is_interned:
3583 * @o: String to probe
3585 * Returns whether the string has been interned.
3588 mono_string_is_interned (MonoString
*o
)
3590 return mono_string_is_interned_lookup (o
, FALSE
);
3594 * mono_string_intern:
3595 * @o: String to intern
3597 * Interns the string passed.
3598 * Returns: The interned string.
3601 mono_string_intern (MonoString
*str
)
3603 return mono_string_is_interned_lookup (str
, TRUE
);
3608 * @domain: the domain where the string will be used.
3609 * @image: a metadata context
3610 * @idx: index into the user string table.
3612 * Implementation for the ldstr opcode.
3613 * Returns: a loaded string from the @image/@idx combination.
3616 mono_ldstr (MonoDomain
*domain
, MonoImage
*image
, guint32 idx
)
3618 MONO_ARCH_SAVE_REGS
;
3621 return mono_lookup_dynamic_token (image
, MONO_TOKEN_STRING
| idx
);
3623 return mono_ldstr_metdata_sig (domain
, mono_metadata_user_string (image
, idx
));
3627 * mono_ldstr_metdata_sig
3628 * @domain: the domain for the string
3629 * @sig: the signature of a metadata string
3631 * Returns: a MonoString for a string stored in the metadata
3634 mono_ldstr_metdata_sig (MonoDomain
*domain
, const char* sig
)
3636 const char *str
= sig
;
3637 MonoString
*o
, *interned
;
3640 len2
= mono_metadata_decode_blob_size (str
, &str
);
3643 o
= mono_string_new_utf16 (domain
, (guint16
*)str
, len2
);
3644 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3647 guint16
*p2
= (guint16
*)mono_string_chars (o
);
3648 for (i
= 0; i
< len2
; ++i
) {
3649 *p2
= GUINT16_FROM_LE (*p2
);
3655 if ((interned
= mono_g_hash_table_lookup (domain
->ldstr_table
, o
))) {
3657 /* o will get garbage collected */
3661 o
= mono_string_get_pinned (o
);
3662 mono_g_hash_table_insert (domain
->ldstr_table
, o
, o
);
3669 * mono_string_to_utf8:
3670 * @s: a System.String
3672 * Return the UTF8 representation for @s.
3673 * the resulting buffer nedds to be freed with g_free().
3676 mono_string_to_utf8 (MonoString
*s
)
3679 GError
*error
= NULL
;
3685 return g_strdup ("");
3687 as
= g_utf16_to_utf8 (mono_string_chars (s
), s
->length
, NULL
, NULL
, &error
);
3689 MonoException
*exc
= mono_get_exception_argument ("string", error
->message
);
3690 g_error_free (error
);
3691 mono_raise_exception(exc
);
3698 * mono_string_to_utf16:
3701 * Return an null-terminated array of the utf-16 chars
3702 * contained in @s. The result must be freed with g_free().
3703 * This is a temporary helper until our string implementation
3704 * is reworked to always include the null terminating char.
3707 mono_string_to_utf16 (MonoString
*s
)
3714 as
= g_malloc ((s
->length
* 2) + 2);
3715 as
[(s
->length
* 2)] = '\0';
3716 as
[(s
->length
* 2) + 1] = '\0';
3719 return (gunichar2
*)(as
);
3722 memcpy (as
, mono_string_chars(s
), s
->length
* 2);
3723 return (gunichar2
*)(as
);
3727 * mono_string_from_utf16:
3728 * @data: the UTF16 string (LPWSTR) to convert
3730 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString.
3732 * Returns: a MonoString.
3735 mono_string_from_utf16 (gunichar2
*data
)
3737 MonoDomain
*domain
= mono_domain_get ();
3743 while (data
[len
]) len
++;
3745 return mono_string_new_utf16 (domain
, data
, len
);
3749 * mono_string_to_utf8_mp:
3750 * @s: a System.String
3752 * Same as mono_string_to_utf8, but allocate the string from a mempool.
3755 mono_string_to_utf8_mp (MonoMemPool
*mp
, MonoString
*s
)
3757 char *r
= mono_string_to_utf8 (s
);
3764 len
= strlen (r
) + 1;
3765 mp_s
= mono_mempool_alloc (mp
, len
);
3766 memcpy (mp_s
, r
, len
);
3774 default_ex_handler (MonoException
*ex
)
3776 MonoObject
*o
= (MonoObject
*)ex
;
3777 g_error ("Exception %s.%s raised in C code", o
->vtable
->klass
->name_space
, o
->vtable
->klass
->name
);
3781 static MonoExceptionFunc ex_handler
= default_ex_handler
;
3784 * mono_install_handler:
3785 * @func: exception handler
3787 * This is an internal JIT routine used to install the handler for exceptions
3791 mono_install_handler (MonoExceptionFunc func
)
3793 ex_handler
= func
? func
: default_ex_handler
;
3797 * mono_raise_exception:
3798 * @ex: exception object
3800 * Signal the runtime that the exception @ex has been raised in unmanaged code.
3803 mono_raise_exception (MonoException
*ex
)
3806 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
3807 * that will cause gcc to omit the function epilog, causing problems when
3808 * the JIT tries to walk the stack, since the return address on the stack
3809 * will point into the next function in the executable, not this one.
3812 if (((MonoObject
*)ex
)->vtable
->klass
== mono_defaults
.threadabortexception_class
)
3813 MONO_OBJECT_SETREF (mono_thread_current (), abort_exc
, ex
);
3819 * mono_wait_handle_new:
3820 * @domain: Domain where the object will be created
3821 * @handle: Handle for the wait handle
3823 * Returns: A new MonoWaitHandle created in the given domain for the given handle
3826 mono_wait_handle_new (MonoDomain
*domain
, HANDLE handle
)
3828 MonoWaitHandle
*res
;
3829 gpointer params
[1];
3830 static MonoMethod
*handle_set
;
3832 res
= (MonoWaitHandle
*)mono_object_new (domain
, mono_defaults
.waithandle_class
);
3834 /* Even though this method is virtual, it's safe to invoke directly, since the object type matches. */
3836 handle_set
= mono_class_get_property_from_name (mono_defaults
.waithandle_class
, "Handle")->set
;
3838 params
[0] = &handle
;
3839 mono_runtime_invoke (handle_set
, res
, params
, NULL
);
3845 mono_wait_handle_get_handle (MonoWaitHandle
*handle
)
3847 static MonoClassField
*f_os_handle
;
3848 static MonoClassField
*f_safe_handle
;
3850 if (!f_os_handle
&& !f_safe_handle
) {
3851 f_os_handle
= mono_class_get_field_from_name (mono_defaults
.waithandle_class
, "os_handle");
3852 f_safe_handle
= mono_class_get_field_from_name (mono_defaults
.waithandle_class
, "safe_wait_handle");
3857 mono_field_get_value ((MonoObject
*)handle
, f_os_handle
, &retval
);
3861 mono_field_get_value ((MonoObject
*)handle
, f_safe_handle
, &sh
);
3867 * mono_async_result_new:
3868 * @domain:domain where the object will be created.
3869 * @handle: wait handle.
3870 * @state: state to pass to AsyncResult
3871 * @data: C closure data.
3873 * Creates a new MonoAsyncResult (AsyncResult C# class) in the given domain.
3874 * If the handle is not null, the handle is initialized to a MonOWaitHandle.
3878 mono_async_result_new (MonoDomain
*domain
, HANDLE handle
, MonoObject
*state
, gpointer data
, MonoObject
*object_data
)
3880 MonoAsyncResult
*res
= (MonoAsyncResult
*)mono_object_new (domain
, mono_defaults
.asyncresult_class
);
3881 MonoMethod
*method
= mono_get_context_capture_method ();
3883 /* we must capture the execution context from the original thread */
3885 MONO_OBJECT_SETREF (res
, execution_context
, mono_runtime_invoke (method
, NULL
, NULL
, NULL
));
3886 /* note: result may be null if the flow is suppressed */
3890 MONO_OBJECT_SETREF (res
, object_data
, object_data
);
3891 MONO_OBJECT_SETREF (res
, async_state
, state
);
3893 MONO_OBJECT_SETREF (res
, handle
, (MonoObject
*) mono_wait_handle_new (domain
, handle
));
3895 res
->sync_completed
= FALSE
;
3896 res
->completed
= FALSE
;
3902 mono_message_init (MonoDomain
*domain
,
3903 MonoMethodMessage
*this,
3904 MonoReflectionMethod
*method
,
3905 MonoArray
*out_args
)
3907 MonoMethodSignature
*sig
= mono_method_signature (method
->method
);
3913 MONO_OBJECT_SETREF (this, method
, method
);
3915 MONO_OBJECT_SETREF (this, args
, mono_array_new (domain
, mono_defaults
.object_class
, sig
->param_count
));
3916 MONO_OBJECT_SETREF (this, arg_types
, mono_array_new (domain
, mono_defaults
.byte_class
, sig
->param_count
));
3917 this->async_result
= NULL
;
3918 this->call_type
= CallType_Sync
;
3920 names
= g_new (char *, sig
->param_count
);
3921 mono_method_get_param_names (method
->method
, (const char **) names
);
3922 MONO_OBJECT_SETREF (this, names
, mono_array_new (domain
, mono_defaults
.string_class
, sig
->param_count
));
3924 for (i
= 0; i
< sig
->param_count
; i
++) {
3925 name
= mono_string_new (domain
, names
[i
]);
3926 mono_array_setref (this->names
, i
, name
);
3930 for (i
= 0, j
= 0; i
< sig
->param_count
; i
++) {
3932 if (sig
->params
[i
]->byref
) {
3934 MonoObject
* arg
= mono_array_get (out_args
, gpointer
, j
);
3935 mono_array_setref (this->args
, i
, arg
);
3939 if (!(sig
->params
[i
]->attrs
& PARAM_ATTRIBUTE_OUT
))
3943 if (sig
->params
[i
]->attrs
& PARAM_ATTRIBUTE_OUT
)
3946 mono_array_set (this->arg_types
, guint8
, i
, arg_type
);
3951 * mono_remoting_invoke:
3952 * @real_proxy: pointer to a RealProxy object
3953 * @msg: The MonoMethodMessage to execute
3954 * @exc: used to store exceptions
3955 * @out_args: used to store output arguments
3957 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
3958 * IMessage interface and it is not trivial to extract results from there. So
3959 * we call an helper method PrivateInvoke instead of calling
3960 * RealProxy::Invoke() directly.
3962 * Returns: the result object.
3965 mono_remoting_invoke (MonoObject
*real_proxy
, MonoMethodMessage
*msg
,
3966 MonoObject
**exc
, MonoArray
**out_args
)
3968 MonoMethod
*im
= real_proxy
->vtable
->domain
->private_invoke_method
;
3971 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
3974 im
= mono_class_get_method_from_name (mono_defaults
.real_proxy_class
, "PrivateInvoke", 4);
3976 real_proxy
->vtable
->domain
->private_invoke_method
= im
;
3979 pa
[0] = real_proxy
;
3984 return mono_runtime_invoke (im
, NULL
, pa
, exc
);
3988 mono_message_invoke (MonoObject
*target
, MonoMethodMessage
*msg
,
3989 MonoObject
**exc
, MonoArray
**out_args
)
3993 MonoMethodSignature
*sig
;
3995 int i
, j
, outarg_count
= 0;
3997 if (target
&& target
->vtable
->klass
== mono_defaults
.transparent_proxy_class
) {
3999 MonoTransparentProxy
* tp
= (MonoTransparentProxy
*)target
;
4000 if (tp
->remote_class
->proxy_class
->contextbound
&& tp
->rp
->context
== (MonoObject
*) mono_context_get ()) {
4001 target
= tp
->rp
->unwrapped_server
;
4003 return mono_remoting_invoke ((MonoObject
*)tp
->rp
, msg
, exc
, out_args
);
4007 domain
= mono_domain_get ();
4008 method
= msg
->method
->method
;
4009 sig
= mono_method_signature (method
);
4011 for (i
= 0; i
< sig
->param_count
; i
++) {
4012 if (sig
->params
[i
]->byref
)
4016 /* FIXME: GC ensure we insert a write barrier for out_args, maybe in the caller? */
4017 *out_args
= mono_array_new (domain
, mono_defaults
.object_class
, outarg_count
);
4020 ret
= mono_runtime_invoke_array (method
, method
->klass
->valuetype
? mono_object_unbox (target
): target
, msg
->args
, exc
);
4022 for (i
= 0, j
= 0; i
< sig
->param_count
; i
++) {
4023 if (sig
->params
[i
]->byref
) {
4025 arg
= mono_array_get (msg
->args
, gpointer
, i
);
4026 mono_array_setref (*out_args
, j
, arg
);
4035 * mono_print_unhandled_exception:
4036 * @exc: The exception
4038 * Prints the unhandled exception.
4041 mono_print_unhandled_exception (MonoObject
*exc
)
4043 char *message
= (char *) "";
4047 gboolean free_message
= FALSE
;
4049 if (mono_object_isinst (exc
, mono_defaults
.exception_class
)) {
4050 klass
= exc
->vtable
->klass
;
4052 while (klass
&& method
== NULL
) {
4053 method
= mono_class_get_method_from_name_flags (klass
, "ToString", 0, METHOD_ATTRIBUTE_VIRTUAL
| METHOD_ATTRIBUTE_PUBLIC
);
4055 klass
= klass
->parent
;
4060 str
= (MonoString
*) mono_runtime_invoke (method
, exc
, NULL
, NULL
);
4062 message
= mono_string_to_utf8 (str
);
4063 free_message
= TRUE
;
4068 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
4069 * exc->vtable->klass->name, message);
4071 g_printerr ("\nUnhandled Exception: %s\n", message
);
4078 * mono_delegate_ctor:
4079 * @this: pointer to an uninitialized delegate object
4080 * @target: target object
4081 * @addr: pointer to native code
4083 * This is used to initialize a delegate. We also insert the method_info if
4084 * we find the info with mono_jit_info_table_find().
4087 mono_delegate_ctor (MonoObject
*this, MonoObject
*target
, gpointer addr
)
4089 MonoDomain
*domain
= mono_domain_get ();
4090 MonoDelegate
*delegate
= (MonoDelegate
*)this;
4091 MonoMethod
*method
= NULL
;
4098 class = this->vtable
->klass
;
4100 if ((ji
= mono_jit_info_table_find (domain
, mono_get_addr_from_ftnptr (addr
)))) {
4101 method
= ji
->method
;
4102 MONO_OBJECT_SETREF (delegate
, method_info
, mono_method_get_object (domain
, method
, NULL
));
4105 if (target
&& target
->vtable
->klass
== mono_defaults
.transparent_proxy_class
) {
4107 method
= mono_marshal_get_remoting_invoke (method
);
4108 delegate
->method_ptr
= mono_compile_method (method
);
4109 MONO_OBJECT_SETREF (delegate
, target
, target
);
4110 } else if (mono_method_signature (method
)->hasthis
&& method
->klass
->valuetype
) {
4111 method
= mono_marshal_get_unbox_wrapper (method
);
4112 delegate
->method_ptr
= mono_compile_method (method
);
4113 MONO_OBJECT_SETREF (delegate
, target
, target
);
4117 * Replace the original trampoline with a delegate trampoline
4118 * which will patch delegate->method_ptr with the address of the
4121 addr
= arch_create_delegate_trampoline (method
, addr
);
4123 delegate
->method_ptr
= addr
;
4124 MONO_OBJECT_SETREF (delegate
, target
, target
);
4129 * mono_method_call_message_new:
4130 * @method: method to encapsulate
4131 * @params: parameters to the method
4132 * @invoke: optional, delegate invoke.
4133 * @cb: async callback delegate.
4134 * @state: state passed to the async callback.
4136 * Translates arguments pointers into a MonoMethodMessage.
4139 mono_method_call_message_new (MonoMethod
*method
, gpointer
*params
, MonoMethod
*invoke
,
4140 MonoDelegate
**cb
, MonoObject
**state
)
4142 MonoDomain
*domain
= mono_domain_get ();
4143 MonoMethodSignature
*sig
= mono_method_signature (method
);
4144 MonoMethodMessage
*msg
;
4147 msg
= (MonoMethodMessage
*)mono_object_new (domain
, mono_defaults
.mono_method_message_class
);
4150 mono_message_init (domain
, msg
, mono_method_get_object (domain
, invoke
, NULL
), NULL
);
4151 count
= sig
->param_count
- 2;
4153 mono_message_init (domain
, msg
, mono_method_get_object (domain
, method
, NULL
), NULL
);
4154 count
= sig
->param_count
;
4157 for (i
= 0; i
< count
; i
++) {
4162 if (sig
->params
[i
]->byref
)
4163 vpos
= *((gpointer
*)params
[i
]);
4167 type
= sig
->params
[i
]->type
;
4168 class = mono_class_from_mono_type (sig
->params
[i
]);
4170 if (class->valuetype
)
4171 arg
= mono_value_box (domain
, class, vpos
);
4173 arg
= *((MonoObject
**)vpos
);
4175 mono_array_setref (msg
->args
, i
, arg
);
4178 if (cb
!= NULL
&& state
!= NULL
) {
4179 *cb
= *((MonoDelegate
**)params
[i
]);
4181 *state
= *((MonoObject
**)params
[i
]);
4188 * mono_method_return_message_restore:
4190 * Restore results from message based processing back to arguments pointers
4193 mono_method_return_message_restore (MonoMethod
*method
, gpointer
*params
, MonoArray
*out_args
)
4195 MonoMethodSignature
*sig
= mono_method_signature (method
);
4196 int i
, j
, type
, size
, out_len
;
4198 if (out_args
== NULL
)
4200 out_len
= mono_array_length (out_args
);
4204 for (i
= 0, j
= 0; i
< sig
->param_count
; i
++) {
4205 MonoType
*pt
= sig
->params
[i
];
4210 mono_raise_exception (mono_get_exception_execution_engine ("The proxy call returned an incorrect number of output arguments"));
4212 arg
= mono_array_get (out_args
, gpointer
, j
);
4216 case MONO_TYPE_VOID
:
4217 g_assert_not_reached ();
4221 case MONO_TYPE_BOOLEAN
:
4224 case MONO_TYPE_CHAR
:
4231 case MONO_TYPE_VALUETYPE
: {
4233 size
= mono_class_value_size (((MonoObject
*)arg
)->vtable
->klass
, NULL
);
4234 memcpy (*((gpointer
*)params
[i
]), arg
+ sizeof (MonoObject
), size
);
4237 size
= mono_class_value_size (mono_class_from_mono_type (pt
), NULL
);
4238 memset (*((gpointer
*)params
[i
]), 0, size
);
4242 case MONO_TYPE_STRING
:
4243 case MONO_TYPE_CLASS
:
4244 case MONO_TYPE_ARRAY
:
4245 case MONO_TYPE_SZARRAY
:
4246 case MONO_TYPE_OBJECT
:
4247 **((MonoObject
***)params
[i
]) = (MonoObject
*)arg
;
4250 g_assert_not_reached ();
4259 * mono_load_remote_field:
4260 * @this: pointer to an object
4261 * @klass: klass of the object containing @field
4262 * @field: the field to load
4263 * @res: a storage to store the result
4265 * This method is called by the runtime on attempts to load fields of
4266 * transparent proxy objects. @this points to such TP, @klass is the class of
4267 * the object containing @field. @res is a storage location which can be
4268 * used to store the result.
4270 * Returns: an address pointing to the value of field.
4273 mono_load_remote_field (MonoObject
*this, MonoClass
*klass
, MonoClassField
*field
, gpointer
*res
)
4275 static MonoMethod
*getter
= NULL
;
4276 MonoDomain
*domain
= mono_domain_get ();
4277 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
4278 MonoClass
*field_class
;
4279 MonoMethodMessage
*msg
;
4280 MonoArray
*out_args
;
4284 g_assert (this->vtable
->klass
== mono_defaults
.transparent_proxy_class
);
4285 g_assert (res
!= NULL
);
4287 if (tp
->remote_class
->proxy_class
->contextbound
&& tp
->rp
->context
== (MonoObject
*) mono_context_get ()) {
4288 mono_field_get_value (tp
->rp
->unwrapped_server
, field
, res
);
4293 getter
= mono_class_get_method_from_name (mono_defaults
.object_class
, "FieldGetter", -1);
4297 field_class
= mono_class_from_mono_type (field
->type
);
4299 msg
= (MonoMethodMessage
*)mono_object_new (domain
, mono_defaults
.mono_method_message_class
);
4300 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 1);
4301 mono_message_init (domain
, msg
, mono_method_get_object (domain
, getter
, NULL
), out_args
);
4303 full_name
= mono_type_get_full_name (klass
);
4304 mono_array_setref (msg
->args
, 0, mono_string_new (domain
, full_name
));
4305 mono_array_setref (msg
->args
, 1, mono_string_new (domain
, field
->name
));
4308 mono_remoting_invoke ((MonoObject
*)(tp
->rp
), msg
, &exc
, &out_args
);
4310 if (exc
) mono_raise_exception ((MonoException
*)exc
);
4312 if (mono_array_length (out_args
) == 0)
4315 *res
= mono_array_get (out_args
, MonoObject
*, 0); /* FIXME: GC write abrrier for res */
4317 if (field_class
->valuetype
) {
4318 return ((char *)*res
) + sizeof (MonoObject
);
4324 * mono_load_remote_field_new:
4329 * Missing documentation.
4332 mono_load_remote_field_new (MonoObject
*this, MonoClass
*klass
, MonoClassField
*field
)
4334 static MonoMethod
*getter
= NULL
;
4335 MonoDomain
*domain
= mono_domain_get ();
4336 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
4337 MonoClass
*field_class
;
4338 MonoMethodMessage
*msg
;
4339 MonoArray
*out_args
;
4340 MonoObject
*exc
, *res
;
4343 g_assert (this->vtable
->klass
== mono_defaults
.transparent_proxy_class
);
4345 field_class
= mono_class_from_mono_type (field
->type
);
4347 if (tp
->remote_class
->proxy_class
->contextbound
&& tp
->rp
->context
== (MonoObject
*) mono_context_get ()) {
4349 if (field_class
->valuetype
) {
4350 res
= mono_object_new (domain
, field_class
);
4351 val
= ((gchar
*) res
) + sizeof (MonoObject
);
4355 mono_field_get_value (tp
->rp
->unwrapped_server
, field
, val
);
4360 getter
= mono_class_get_method_from_name (mono_defaults
.object_class
, "FieldGetter", -1);
4364 msg
= (MonoMethodMessage
*)mono_object_new (domain
, mono_defaults
.mono_method_message_class
);
4365 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 1);
4367 mono_message_init (domain
, msg
, mono_method_get_object (domain
, getter
, NULL
), out_args
);
4369 full_name
= mono_type_get_full_name (klass
);
4370 mono_array_setref (msg
->args
, 0, mono_string_new (domain
, full_name
));
4371 mono_array_setref (msg
->args
, 1, mono_string_new (domain
, field
->name
));
4374 mono_remoting_invoke ((MonoObject
*)(tp
->rp
), msg
, &exc
, &out_args
);
4376 if (exc
) mono_raise_exception ((MonoException
*)exc
);
4378 if (mono_array_length (out_args
) == 0)
4381 res
= mono_array_get (out_args
, MonoObject
*, 0);
4387 * mono_store_remote_field:
4388 * @this: pointer to an object
4389 * @klass: klass of the object containing @field
4390 * @field: the field to load
4391 * @val: the value/object to store
4393 * This method is called by the runtime on attempts to store fields of
4394 * transparent proxy objects. @this points to such TP, @klass is the class of
4395 * the object containing @field. @val is the new value to store in @field.
4398 mono_store_remote_field (MonoObject
*this, MonoClass
*klass
, MonoClassField
*field
, gpointer val
)
4400 static MonoMethod
*setter
= NULL
;
4401 MonoDomain
*domain
= mono_domain_get ();
4402 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
4403 MonoClass
*field_class
;
4404 MonoMethodMessage
*msg
;
4405 MonoArray
*out_args
;
4410 g_assert (this->vtable
->klass
== mono_defaults
.transparent_proxy_class
);
4412 field_class
= mono_class_from_mono_type (field
->type
);
4414 if (tp
->remote_class
->proxy_class
->contextbound
&& tp
->rp
->context
== (MonoObject
*) mono_context_get ()) {
4415 if (field_class
->valuetype
) mono_field_set_value (tp
->rp
->unwrapped_server
, field
, val
);
4416 else mono_field_set_value (tp
->rp
->unwrapped_server
, field
, *((MonoObject
**)val
));
4421 setter
= mono_class_get_method_from_name (mono_defaults
.object_class
, "FieldSetter", -1);
4425 if (field_class
->valuetype
)
4426 arg
= mono_value_box (domain
, field_class
, val
);
4428 arg
= *((MonoObject
**)val
);
4431 msg
= (MonoMethodMessage
*)mono_object_new (domain
, mono_defaults
.mono_method_message_class
);
4432 mono_message_init (domain
, msg
, mono_method_get_object (domain
, setter
, NULL
), NULL
);
4434 full_name
= mono_type_get_full_name (klass
);
4435 mono_array_setref (msg
->args
, 0, mono_string_new (domain
, full_name
));
4436 mono_array_setref (msg
->args
, 1, mono_string_new (domain
, field
->name
));
4437 mono_array_setref (msg
->args
, 2, arg
);
4440 mono_remoting_invoke ((MonoObject
*)(tp
->rp
), msg
, &exc
, &out_args
);
4442 if (exc
) mono_raise_exception ((MonoException
*)exc
);
4446 * mono_store_remote_field_new:
4452 * Missing documentation
4455 mono_store_remote_field_new (MonoObject
*this, MonoClass
*klass
, MonoClassField
*field
, MonoObject
*arg
)
4457 static MonoMethod
*setter
= NULL
;
4458 MonoDomain
*domain
= mono_domain_get ();
4459 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
4460 MonoClass
*field_class
;
4461 MonoMethodMessage
*msg
;
4462 MonoArray
*out_args
;
4466 g_assert (this->vtable
->klass
== mono_defaults
.transparent_proxy_class
);
4468 field_class
= mono_class_from_mono_type (field
->type
);
4470 if (tp
->remote_class
->proxy_class
->contextbound
&& tp
->rp
->context
== (MonoObject
*) mono_context_get ()) {
4471 if (field_class
->valuetype
) mono_field_set_value (tp
->rp
->unwrapped_server
, field
, ((gchar
*) arg
) + sizeof (MonoObject
));
4472 else mono_field_set_value (tp
->rp
->unwrapped_server
, field
, arg
);
4477 setter
= mono_class_get_method_from_name (mono_defaults
.object_class
, "FieldSetter", -1);
4481 msg
= (MonoMethodMessage
*)mono_object_new (domain
, mono_defaults
.mono_method_message_class
);
4482 mono_message_init (domain
, msg
, mono_method_get_object (domain
, setter
, NULL
), NULL
);
4484 full_name
= mono_type_get_full_name (klass
);
4485 mono_array_setref (msg
->args
, 0, mono_string_new (domain
, full_name
));
4486 mono_array_setref (msg
->args
, 1, mono_string_new (domain
, field
->name
));
4487 mono_array_setref (msg
->args
, 2, arg
);
4490 mono_remoting_invoke ((MonoObject
*)(tp
->rp
), msg
, &exc
, &out_args
);
4492 if (exc
) mono_raise_exception ((MonoException
*)exc
);
4496 * mono_get_addr_from_ftnptr:
4498 * Given a pointer to a function descriptor, return the function address.
4499 * This is only needed on IA64.
4502 mono_get_addr_from_ftnptr (gpointer descr
)
4505 return *(gpointer
*)descr
;
4513 * mono_string_chars:
4516 * Returns a pointer to the UCS16 characters stored in the MonoString
4519 mono_string_chars(MonoString
*s
)
4521 /* This method is here only for documentation extraction, this is a macro */
4525 * mono_string_length:
4528 * Returns the lenght in characters of the string
4531 mono_string_length (MonoString
*s
)
4533 /* This method is here only for documentation extraction, this is a macro */