5 * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
6 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
7 * Copyright 2011-2014 Xamarin, Inc (http://www.xamarin.com)
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
14 #include "mono/metadata/handle.h"
15 #include "mono/metadata/method-builder-ilgen-internals.h"
16 #include "mono/metadata/remoting.h"
17 #include "mono/metadata/marshal.h"
18 #include "mono/metadata/marshal-internals.h"
19 #include "mono/metadata/abi-details.h"
20 #include "mono/metadata/class-init.h"
21 #include "mono/metadata/cominterop.h"
22 #include "mono/metadata/tabledefs.h"
23 #include "mono/metadata/exception.h"
24 #include "mono/metadata/debug-helpers.h"
25 #include "mono/metadata/reflection-internals.h"
26 #include "mono/metadata/assembly.h"
27 #include "icall-decl.h"
30 MONO_MARSHAL_NONE
, /* No marshalling needed */
31 MONO_MARSHAL_COPY
, /* Can be copied by value to the new domain */
32 MONO_MARSHAL_COPY_OUT
, /* out parameter that needs to be copied back to the original instance */
33 MONO_MARSHAL_SERIALIZE
/* Value needs to be serialized into the new domain */
34 } MonoXDomainMarshalType
;
36 #ifndef DISABLE_REMOTING
38 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
42 #include "mono/cil/opcode.def"
47 struct _MonoRemotingMethods
{
49 MonoMethod
*invoke_with_check
;
50 MonoMethod
*xdomain_invoke
;
51 MonoMethod
*xdomain_dispatch
;
54 typedef struct _MonoRemotingMethods MonoRemotingMethods
;
57 mono_remoting_wrapper (MonoMethod
*method
, gpointer
*params
);
59 static MonoException
*
60 mono_remoting_update_exception (MonoException
*exc
);
63 mono_marshal_set_domain_by_id (gint32 id
, MonoBoolean push
);
66 mono_marshal_check_domain_image (gint32 domain_id
, MonoImage
*image
);
69 mono_upgrade_remote_class_wrapper (MonoReflectionType
*rtype
, MonoTransparentProxy
*tproxy
);
71 static MonoXDomainMarshalType
72 mono_get_xdomain_marshal_type (MonoType
*t
);
75 mono_marshal_xdomain_copy_out_value (MonoObject
*src
, MonoObject
*dst
);
77 static MonoReflectionType
*
78 type_from_handle (MonoType
*handle
);
81 mono_context_set_icall (MonoAppContext
*new_context
);
83 static MonoAppContext
*
84 mono_context_get_icall (void);
87 mono_marshal_xdomain_copy_value (MonoObject
* val_raw
, MonoError
*error
);
89 /* Class lazy loading functions */
90 static GENERATE_GET_CLASS_WITH_CACHE (remoting_services
, "System.Runtime.Remoting", "RemotingServices")
91 static GENERATE_GET_CLASS_WITH_CACHE (call_context
, "System.Runtime.Remoting.Messaging", "CallContext")
92 static GENERATE_GET_CLASS_WITH_CACHE (context
, "System.Runtime.Remoting.Contexts", "Context")
94 static mono_mutex_t remoting_mutex
;
95 static gboolean remoting_mutex_inited
;
97 static MonoClass
*byte_array_class
;
99 static MonoMethod
*method_rs_serialize
, *method_rs_deserialize
, *method_exc_fixexc
, *method_rs_appdomain_target
;
100 static MonoMethod
*method_set_call_context
, *method_needs_context_sink
, *method_rs_serialize_exc
;
104 mono_compile_method_icall (MonoMethod
*method
);
107 template <typename T
>
109 register_icall (T func
, const char *name
, const char *sigstr
, gboolean save
)
112 register_icall (gpointer func
, const char *name
, const char *sigstr
, gboolean save
)
115 MonoMethodSignature
*sig
= mono_create_icall_signature (sigstr
);
117 mono_register_jit_icall (func
, name
, sig
, save
);
123 g_assert (remoting_mutex_inited
);
124 mono_os_mutex_lock (&remoting_mutex
);
128 remoting_unlock (void)
130 g_assert (remoting_mutex_inited
);
131 mono_os_mutex_unlock (&remoting_mutex
);
135 * Return the hash table pointed to by VAR, lazily creating it if neccesary.
138 get_cache (GHashTable
**var
, GHashFunc hash_func
, GCompareFunc equal_func
)
144 g_hash_table_new (hash_func
, equal_func
);
145 mono_memory_barrier ();
154 get_cache_full (GHashTable
**var
, GHashFunc hash_func
, GCompareFunc equal_func
, GDestroyNotify key_destroy_func
, GDestroyNotify value_destroy_func
)
160 g_hash_table_new_full (hash_func
, equal_func
, key_destroy_func
, value_destroy_func
);
161 mono_memory_barrier ();
170 mono_remoting_init (void)
172 mono_os_mutex_init (&remoting_mutex
);
173 remoting_mutex_inited
= TRUE
;
177 mono_remoting_marshal_init (void)
182 static gboolean module_initialized
= FALSE
;
183 static gboolean icalls_registered
= FALSE
;
185 if (module_initialized
)
188 byte_array_class
= mono_class_create_array (mono_defaults
.byte_class
, 1);
191 klass
= mono_class_get_remoting_services_class ();
192 method_rs_serialize
= mono_class_get_method_from_name_checked (klass
, "SerializeCallData", -1, 0, error
);
193 mono_error_assert_ok (error
);
194 g_assert (method_rs_serialize
);
195 method_rs_deserialize
= mono_class_get_method_from_name_checked (klass
, "DeserializeCallData", -1, 0, error
);
196 mono_error_assert_ok (error
);
197 g_assert (method_rs_deserialize
);
198 method_rs_serialize_exc
= mono_class_get_method_from_name_checked (klass
, "SerializeExceptionData", -1, 0, error
);
199 mono_error_assert_ok (error
);
200 g_assert (method_rs_serialize_exc
);
202 klass
= mono_defaults
.real_proxy_class
;
203 method_rs_appdomain_target
= mono_class_get_method_from_name_checked (klass
, "GetAppDomainTarget", -1, 0, error
);
204 mono_error_assert_ok (error
);
205 g_assert (method_rs_appdomain_target
);
207 klass
= mono_defaults
.exception_class
;
208 method_exc_fixexc
= mono_class_get_method_from_name_checked (klass
, "FixRemotingException", -1, 0, error
);
209 mono_error_assert_ok (error
);
210 g_assert (method_exc_fixexc
);
212 klass
= mono_class_get_call_context_class ();
213 method_set_call_context
= mono_class_get_method_from_name_checked (klass
, "SetCurrentCallContext", -1, 0, error
);
214 mono_error_assert_ok (error
);
215 g_assert (method_set_call_context
);
217 klass
= mono_class_get_context_class ();
218 method_needs_context_sink
= mono_class_get_method_from_name_checked (klass
, "get_NeedsContextSink", -1, 0, error
);
219 mono_error_assert_ok (error
);
220 g_assert (method_needs_context_sink
);
225 if (!icalls_registered
) {
226 register_icall (type_from_handle
, "type_from_handle", "object ptr", FALSE
);
227 register_icall (mono_marshal_set_domain_by_id
, "mono_marshal_set_domain_by_id", "int32 int32 int32", FALSE
);
228 register_icall (mono_marshal_check_domain_image
, "mono_marshal_check_domain_image", "int32 int32 ptr", FALSE
);
229 register_icall (ves_icall_mono_marshal_xdomain_copy_value
, "ves_icall_mono_marshal_xdomain_copy_value", "object object", FALSE
);
230 register_icall (mono_marshal_xdomain_copy_out_value
, "mono_marshal_xdomain_copy_out_value", "void object object", FALSE
);
231 register_icall (mono_remoting_wrapper
, "mono_remoting_wrapper", "object ptr ptr", FALSE
);
232 register_icall (mono_remoting_update_exception
, "mono_remoting_update_exception", "object object", FALSE
);
233 register_icall (mono_upgrade_remote_class_wrapper
, "mono_upgrade_remote_class_wrapper", "void object object", FALSE
);
236 register_icall (mono_compile_method_icall
, "mono_compile_method_icall", "ptr ptr", FALSE
);
239 register_icall (mono_context_get_icall
, "mono_context_get_icall", "object", FALSE
);
240 register_icall (mono_context_set_icall
, "mono_context_set_icall", "void object", FALSE
);
243 icalls_registered
= TRUE
;
245 mono_loader_unlock ();
247 module_initialized
= TRUE
;
250 // This is an icall, it will return NULL and set pending exception (in
251 // mono_type_from_handle wrapper) on failure.
252 static MonoReflectionType
*
253 type_from_handle (MonoType
*handle
)
255 return mono_type_from_handle (handle
);
260 mono_mb_emit_proxy_check (MonoMethodBuilder
*mb
, int branch_code
)
263 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoObject
, vtable
));
264 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
265 mono_mb_emit_icon (mb
, MONO_STRUCT_OFFSET (MonoVTable
, klass
));
266 mono_mb_emit_byte (mb
, CEE_ADD
);
267 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
268 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
269 mono_mb_emit_byte (mb
, CEE_MONO_CLASSCONST
);
270 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_defaults
.transparent_proxy_class
));
271 pos
= mono_mb_emit_branch (mb
, branch_code
);
276 mono_mb_emit_xdomain_check (MonoMethodBuilder
*mb
, int branch_code
)
279 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
280 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
281 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRealProxy
, target_domain_id
));
282 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
283 mono_mb_emit_icon (mb
, -1);
284 pos
= mono_mb_emit_branch (mb
, branch_code
);
289 mono_mb_emit_contextbound_check (MonoMethodBuilder
*mb
, int branch_code
)
291 static int offset
= -1;
295 mono_class_contextbound_bit_offset (&offset
, &mask
);
297 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, remote_class
));
298 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
299 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRemoteClass
, proxy_class
));
300 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
301 mono_mb_emit_ldflda (mb
, offset
);
302 mono_mb_emit_byte (mb
, CEE_LDIND_U1
);
303 mono_mb_emit_icon (mb
, mask
);
304 mono_mb_emit_byte (mb
, CEE_AND
);
305 mono_mb_emit_icon (mb
, 0);
306 return mono_mb_emit_branch (mb
, branch_code
);
308 #endif /* !DISABLE_JIT */
310 static inline MonoMethod
*
311 mono_marshal_remoting_find_in_cache (MonoMethod
*method
, int wrapper_type
)
313 MonoMethod
*res
= NULL
;
314 MonoRemotingMethods
*wrps
= NULL
;
316 mono_marshal_lock_internal ();
317 if (mono_method_get_wrapper_cache (method
)->remoting_invoke_cache
)
318 wrps
= (MonoRemotingMethods
*)g_hash_table_lookup (mono_method_get_wrapper_cache (method
)->remoting_invoke_cache
, method
);
321 switch (wrapper_type
) {
322 case MONO_WRAPPER_REMOTING_INVOKE
: res
= wrps
->invoke
; break;
323 case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
: res
= wrps
->invoke_with_check
; break;
324 case MONO_WRAPPER_XDOMAIN_INVOKE
: res
= wrps
->xdomain_invoke
; break;
325 case MONO_WRAPPER_XDOMAIN_DISPATCH
: res
= wrps
->xdomain_dispatch
; break;
329 /* it is important to do the unlock after the load from wrps, since in
330 * mono_remoting_mb_create_and_cache () we drop the marshal lock to be able
331 * to take the loader lock and some other thread may set the fields.
333 mono_marshal_unlock_internal ();
337 /* Create the method from the builder and place it in the cache */
338 static inline MonoMethod
*
339 mono_remoting_mb_create_and_cache (MonoMethod
*key
, MonoMethodBuilder
*mb
,
340 MonoMethodSignature
*sig
, int max_stack
, WrapperInfo
*info
)
342 MonoMethod
**res
= NULL
;
343 MonoRemotingMethods
*wrps
;
346 cache
= get_cache_full (&mono_method_get_wrapper_cache (key
)->remoting_invoke_cache
, mono_aligned_addr_hash
, NULL
, NULL
, g_free
);
348 mono_marshal_lock_internal ();
349 wrps
= (MonoRemotingMethods
*)g_hash_table_lookup (cache
, key
);
351 wrps
= g_new0 (MonoRemotingMethods
, 1);
352 g_hash_table_insert (cache
, key
, wrps
);
355 switch (mb
->method
->wrapper_type
) {
356 case MONO_WRAPPER_REMOTING_INVOKE
: res
= &wrps
->invoke
; break;
357 case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
: res
= &wrps
->invoke_with_check
; break;
358 case MONO_WRAPPER_XDOMAIN_INVOKE
: res
= &wrps
->xdomain_invoke
; break;
359 case MONO_WRAPPER_XDOMAIN_DISPATCH
: res
= &wrps
->xdomain_dispatch
; break;
360 default: g_assert_not_reached (); break;
362 mono_marshal_unlock_internal ();
366 newm
= mono_mb_create_method (mb
, sig
, max_stack
);
368 mono_marshal_lock_internal ();
371 mono_marshal_set_wrapper_info (*res
, info
);
372 mono_marshal_unlock_internal ();
374 mono_marshal_unlock_internal ();
375 mono_free_method (newm
);
383 mono_remoting_wrapper (MonoMethod
*method
, gpointer
*params
)
386 MonoMethodMessage
*msg
;
387 MonoTransparentProxy
*this_obj
;
388 MonoObject
*res
, *exc
;
391 this_obj
= *((MonoTransparentProxy
**)params
[0]);
394 g_assert (mono_object_is_transparent_proxy (this_obj
));
396 /* skip the this pointer */
399 if (mono_class_is_contextbound (this_obj
->remote_class
->proxy_class
) && this_obj
->rp
->context
== (MonoObject
*) mono_context_get ())
402 MonoMethodSignature
*sig
= mono_method_signature_internal (method
);
403 int count
= sig
->param_count
;
404 gpointer
* mparams
= g_newa (gpointer
, count
);
406 for (i
=0; i
<count
; i
++) {
407 MonoClass
*klass
= mono_class_from_mono_type_internal (sig
->params
[i
]);
408 if (m_class_is_valuetype (klass
)) {
409 if (sig
->params
[i
]->byref
) {
410 mparams
[i
] = *((gpointer
*)params
[i
]);
412 /* runtime_invoke expects a boxed instance */
413 if (mono_class_is_nullable (mono_class_from_mono_type_internal (sig
->params
[i
]))) {
414 mparams
[i
] = mono_nullable_box ((guint8
*)params
[i
], klass
, error
);
415 goto_if_nok (error
, fail
);
417 mparams
[i
] = params
[i
];
420 mparams
[i
] = *((gpointer
**)params
[i
]);
424 res
= mono_runtime_invoke_checked (method
, m_class_is_valuetype (method
->klass
)? mono_object_unbox_internal ((MonoObject
*)this_obj
): this_obj
, mparams
, error
);
425 goto_if_nok (error
, fail
);
430 msg
= mono_method_call_message_new (method
, params
, NULL
, NULL
, NULL
, error
);
431 goto_if_nok (error
, fail
);
433 res
= mono_remoting_invoke ((MonoObject
*)this_obj
->rp
, msg
, &exc
, &out_args
, error
);
434 goto_if_nok (error
, fail
);
438 exc
= (MonoObject
*) mono_remoting_update_exception ((MonoException
*)exc
);
439 mono_error_set_exception_instance (error
, (MonoException
*)exc
);
443 mono_method_return_message_restore (method
, params
, out_args
, error
);
444 goto_if_nok (error
, fail
);
448 mono_error_set_pending_exception (error
);
453 * Handles exception transformation at appdomain call boundary.
454 * Note this is called from target appdomain inside xdomain wrapper, but from
455 * source domain in the mono_remoting_wrapper slowpath.
457 static MonoException
*
458 mono_remoting_update_exception (MonoException
*exc
)
460 MonoInternalThread
*thread
;
461 MonoClass
*klass
= mono_object_class (exc
);
463 /* Serialization error can only happen when still in the target appdomain */
464 if (!(mono_class_get_flags (klass
) & TYPE_ATTRIBUTE_SERIALIZABLE
)) {
466 char *aname
= mono_stringify_assembly_name (&m_class_get_image (klass
)->assembly
->aname
);
467 char *message
= g_strdup_printf ("Type '%s' in Assembly '%s' is not marked as serializable", m_class_get_name (klass
), aname
);
468 ret
= mono_get_exception_serialization (message
);
474 thread
= mono_thread_internal_current ();
475 if (mono_object_class (exc
) == mono_defaults
.threadabortexception_class
&&
476 thread
->flags
& MONO_THREAD_FLAG_APPDOMAIN_ABORT
) {
477 mono_thread_internal_reset_abort (thread
);
478 return mono_get_exception_appdomain_unloaded ();
485 * mono_marshal_get_remoting_invoke:
488 mono_marshal_get_remoting_invoke (MonoMethod
*method
, MonoError
*error
)
490 MonoMethodSignature
*sig
;
491 MonoMethodBuilder
*mb
;
499 if (method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE
|| method
->wrapper_type
== MONO_WRAPPER_XDOMAIN_INVOKE
)
502 /* this seems to be the best plase to put this, as all remoting invokes seem to get filtered through here */
504 if (mono_class_is_com_object (method
->klass
) || method
->klass
== mono_class_try_get_com_object_class ()) {
505 MonoVTable
*vtable
= mono_class_vtable_checked (mono_domain_get (), method
->klass
, error
);
506 return_val_if_nok (error
, NULL
);
508 if (!mono_vtable_is_remote (vtable
)) {
509 return mono_cominterop_get_invoke (method
);
514 sig
= mono_signature_no_pinvoke (method
);
516 /* we cant remote methods without this pointer */
520 if ((res
= mono_marshal_remoting_find_in_cache (method
, MONO_WRAPPER_REMOTING_INVOKE
)))
523 mono_remoting_marshal_init ();
525 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_REMOTING_INVOKE
);
528 mb
->method
->save_lmf
= 1;
530 params_var
= mono_mb_emit_save_args (mb
, sig
, TRUE
);
532 mono_mb_emit_ptr (mb
, method
);
533 mono_mb_emit_ldloc (mb
, params_var
);
534 mono_mb_emit_icall (mb
, mono_remoting_wrapper
);
535 // FIXME: this interrupt checkpoint code is a no-op since 'mb'
536 // is a MONO_WRAPPER_REMOTING_INVOKE, and
537 // mono_thread_interruption_checkpoint_request (FALSE)
538 // considers such wrappers "protected" and always returns
539 // NULL as if there's no pending interruption.
540 mono_marshal_emit_thread_interrupt_checkpoint (mb
);
542 if (sig
->ret
->type
== MONO_TYPE_VOID
) {
543 mono_mb_emit_byte (mb
, CEE_POP
);
544 mono_mb_emit_byte (mb
, CEE_RET
);
546 mono_mb_emit_restore_result (mb
, sig
->ret
);
550 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
551 info
->d
.remoting
.method
= method
;
552 res
= mono_remoting_mb_create_and_cache (method
, mb
, sig
, sig
->param_count
+ 16, info
);
558 /* mono_marshal_xdomain_copy_out_value()
559 * Copies the contents of the src instance into the dst instance. src and dst
560 * must have the same type, and if they are arrays, the same size.
562 * This is an icall, it may use mono_error_set_pending_exception
565 mono_marshal_xdomain_copy_out_value (MonoObject
*src
, MonoObject
*dst
)
568 if (src
== NULL
|| dst
== NULL
) return;
570 g_assert (mono_object_class (src
) == mono_object_class (dst
));
572 switch (m_class_get_byval_arg (mono_object_class (src
))->type
) {
573 case MONO_TYPE_ARRAY
:
574 case MONO_TYPE_SZARRAY
: {
575 int mt
= mono_get_xdomain_marshal_type (m_class_get_byval_arg (m_class_get_element_class (mono_object_class (src
))));
576 if (mt
== MONO_MARSHAL_SERIALIZE
) return;
577 if (mt
== MONO_MARSHAL_COPY
) {
578 int i
, len
= mono_array_length_internal ((MonoArray
*)dst
);
579 for (i
= 0; i
< len
; i
++) {
580 MonoObject
*item
= (MonoObject
*)mono_array_get_internal ((MonoArray
*)src
, gpointer
, i
);
581 MonoObject
*item_copy
= mono_marshal_xdomain_copy_value (item
, error
);
582 if (mono_error_set_pending_exception (error
))
584 mono_array_setref_internal ((MonoArray
*)dst
, i
, item_copy
);
587 mono_array_full_copy ((MonoArray
*)src
, (MonoArray
*)dst
);
598 #if !defined (DISABLE_JIT)
600 mono_marshal_emit_xdomain_copy_value (MonoMethodBuilder
*mb
, MonoClass
*pclass
)
602 mono_mb_emit_icall (mb
, ves_icall_mono_marshal_xdomain_copy_value
);
603 mono_mb_emit_op (mb
, CEE_CASTCLASS
, pclass
);
607 mono_marshal_emit_xdomain_copy_out_value (MonoMethodBuilder
*mb
, MonoClass
*pclass
)
609 mono_mb_emit_icall (mb
, mono_marshal_xdomain_copy_out_value
);
613 /* mono_marshal_supports_fast_xdomain()
614 * Returns TRUE if the method can use the fast xdomain wrapper.
617 mono_marshal_supports_fast_xdomain (MonoMethod
*method
)
619 return !mono_class_is_contextbound (method
->klass
) &&
620 !((method
->flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
) && (strcmp (".ctor", method
->name
) == 0));
624 mono_marshal_set_domain_by_id (gint32 id
, MonoBoolean push
)
626 MonoDomain
*current_domain
= mono_domain_get ();
627 MonoDomain
*domain
= mono_domain_get_by_id (id
);
629 if (!domain
|| !mono_domain_set (domain
, FALSE
)) {
630 mono_set_pending_exception (mono_get_exception_appdomain_unloaded ());
635 mono_thread_push_appdomain_ref (domain
);
637 mono_thread_pop_appdomain_ref ();
639 return current_domain
->domain_id
;
642 #if !defined (DISABLE_JIT)
644 mono_marshal_emit_switch_domain (MonoMethodBuilder
*mb
)
646 mono_mb_emit_icall (mb
, mono_marshal_set_domain_by_id
);
650 mono_compile_method_icall (MonoMethod
*method
)
653 gpointer result
= mono_compile_method_checked (method
, error
);
654 mono_error_set_pending_exception (error
);
658 /* mono_marshal_emit_load_domain_method ()
659 * Loads into the stack a pointer to the code of the provided method for
660 * the current domain.
663 mono_marshal_emit_load_domain_method (MonoMethodBuilder
*mb
, MonoMethod
*method
)
665 /* We need a pointer to the method for the running domain (not the domain
666 * that compiles the method).
668 mono_mb_emit_ptr (mb
, method
);
669 mono_mb_emit_icall (mb
, mono_compile_method_icall
);
673 /* mono_marshal_check_domain_image ()
674 * Returns TRUE if the image is loaded in the specified
675 * application domain.
678 mono_marshal_check_domain_image (gint32 domain_id
, MonoImage
*image
)
683 MonoDomain
*domain
= mono_domain_get_by_id (domain_id
);
687 mono_domain_assemblies_lock (domain
);
688 for (tmp
= domain
->domain_assemblies
; tmp
; tmp
= tmp
->next
) {
689 ass
= (MonoAssembly
*)tmp
->data
;
690 if (ass
->image
== image
)
693 mono_domain_assemblies_unlock (domain
);
698 /* mono_marshal_get_xappdomain_dispatch ()
699 * Generates a method that dispatches a method call from another domain into
700 * the current domain.
703 mono_marshal_get_xappdomain_dispatch (MonoMethod
*method
, int *marshal_types
, int complex_count
, int complex_out_count
, int ret_marshal_type
)
705 MonoMethodSignature
*sig
, *csig
;
706 MonoMethodBuilder
*mb
;
708 int i
, j
, param_index
, copy_locals_base
;
709 MonoClass
*ret_class
= NULL
;
710 int loc_array
=0, loc_return
=0, loc_serialized_exc
=0;
711 MonoExceptionClause
*main_clause
;
713 gboolean copy_return
;
716 if ((res
= mono_marshal_remoting_find_in_cache (method
, MONO_WRAPPER_XDOMAIN_DISPATCH
)))
719 sig
= mono_method_signature_internal (method
);
720 copy_return
= (sig
->ret
->type
!= MONO_TYPE_VOID
&& ret_marshal_type
!= MONO_MARSHAL_SERIALIZE
);
723 csig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 3 + sig
->param_count
- complex_count
);
724 csig
->params
[j
++] = mono_get_object_type ();
725 csig
->params
[j
++] = m_class_get_this_arg (byte_array_class
);
726 csig
->params
[j
++] = m_class_get_this_arg (byte_array_class
);
727 for (i
= 0; i
< sig
->param_count
; i
++) {
728 if (marshal_types
[i
] != MONO_MARSHAL_SERIALIZE
)
729 csig
->params
[j
++] = sig
->params
[i
];
732 csig
->ret
= sig
->ret
;
734 csig
->ret
= mono_get_void_type ();
736 csig
->hasthis
= FALSE
;
738 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_XDOMAIN_DISPATCH
);
739 mb
->method
->save_lmf
= 1;
744 loc_serialized_exc
= mono_mb_add_local (mb
, m_class_get_byval_arg (byte_array_class
));
745 if (complex_count
> 0)
746 loc_array
= mono_mb_add_local (mb
, mono_get_object_type ());
747 if (sig
->ret
->type
!= MONO_TYPE_VOID
) {
748 loc_return
= mono_mb_add_local (mb
, sig
->ret
);
749 ret_class
= mono_class_from_mono_type_internal (sig
->ret
);
754 main_clause
= (MonoExceptionClause
*)mono_image_alloc0 (m_class_get_image (method
->klass
), sizeof (MonoExceptionClause
));
755 main_clause
->try_offset
= mono_mb_get_label (mb
);
757 /* Clean the call context */
759 mono_mb_emit_byte (mb
, CEE_LDNULL
);
760 mono_mb_emit_managed_call (mb
, method_set_call_context
, NULL
);
761 mono_mb_emit_byte (mb
, CEE_POP
);
763 /* Deserialize call data */
765 mono_mb_emit_ldarg (mb
, 1);
766 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
767 mono_mb_emit_byte (mb
, CEE_DUP
);
768 pos
= mono_mb_emit_short_branch (mb
, CEE_BRFALSE_S
);
770 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
771 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
773 if (complex_count
> 0)
774 mono_mb_emit_stloc (mb
, loc_array
);
776 mono_mb_emit_byte (mb
, CEE_POP
);
778 mono_mb_patch_short_branch (mb
, pos
);
780 /* Get the target object */
782 mono_mb_emit_ldarg (mb
, 0);
783 mono_mb_emit_managed_call (mb
, method_rs_appdomain_target
, NULL
);
785 /* Load the arguments */
787 copy_locals_base
= mb
->locals
;
788 param_index
= 3; // Index of the first non-serialized parameter of this wrapper
790 for (i
= 0; i
< sig
->param_count
; i
++) {
791 MonoType
*pt
= sig
->params
[i
];
792 MonoClass
*pclass
= mono_class_from_mono_type_internal (pt
);
793 switch (marshal_types
[i
]) {
794 case MONO_MARSHAL_SERIALIZE
: {
795 /* take the value from the serialized array */
796 mono_mb_emit_ldloc (mb
, loc_array
);
797 mono_mb_emit_icon (mb
, j
++);
799 if (m_class_is_valuetype (pclass
)) {
800 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
801 mono_mb_emit_op (mb
, CEE_UNBOX
, pclass
);
803 mono_mb_emit_op (mb
, CEE_LDELEMA
, pclass
);
806 if (m_class_is_valuetype (pclass
)) {
807 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
808 mono_mb_emit_op (mb
, CEE_UNBOX
, pclass
);
809 mono_mb_emit_op (mb
, CEE_LDOBJ
, pclass
);
811 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
812 if (pclass
!= mono_defaults
.object_class
) {
813 mono_mb_emit_op (mb
, CEE_CASTCLASS
, pclass
);
819 case MONO_MARSHAL_COPY_OUT
: {
820 /* Keep a local copy of the value since we need to copy it back after the call */
821 int copy_local
= mono_mb_add_local (mb
, m_class_get_byval_arg (pclass
));
822 mono_mb_emit_ldarg (mb
, param_index
++);
823 mono_marshal_emit_xdomain_copy_value (mb
, pclass
);
824 mono_mb_emit_byte (mb
, CEE_DUP
);
825 mono_mb_emit_stloc (mb
, copy_local
);
828 case MONO_MARSHAL_COPY
: {
829 mono_mb_emit_ldarg (mb
, param_index
);
831 mono_mb_emit_byte (mb
, CEE_DUP
);
832 mono_mb_emit_byte (mb
, CEE_DUP
);
833 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
834 mono_marshal_emit_xdomain_copy_value (mb
, pclass
);
835 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
837 mono_marshal_emit_xdomain_copy_value (mb
, pclass
);
842 case MONO_MARSHAL_NONE
:
843 mono_mb_emit_ldarg (mb
, param_index
++);
848 /* Make the call to the real object */
850 mono_marshal_emit_thread_force_interrupt_checkpoint (mb
);
852 mono_mb_emit_op (mb
, CEE_CALLVIRT
, method
);
854 if (sig
->ret
->type
!= MONO_TYPE_VOID
)
855 mono_mb_emit_stloc (mb
, loc_return
);
857 /* copy back MONO_MARSHAL_COPY_OUT parameters */
861 for (i
= 0; i
< sig
->param_count
; i
++) {
862 if (marshal_types
[i
] == MONO_MARSHAL_SERIALIZE
) continue;
863 if (marshal_types
[i
] == MONO_MARSHAL_COPY_OUT
) {
864 mono_mb_emit_ldloc (mb
, copy_locals_base
+ (j
++));
865 mono_mb_emit_ldarg (mb
, param_index
);
866 mono_marshal_emit_xdomain_copy_out_value (mb
, mono_class_from_mono_type_internal (sig
->params
[i
]));
871 /* Serialize the return values */
873 if (complex_out_count
> 0) {
874 /* Reset parameters in the array that don't need to be serialized back */
876 for (i
= 0; i
< sig
->param_count
; i
++) {
877 if (marshal_types
[i
] != MONO_MARSHAL_SERIALIZE
) continue;
878 if (!sig
->params
[i
]->byref
) {
879 mono_mb_emit_ldloc (mb
, loc_array
);
880 mono_mb_emit_icon (mb
, j
);
881 mono_mb_emit_byte (mb
, CEE_LDNULL
);
882 mono_mb_emit_byte (mb
, CEE_STELEM_REF
);
887 /* Add the return value to the array */
889 if (ret_marshal_type
== MONO_MARSHAL_SERIALIZE
) {
890 mono_mb_emit_ldloc (mb
, loc_array
);
891 mono_mb_emit_icon (mb
, complex_count
); /* The array has an additional slot to hold the ret value */
892 mono_mb_emit_ldloc (mb
, loc_return
);
894 g_assert (ret_class
); /*FIXME properly fail here*/
895 if (m_class_is_valuetype (ret_class
)) {
896 mono_mb_emit_op (mb
, CEE_BOX
, ret_class
);
898 mono_mb_emit_byte (mb
, CEE_STELEM_REF
);
903 mono_mb_emit_ldarg (mb
, 1);
904 mono_mb_emit_ldloc (mb
, loc_array
);
905 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
906 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
907 } else if (ret_marshal_type
== MONO_MARSHAL_SERIALIZE
) {
908 mono_mb_emit_ldarg (mb
, 1);
909 mono_mb_emit_ldloc (mb
, loc_return
);
910 if (m_class_is_valuetype (ret_class
)) {
911 mono_mb_emit_op (mb
, CEE_BOX
, ret_class
);
913 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
914 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
916 mono_mb_emit_ldarg (mb
, 1);
917 mono_mb_emit_byte (mb
, CEE_LDNULL
);
918 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
919 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
922 mono_mb_emit_ldarg (mb
, 2);
923 mono_mb_emit_byte (mb
, CEE_LDNULL
);
924 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
925 pos_leave
= mono_mb_emit_branch (mb
, CEE_LEAVE
);
927 /* Main exception catch */
928 main_clause
->flags
= MONO_EXCEPTION_CLAUSE_NONE
;
929 main_clause
->try_len
= mono_mb_get_pos (mb
) - main_clause
->try_offset
;
930 main_clause
->data
.catch_class
= mono_defaults
.object_class
;
933 main_clause
->handler_offset
= mono_mb_get_label (mb
);
935 mono_mb_emit_icall (mb
, mono_remoting_update_exception
);
936 mono_mb_emit_op (mb
, CEE_CASTCLASS
, mono_defaults
.exception_class
);
937 mono_mb_emit_managed_call (mb
, method_rs_serialize_exc
, NULL
);
938 mono_mb_emit_stloc (mb
, loc_serialized_exc
);
939 mono_mb_emit_ldarg (mb
, 2);
940 mono_mb_emit_ldloc (mb
, loc_serialized_exc
);
941 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
942 mono_mb_emit_branch (mb
, CEE_LEAVE
);
944 main_clause
->handler_len
= mono_mb_get_pos (mb
) - main_clause
->handler_offset
;
946 mono_mb_patch_branch (mb
, pos_leave
);
949 mono_mb_emit_ldloc (mb
, loc_return
);
951 mono_mb_emit_byte (mb
, CEE_RET
);
953 mono_mb_set_clauses (mb
, 1, main_clause
);
956 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
957 info
->d
.remoting
.method
= method
;
958 res
= mono_remoting_mb_create_and_cache (method
, mb
, csig
, csig
->param_count
+ 16, info
);
965 * mono_marshal_get_xappdomain_invoke:
966 * Generates a fast remoting wrapper for cross app domain calls.
969 mono_marshal_get_xappdomain_invoke (MonoMethod
*method
, MonoError
*error
)
971 MonoMethodSignature
*sig
;
972 MonoMethodBuilder
*mb
;
974 int i
, j
, complex_count
, complex_out_count
, copy_locals_base
;
976 MonoClass
*ret_class
= NULL
;
977 MonoMethod
*xdomain_method
;
978 int ret_marshal_type
= MONO_MARSHAL_NONE
;
979 int loc_array
=0, loc_serialized_data
=-1, loc_real_proxy
;
980 int loc_old_domainid
, loc_domainid
, loc_return
=0, loc_serialized_exc
=0, loc_context
;
981 int pos
, pos_dispatch
, pos_noex
;
982 gboolean copy_return
= FALSE
;
988 if (method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE
|| method
->wrapper_type
== MONO_WRAPPER_XDOMAIN_INVOKE
)
991 /* we cant remote methods without this pointer */
992 if (!mono_method_signature_internal (method
)->hasthis
)
995 mono_remoting_marshal_init ();
997 if (!mono_marshal_supports_fast_xdomain (method
))
998 return mono_marshal_get_remoting_invoke (method
, error
);
1000 if ((res
= mono_marshal_remoting_find_in_cache (method
, MONO_WRAPPER_XDOMAIN_INVOKE
)))
1003 sig
= mono_signature_no_pinvoke (method
);
1005 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_XDOMAIN_INVOKE
);
1006 mb
->method
->save_lmf
= 1;
1008 /* Count the number of parameters that need to be serialized */
1010 marshal_types
= g_newa (int, sig
->param_count
);
1011 complex_count
= complex_out_count
= 0;
1012 for (i
= 0; i
< sig
->param_count
; i
++) {
1013 MonoType
*ptype
= sig
->params
[i
];
1014 int mt
= mono_get_xdomain_marshal_type (ptype
);
1016 /* If the [Out] attribute is applied to a parameter that can be internally copied,
1017 * the copy will be made by reusing the original object instance
1019 if ((ptype
->attrs
& PARAM_ATTRIBUTE_OUT
) != 0 && mt
== MONO_MARSHAL_COPY
&& !ptype
->byref
)
1020 mt
= MONO_MARSHAL_COPY_OUT
;
1021 else if (mt
== MONO_MARSHAL_SERIALIZE
) {
1023 if (ptype
->byref
) complex_out_count
++;
1025 marshal_types
[i
] = mt
;
1028 if (sig
->ret
->type
!= MONO_TYPE_VOID
) {
1029 ret_marshal_type
= mono_get_xdomain_marshal_type (sig
->ret
);
1030 ret_class
= mono_class_from_mono_type_internal (sig
->ret
);
1031 copy_return
= ret_marshal_type
!= MONO_MARSHAL_SERIALIZE
;
1037 MonoType
*object_type
= mono_get_object_type ();
1038 MonoType
*byte_array_type
= m_class_get_byval_arg (byte_array_class
);
1039 MonoType
*int32_type
= mono_get_int32_type ();
1040 if (complex_count
> 0)
1041 loc_array
= mono_mb_add_local (mb
, object_type
);
1042 loc_serialized_data
= mono_mb_add_local (mb
, byte_array_type
);
1043 loc_real_proxy
= mono_mb_add_local (mb
, object_type
);
1045 loc_return
= mono_mb_add_local (mb
, sig
->ret
);
1046 loc_old_domainid
= mono_mb_add_local (mb
, int32_type
);
1047 loc_domainid
= mono_mb_add_local (mb
, int32_type
);
1048 loc_serialized_exc
= mono_mb_add_local (mb
, byte_array_type
);
1049 loc_context
= mono_mb_add_local (mb
, object_type
);
1051 /* Save thread domain data */
1053 mono_mb_emit_icall (mb
, mono_context_get_icall
);
1054 mono_mb_emit_byte (mb
, CEE_DUP
);
1055 mono_mb_emit_stloc (mb
, loc_context
);
1057 /* If the thread is not running in the default context, it needs to go
1058 * through the whole remoting sink, since the context is going to change
1060 mono_mb_emit_managed_call (mb
, method_needs_context_sink
, NULL
);
1061 pos
= mono_mb_emit_short_branch (mb
, CEE_BRTRUE_S
);
1063 /* Another case in which the fast path can't be used: when the target domain
1064 * has a different image for the same assembly.
1067 /* Get the target domain id */
1069 mono_mb_emit_ldarg (mb
, 0);
1070 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
1071 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1072 mono_mb_emit_byte (mb
, CEE_DUP
);
1073 mono_mb_emit_stloc (mb
, loc_real_proxy
);
1075 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRealProxy
, target_domain_id
));
1076 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
1077 mono_mb_emit_stloc (mb
, loc_domainid
);
1079 /* Check if the target domain has the same image for the required assembly */
1081 mono_mb_emit_ldloc (mb
, loc_domainid
);
1082 mono_mb_emit_ptr (mb
, m_class_get_image (method
->klass
));
1083 mono_mb_emit_icall (mb
, mono_marshal_check_domain_image
);
1084 pos_dispatch
= mono_mb_emit_short_branch (mb
, CEE_BRTRUE_S
);
1086 /* Use the whole remoting sink to dispatch this message */
1088 mono_mb_patch_short_branch (mb
, pos
);
1090 mono_mb_emit_ldarg (mb
, 0);
1091 for (i
= 0; i
< sig
->param_count
; i
++)
1092 mono_mb_emit_ldarg (mb
, i
+ 1);
1094 MonoMethod
* remoting_invoke_method
= mono_marshal_get_remoting_invoke (method
, error
);
1095 if (!is_ok (error
)) {
1099 mono_mb_emit_managed_call (mb
, remoting_invoke_method
, NULL
);
1100 mono_mb_emit_byte (mb
, CEE_RET
);
1101 mono_mb_patch_short_branch (mb
, pos_dispatch
);
1103 /* Create the array that will hold the parameters to be serialized */
1105 if (complex_count
> 0) {
1106 mono_mb_emit_icon (mb
, (ret_marshal_type
== MONO_MARSHAL_SERIALIZE
&& complex_out_count
> 0) ? complex_count
+ 1 : complex_count
); /* +1 for the return type */
1107 mono_mb_emit_op (mb
, CEE_NEWARR
, mono_defaults
.object_class
);
1110 for (i
= 0; i
< sig
->param_count
; i
++) {
1112 if (marshal_types
[i
] != MONO_MARSHAL_SERIALIZE
) continue;
1113 pclass
= mono_class_from_mono_type_internal (sig
->params
[i
]);
1114 mono_mb_emit_byte (mb
, CEE_DUP
);
1115 mono_mb_emit_icon (mb
, j
);
1116 mono_mb_emit_ldarg (mb
, i
+ 1); /* 0=this */
1117 if (sig
->params
[i
]->byref
) {
1118 if (m_class_is_valuetype (pclass
))
1119 mono_mb_emit_op (mb
, CEE_LDOBJ
, pclass
);
1121 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1123 if (m_class_is_valuetype (pclass
))
1124 mono_mb_emit_op (mb
, CEE_BOX
, pclass
);
1125 mono_mb_emit_byte (mb
, CEE_STELEM_REF
);
1128 mono_mb_emit_stloc (mb
, loc_array
);
1130 /* Serialize parameters */
1132 mono_mb_emit_ldloc (mb
, loc_array
);
1133 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
1134 mono_mb_emit_stloc (mb
, loc_serialized_data
);
1136 mono_mb_emit_byte (mb
, CEE_LDNULL
);
1137 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
1138 mono_mb_emit_stloc (mb
, loc_serialized_data
);
1143 mono_mb_emit_ldloc (mb
, loc_domainid
);
1144 mono_mb_emit_byte (mb
, CEE_LDC_I4_1
);
1145 mono_marshal_emit_switch_domain (mb
);
1146 mono_mb_emit_stloc (mb
, loc_old_domainid
);
1148 /* Load the arguments */
1150 mono_mb_emit_ldloc (mb
, loc_real_proxy
);
1151 mono_mb_emit_ldloc_addr (mb
, loc_serialized_data
);
1152 mono_mb_emit_ldloc_addr (mb
, loc_serialized_exc
);
1154 copy_locals_base
= mb
->locals
;
1155 for (i
= 0; i
< sig
->param_count
; i
++) {
1156 switch (marshal_types
[i
]) {
1157 case MONO_MARSHAL_SERIALIZE
:
1159 case MONO_MARSHAL_COPY
: {
1160 mono_mb_emit_ldarg (mb
, i
+1);
1161 if (sig
->params
[i
]->byref
) {
1162 /* make a local copy of the byref parameter. The real parameter
1163 * will be updated after the xdomain call
1165 MonoClass
*pclass
= mono_class_from_mono_type_internal (sig
->params
[i
]);
1166 int copy_local
= mono_mb_add_local (mb
, m_class_get_byval_arg (pclass
));
1167 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1168 mono_mb_emit_stloc (mb
, copy_local
);
1169 mono_mb_emit_ldloc_addr (mb
, copy_local
);
1173 case MONO_MARSHAL_COPY_OUT
:
1174 case MONO_MARSHAL_NONE
:
1175 mono_mb_emit_ldarg (mb
, i
+1);
1180 /* Make the call to the invoke wrapper in the target domain */
1182 xdomain_method
= mono_marshal_get_xappdomain_dispatch (method
, marshal_types
, complex_count
, complex_out_count
, ret_marshal_type
);
1183 mono_marshal_emit_load_domain_method (mb
, xdomain_method
);
1184 mono_mb_emit_calli (mb
, mono_method_signature_internal (xdomain_method
));
1187 mono_mb_emit_stloc (mb
, loc_return
);
1191 mono_mb_emit_ldloc (mb
, loc_old_domainid
);
1192 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
1193 mono_marshal_emit_switch_domain (mb
);
1194 mono_mb_emit_byte (mb
, CEE_POP
);
1196 /* Restore thread domain data */
1198 mono_mb_emit_ldloc (mb
, loc_context
);
1199 mono_mb_emit_icall (mb
, mono_context_set_icall
);
1201 /* if (loc_serialized_exc != null) ... */
1203 mono_mb_emit_ldloc (mb
, loc_serialized_exc
);
1204 pos_noex
= mono_mb_emit_short_branch (mb
, CEE_BRFALSE_S
);
1206 mono_mb_emit_ldloc (mb
, loc_serialized_exc
);
1207 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
1208 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
1209 mono_mb_emit_op (mb
, CEE_CASTCLASS
, mono_defaults
.exception_class
);
1210 mono_mb_emit_managed_call (mb
, method_exc_fixexc
, NULL
);
1211 mono_mb_emit_byte (mb
, CEE_THROW
);
1212 mono_mb_patch_short_branch (mb
, pos_noex
);
1214 /* copy back non-serialized output parameters */
1217 for (i
= 0; i
< sig
->param_count
; i
++) {
1218 if (!sig
->params
[i
]->byref
|| marshal_types
[i
] != MONO_MARSHAL_COPY
) continue;
1219 mono_mb_emit_ldarg (mb
, i
+ 1);
1220 mono_mb_emit_ldloc (mb
, copy_locals_base
+ (j
++));
1221 mono_marshal_emit_xdomain_copy_value (mb
, mono_class_from_mono_type_internal (sig
->params
[i
]));
1222 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
1225 /* Deserialize out parameters */
1227 if (complex_out_count
> 0) {
1228 mono_mb_emit_ldloc (mb
, loc_serialized_data
);
1229 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
1230 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
1231 mono_mb_emit_stloc (mb
, loc_array
);
1233 /* Copy back output parameters and return type */
1236 for (i
= 0; i
< sig
->param_count
; i
++) {
1237 if (marshal_types
[i
] != MONO_MARSHAL_SERIALIZE
) continue;
1238 if (sig
->params
[i
]->byref
) {
1239 MonoClass
*pclass
= mono_class_from_mono_type_internal (sig
->params
[i
]);
1240 mono_mb_emit_ldarg (mb
, i
+ 1);
1241 mono_mb_emit_ldloc (mb
, loc_array
);
1242 mono_mb_emit_icon (mb
, j
);
1243 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
1244 if (m_class_is_valuetype (pclass
)) {
1245 mono_mb_emit_op (mb
, CEE_UNBOX
, pclass
);
1246 mono_mb_emit_op (mb
, CEE_LDOBJ
, pclass
);
1247 mono_mb_emit_op (mb
, CEE_STOBJ
, pclass
);
1249 if (pclass
!= mono_defaults
.object_class
)
1250 mono_mb_emit_op (mb
, CEE_CASTCLASS
, pclass
);
1251 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
1257 if (ret_marshal_type
== MONO_MARSHAL_SERIALIZE
) {
1258 mono_mb_emit_ldloc (mb
, loc_array
);
1259 mono_mb_emit_icon (mb
, complex_count
);
1260 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
1261 if (m_class_is_valuetype (ret_class
)) {
1262 mono_mb_emit_op (mb
, CEE_UNBOX
, ret_class
);
1263 mono_mb_emit_op (mb
, CEE_LDOBJ
, ret_class
);
1266 } else if (ret_marshal_type
== MONO_MARSHAL_SERIALIZE
) {
1267 mono_mb_emit_ldloc (mb
, loc_serialized_data
);
1268 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
1269 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
1270 if (m_class_is_valuetype (ret_class
)) {
1271 mono_mb_emit_op (mb
, CEE_UNBOX
, ret_class
);
1272 mono_mb_emit_op (mb
, CEE_LDOBJ
, ret_class
);
1273 } else if (ret_class
!= mono_defaults
.object_class
) {
1274 mono_mb_emit_op (mb
, CEE_CASTCLASS
, ret_class
);
1277 mono_mb_emit_ldloc (mb
, loc_serialized_data
);
1278 mono_mb_emit_byte (mb
, CEE_DUP
);
1279 pos
= mono_mb_emit_short_branch (mb
, CEE_BRFALSE_S
);
1280 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
1282 mono_mb_patch_short_branch (mb
, pos
);
1283 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
1284 mono_mb_emit_byte (mb
, CEE_POP
);
1288 mono_mb_emit_ldloc (mb
, loc_return
);
1289 if (ret_marshal_type
== MONO_MARSHAL_COPY
)
1290 mono_marshal_emit_xdomain_copy_value (mb
, ret_class
);
1293 mono_mb_emit_byte (mb
, CEE_RET
);
1294 #endif /* DISABLE_JIT */
1296 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1297 info
->d
.remoting
.method
= method
;
1298 res
= mono_remoting_mb_create_and_cache (method
, mb
, sig
, sig
->param_count
+ 16, info
);
1305 * mono_marshal_get_remoting_invoke_for_target:
1308 mono_marshal_get_remoting_invoke_for_target (MonoMethod
*method
, MonoRemotingTarget target_type
, MonoError
*error
)
1311 if (target_type
== MONO_REMOTING_TARGET_APPDOMAIN
) {
1312 return mono_marshal_get_xappdomain_invoke (method
, error
);
1313 } else if (target_type
== MONO_REMOTING_TARGET_COMINTEROP
) {
1315 return mono_cominterop_get_invoke (method
);
1317 g_assert_not_reached ();
1320 return mono_marshal_get_remoting_invoke (method
, error
);
1326 G_GNUC_UNUSED
static gpointer
1327 mono_marshal_load_remoting_wrapper (MonoRealProxy
*rp
, MonoMethod
*method
)
1330 MonoMethod
*marshal_method
= NULL
;
1331 if (rp
->target_domain_id
!= -1)
1332 marshal_method
= mono_marshal_get_xappdomain_invoke (method
, error
);
1334 marshal_method
= mono_marshal_get_remoting_invoke (method
, error
);
1335 mono_error_assert_ok (error
);
1336 gpointer compiled_ptr
= mono_compile_method_checked (marshal_method
, error
);
1337 mono_error_assert_ok (error
);
1338 return compiled_ptr
;
1342 * mono_marshal_get_remoting_invoke_with_check:
1345 mono_marshal_get_remoting_invoke_with_check (MonoMethod
*method
, MonoError
*error
)
1347 MonoMethodSignature
*sig
;
1348 MonoMethodBuilder
*mb
;
1349 MonoMethod
*res
, *native
;
1351 int i
, pos
, pos_rem
;
1356 if (method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
)
1359 /* we cant remote methods without this pointer */
1360 g_assert (mono_method_signature_internal (method
)->hasthis
);
1362 if ((res
= mono_marshal_remoting_find_in_cache (method
, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
)))
1365 sig
= mono_signature_no_pinvoke (method
);
1367 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
);
1370 for (i
= 0; i
<= sig
->param_count
; i
++)
1371 mono_mb_emit_ldarg (mb
, i
);
1373 mono_mb_emit_ldarg (mb
, 0);
1374 pos
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
1376 if (mono_marshal_supports_fast_xdomain (method
)) {
1377 mono_mb_emit_ldarg (mb
, 0);
1378 pos_rem
= mono_mb_emit_xdomain_check (mb
, CEE_BEQ
);
1380 /* wrapper for cross app domain calls */
1381 native
= mono_marshal_get_xappdomain_invoke (method
, error
);
1382 if (!is_ok (error
)) {
1386 mono_mb_emit_managed_call (mb
, native
, mono_method_signature_internal (native
));
1387 mono_mb_emit_byte (mb
, CEE_RET
);
1389 mono_mb_patch_branch (mb
, pos_rem
);
1391 /* wrapper for normal remote calls */
1392 native
= mono_marshal_get_remoting_invoke (method
, error
);
1393 if (!is_ok (error
)) {
1397 mono_mb_emit_managed_call (mb
, native
, mono_method_signature_internal (native
));
1398 mono_mb_emit_byte (mb
, CEE_RET
);
1401 mono_mb_patch_branch (mb
, pos
);
1402 mono_mb_emit_managed_call (mb
, method
, mono_method_signature_internal (method
));
1403 mono_mb_emit_byte (mb
, CEE_RET
);
1406 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1407 info
->d
.remoting
.method
= method
;
1408 res
= mono_remoting_mb_create_and_cache (method
, mb
, sig
, sig
->param_count
+ 16, info
);
1415 * mono_marshal_get_ldfld_wrapper:
1416 * \param type the type of the field
1418 * This method generates a function which can be use to load a field with type
1419 * \p type from an object. The generated function has the following signature:
1421 * <code><i>type</i> ldfld_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset)</code>
1424 mono_marshal_get_ldfld_wrapper (MonoType
*type
)
1426 MonoMethodSignature
*sig
;
1427 MonoMethodBuilder
*mb
;
1433 int t
, pos0
, pos1
= 0;
1434 static MonoMethod
* tp_load
= NULL
;
1436 type
= mono_type_get_underlying_type (type
);
1441 if (type
->type
== MONO_TYPE_SZARRAY
) {
1442 klass
= mono_defaults
.array_class
;
1443 } else if (type
->type
== MONO_TYPE_VALUETYPE
) {
1444 klass
= type
->data
.klass
;
1445 } else if (t
== MONO_TYPE_OBJECT
|| t
== MONO_TYPE_CLASS
|| t
== MONO_TYPE_STRING
) {
1446 klass
= mono_defaults
.object_class
;
1447 } else if (t
== MONO_TYPE_PTR
|| t
== MONO_TYPE_FNPTR
) {
1448 klass
= mono_defaults
.int_class
;
1449 } else if (t
== MONO_TYPE_GENERICINST
) {
1450 if (mono_type_generic_inst_is_valuetype (type
))
1451 klass
= mono_class_from_mono_type_internal (type
);
1453 klass
= mono_defaults
.object_class
;
1455 klass
= mono_class_from_mono_type_internal (type
);
1458 klass
= mono_defaults
.int_class
;
1461 cache
= get_cache (&m_class_get_image (klass
)->ldfld_wrapper_cache
, mono_aligned_addr_hash
, NULL
);
1462 if ((res
= mono_marshal_find_in_cache (cache
, klass
)))
1465 #ifndef DISABLE_REMOTING
1468 tp_load
= mono_class_get_method_from_name_checked (mono_defaults
.transparent_proxy_class
, "LoadRemoteFieldNew", -1, 0, error
);
1469 mono_error_assert_ok (error
);
1470 g_assert (tp_load
!= NULL
);
1474 /* we add the %p pointer value of klass because class names are not unique */
1475 name
= g_strdup_printf ("__ldfld_wrapper_%p_%s.%s", klass
, m_class_get_name_space (klass
), m_class_get_name (klass
));
1476 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_LDFLD
);
1479 MonoType
*object_type
= mono_get_object_type ();
1480 MonoType
*int_type
= mono_get_int_type ();
1481 sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 4);
1482 sig
->params
[0] = object_type
;
1483 sig
->params
[1] = int_type
;
1484 sig
->params
[2] = int_type
;
1485 sig
->params
[3] = int_type
;
1486 sig
->ret
= m_class_get_byval_arg (klass
);
1489 mono_mb_emit_ldarg (mb
, 0);
1490 pos0
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
1492 #ifndef DISABLE_REMOTING
1493 mono_mb_emit_ldarg (mb
, 0);
1494 mono_mb_emit_ldarg (mb
, 1);
1495 mono_mb_emit_ldarg (mb
, 2);
1497 mono_mb_emit_managed_call (mb
, tp_load
, NULL
);
1500 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
1501 csig->params [0] = mono_get_object_type ();
1502 csig->params [1] = mono_get_int_type ();
1503 csig->params [2] = mono_get_int_type ();
1504 csig->ret = m_class_get_this_arg (klass);
1507 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
1508 mono_marshal_emit_thread_interrupt_checkpoint (mb);
1511 if (m_class_is_valuetype (klass
)) {
1512 mono_mb_emit_op (mb
, CEE_UNBOX
, klass
);
1513 pos1
= mono_mb_emit_branch (mb
, CEE_BR
);
1515 mono_mb_emit_byte (mb
, CEE_RET
);
1519 mono_mb_patch_branch (mb
, pos0
);
1521 mono_mb_emit_ldarg (mb
, 0);
1522 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1523 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
1524 mono_mb_emit_ldarg (mb
, 3);
1525 mono_mb_emit_byte (mb
, CEE_ADD
);
1527 if (m_class_is_valuetype (klass
))
1528 mono_mb_patch_branch (mb
, pos1
);
1533 case MONO_TYPE_BOOLEAN
:
1534 case MONO_TYPE_CHAR
:
1543 case MONO_TYPE_ARRAY
:
1544 case MONO_TYPE_SZARRAY
:
1545 case MONO_TYPE_OBJECT
:
1546 case MONO_TYPE_CLASS
:
1547 case MONO_TYPE_STRING
:
1551 case MONO_TYPE_FNPTR
:
1552 mono_mb_emit_byte (mb
, mono_type_to_ldind (type
));
1554 case MONO_TYPE_VALUETYPE
:
1555 g_assert (!m_class_is_enumtype (klass
));
1556 mono_mb_emit_op (mb
, CEE_LDOBJ
, klass
);
1558 case MONO_TYPE_GENERICINST
:
1559 if (mono_type_generic_inst_is_valuetype (type
)) {
1560 mono_mb_emit_op (mb
, CEE_LDOBJ
, klass
);
1562 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1566 case MONO_TYPE_MVAR
:
1567 mono_mb_emit_op (mb
, CEE_LDOBJ
, klass
);
1570 g_warning ("type %x not implemented", type
->type
);
1571 g_assert_not_reached ();
1574 mono_mb_emit_byte (mb
, CEE_RET
);
1575 #endif /* DISABLE_JIT */
1577 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1578 info
->d
.proxy
.klass
= klass
;
1579 res
= mono_mb_create_and_cache_full (cache
, klass
,
1580 mb
, sig
, sig
->param_count
+ 16, info
, NULL
);
1587 * mono_marshal_get_ldflda_wrapper:
1588 * @type: the type of the field
1590 * This method generates a function which can be used to load a field address
1591 * from an object. The generated function has the following signature:
1592 * gpointer ldflda_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset);
1595 mono_marshal_get_ldflda_wrapper (MonoType
*type
)
1597 MonoMethodSignature
*sig
;
1598 MonoMethodBuilder
*mb
;
1604 int t
, pos0
, pos1
, pos2
, pos3
;
1606 type
= mono_type_get_underlying_type (type
);
1610 if (type
->type
== MONO_TYPE_SZARRAY
) {
1611 klass
= mono_defaults
.array_class
;
1612 } else if (type
->type
== MONO_TYPE_VALUETYPE
) {
1613 klass
= type
->data
.klass
;
1614 } else if (t
== MONO_TYPE_OBJECT
|| t
== MONO_TYPE_CLASS
|| t
== MONO_TYPE_STRING
) {
1615 klass
= mono_defaults
.object_class
;
1616 } else if (t
== MONO_TYPE_PTR
|| t
== MONO_TYPE_FNPTR
) {
1617 klass
= mono_defaults
.int_class
;
1618 } else if (t
== MONO_TYPE_GENERICINST
) {
1619 if (mono_type_generic_inst_is_valuetype (type
))
1620 klass
= mono_class_from_mono_type_internal (type
);
1622 klass
= mono_defaults
.object_class
;
1624 klass
= mono_class_from_mono_type_internal (type
);
1627 klass
= mono_defaults
.int_class
;
1630 cache
= get_cache (&m_class_get_image (klass
)->ldflda_wrapper_cache
, mono_aligned_addr_hash
, NULL
);
1631 if ((res
= mono_marshal_find_in_cache (cache
, klass
)))
1634 mono_remoting_marshal_init ();
1636 /* we add the %p pointer value of klass because class names are not unique */
1637 name
= g_strdup_printf ("__ldflda_wrapper_%p_%s.%s", klass
, m_class_get_name_space (klass
), m_class_get_name (klass
));
1638 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_LDFLDA
);
1641 MonoType
*object_type
= mono_get_object_type ();
1642 MonoType
*int_type
= mono_get_int_type ();
1643 sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 4);
1644 sig
->params
[0] = object_type
;
1645 sig
->params
[1] = int_type
;
1646 sig
->params
[2] = int_type
;
1647 sig
->params
[3] = int_type
;
1648 sig
->ret
= int_type
;
1651 /* if typeof (this) != transparent_proxy goto pos0 */
1652 mono_mb_emit_ldarg (mb
, 0);
1653 pos0
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
1655 /* if same_appdomain goto pos1 */
1656 mono_mb_emit_ldarg (mb
, 0);
1657 pos1
= mono_mb_emit_xdomain_check (mb
, CEE_BEQ
);
1659 mono_mb_emit_exception_full (mb
, "System", "InvalidOperationException", "Attempt to load field address from object in another appdomain.");
1661 /* same app domain */
1662 mono_mb_patch_branch (mb
, pos1
);
1664 /* if typeof (this) != contextbound goto pos2 */
1665 mono_mb_emit_ldarg (mb
, 0);
1666 pos2
= mono_mb_emit_contextbound_check (mb
, CEE_BEQ
);
1668 /* if this->rp->context == mono_context_get goto pos3 */
1669 mono_mb_emit_ldarg (mb
, 0);
1670 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
1671 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1672 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRealProxy
, context
));
1673 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1674 mono_mb_emit_icall (mb
, mono_context_get_icall
);
1675 pos3
= mono_mb_emit_branch (mb
, CEE_BEQ
);
1677 mono_mb_emit_exception_full (mb
, "System", "InvalidOperationException", "Attempt to load field address from object in another context.");
1679 mono_mb_patch_branch (mb
, pos2
);
1680 mono_mb_patch_branch (mb
, pos3
);
1682 /* return the address of the field from this->rp->unwrapped_server */
1683 mono_mb_emit_ldarg (mb
, 0);
1684 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
1685 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1686 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRealProxy
, unwrapped_server
));
1687 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1688 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1689 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
1690 mono_mb_emit_ldarg (mb
, 3);
1691 mono_mb_emit_byte (mb
, CEE_ADD
);
1692 mono_mb_emit_byte (mb
, CEE_RET
);
1694 /* not a proxy: return the address of the field directly */
1695 mono_mb_patch_branch (mb
, pos0
);
1697 mono_mb_emit_ldarg (mb
, 0);
1698 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1699 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
1700 mono_mb_emit_ldarg (mb
, 3);
1701 mono_mb_emit_byte (mb
, CEE_ADD
);
1703 mono_mb_emit_byte (mb
, CEE_RET
);
1706 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1707 info
->d
.proxy
.klass
= klass
;
1708 res
= mono_mb_create_and_cache_full (cache
, klass
,
1709 mb
, sig
, sig
->param_count
+ 16,
1718 * mono_marshal_get_stfld_wrapper:
1719 * \param type the type of the field
1721 * This method generates a function which can be use to store a field with type
1722 * \p type. The generated function has the following signature:
1724 * <code>void stfld_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset, <i>type</i> val)</code>
1727 mono_marshal_get_stfld_wrapper (MonoType
*type
)
1729 MonoMethodSignature
*sig
;
1730 MonoMethodBuilder
*mb
;
1737 static MonoMethod
*tp_store
= NULL
;
1739 type
= mono_type_get_underlying_type (type
);
1743 if (type
->type
== MONO_TYPE_SZARRAY
) {
1744 klass
= mono_defaults
.array_class
;
1745 } else if (type
->type
== MONO_TYPE_VALUETYPE
) {
1746 klass
= type
->data
.klass
;
1747 } else if (t
== MONO_TYPE_OBJECT
|| t
== MONO_TYPE_CLASS
|| t
== MONO_TYPE_STRING
) {
1748 klass
= mono_defaults
.object_class
;
1749 } else if (t
== MONO_TYPE_PTR
|| t
== MONO_TYPE_FNPTR
) {
1750 klass
= mono_defaults
.int_class
;
1751 } else if (t
== MONO_TYPE_GENERICINST
) {
1752 if (mono_type_generic_inst_is_valuetype (type
))
1753 klass
= mono_class_from_mono_type_internal (type
);
1755 klass
= mono_defaults
.object_class
;
1757 klass
= mono_class_from_mono_type_internal (type
);
1760 klass
= mono_defaults
.int_class
;
1763 cache
= get_cache (&m_class_get_image (klass
)->stfld_wrapper_cache
, mono_aligned_addr_hash
, NULL
);
1764 if ((res
= mono_marshal_find_in_cache (cache
, klass
)))
1767 #ifndef DISABLE_REMOTING
1770 tp_store
= mono_class_get_method_from_name_checked (mono_defaults
.transparent_proxy_class
, "StoreRemoteField", -1, 0, error
);
1771 mono_error_assert_ok (error
);
1772 g_assert (tp_store
!= NULL
);
1776 /* we add the %p pointer value of klass because class names are not unique */
1777 name
= g_strdup_printf ("__stfld_wrapper_%p_%s.%s", klass
, m_class_get_name_space (klass
), m_class_get_name (klass
));
1778 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_STFLD
);
1782 MonoType
*object_type
= mono_get_object_type ();
1783 MonoType
*int_type
= mono_get_int_type ();
1784 MonoType
*void_type
= mono_get_void_type ();
1785 sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 5);
1786 sig
->params
[0] = object_type
;
1787 sig
->params
[1] = int_type
;
1788 sig
->params
[2] = int_type
;
1789 sig
->params
[3] = int_type
;
1790 sig
->params
[4] = m_class_get_byval_arg (klass
);
1791 sig
->ret
= void_type
;
1794 mono_mb_emit_ldarg (mb
, 0);
1795 pos
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
1797 #ifndef DISABLE_REMOTING
1798 mono_mb_emit_ldarg (mb
, 0);
1799 mono_mb_emit_ldarg (mb
, 1);
1800 mono_mb_emit_ldarg (mb
, 2);
1801 mono_mb_emit_ldarg (mb
, 4);
1802 if (m_class_is_valuetype (klass
))
1803 mono_mb_emit_op (mb
, CEE_BOX
, klass
);
1805 mono_mb_emit_managed_call (mb
, tp_store
, NULL
);
1807 mono_mb_emit_byte (mb
, CEE_RET
);
1810 mono_mb_patch_branch (mb
, pos
);
1812 mono_mb_emit_ldarg (mb
, 0);
1813 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1814 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
1815 mono_mb_emit_ldarg (mb
, 3);
1816 mono_mb_emit_byte (mb
, CEE_ADD
);
1817 mono_mb_emit_ldarg (mb
, 4);
1822 case MONO_TYPE_BOOLEAN
:
1823 case MONO_TYPE_CHAR
:
1832 case MONO_TYPE_ARRAY
:
1833 case MONO_TYPE_SZARRAY
:
1834 case MONO_TYPE_OBJECT
:
1835 case MONO_TYPE_CLASS
:
1836 case MONO_TYPE_STRING
:
1840 case MONO_TYPE_FNPTR
:
1841 mono_mb_emit_byte (mb
, mono_type_to_stind (type
));
1843 case MONO_TYPE_VALUETYPE
:
1844 g_assert (!m_class_is_enumtype (klass
));
1845 mono_mb_emit_op (mb
, CEE_STOBJ
, klass
);
1847 case MONO_TYPE_GENERICINST
:
1849 case MONO_TYPE_MVAR
:
1850 mono_mb_emit_op (mb
, CEE_STOBJ
, klass
);
1853 g_warning ("type %x not implemented", type
->type
);
1854 g_assert_not_reached ();
1857 mono_mb_emit_byte (mb
, CEE_RET
);
1860 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1861 info
->d
.proxy
.klass
= klass
;
1862 res
= mono_mb_create_and_cache_full (cache
, klass
,
1863 mb
, sig
, sig
->param_count
+ 16,
1871 * mono_marshal_get_proxy_cancast:
1874 mono_marshal_get_proxy_cancast (MonoClass
*klass
)
1876 static MonoMethodSignature
*isint_sig
= NULL
;
1880 int pos_failed
, pos_end
;
1881 char *name
, *klass_name
;
1882 MonoMethod
*can_cast_to
;
1883 MonoMethodDesc
*desc
;
1884 MonoMethodBuilder
*mb
;
1886 cache
= get_cache (&m_class_get_image (klass
)->proxy_isinst_cache
, mono_aligned_addr_hash
, NULL
);
1887 if ((res
= mono_marshal_find_in_cache (cache
, klass
)))
1891 isint_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 1);
1892 isint_sig
->params
[0] = mono_get_object_type ();
1893 isint_sig
->ret
= mono_get_object_type ();
1894 isint_sig
->pinvoke
= 0;
1897 klass_name
= mono_type_full_name (m_class_get_byval_arg (klass
));
1898 name
= g_strdup_printf ("__proxy_isinst_wrapper_%s", klass_name
);
1899 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_PROXY_ISINST
);
1900 g_free (klass_name
);
1903 mb
->method
->save_lmf
= 1;
1906 /* get the real proxy from the transparent proxy*/
1907 mono_mb_emit_ldarg (mb
, 0);
1908 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
1909 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1911 /* get the reflection type from the type handle */
1912 mono_mb_emit_ptr (mb
, m_class_get_byval_arg (klass
));
1913 mono_mb_emit_icall (mb
, type_from_handle
);
1915 mono_mb_emit_ldarg (mb
, 0);
1917 /* make the call to CanCastTo (type, ob) */
1918 desc
= mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE
);
1919 can_cast_to
= mono_method_desc_search_in_class (desc
, mono_defaults
.iremotingtypeinfo_class
);
1920 g_assert (can_cast_to
);
1921 mono_method_desc_free (desc
);
1922 mono_mb_emit_op (mb
, CEE_CALLVIRT
, can_cast_to
);
1924 pos_failed
= mono_mb_emit_branch (mb
, CEE_BRFALSE
);
1926 /* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
1927 mono_mb_emit_ptr (mb
, m_class_get_byval_arg (klass
));
1928 mono_mb_emit_icall (mb
, type_from_handle
);
1929 mono_mb_emit_ldarg (mb
, 0);
1931 mono_mb_emit_icall (mb
, mono_upgrade_remote_class_wrapper
);
1932 mono_marshal_emit_thread_interrupt_checkpoint (mb
);
1934 mono_mb_emit_ldarg (mb
, 0);
1935 pos_end
= mono_mb_emit_branch (mb
, CEE_BR
);
1939 mono_mb_patch_branch (mb
, pos_failed
);
1940 mono_mb_emit_byte (mb
, CEE_LDNULL
);
1944 mono_mb_patch_branch (mb
, pos_end
);
1945 mono_mb_emit_byte (mb
, CEE_RET
);
1948 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1949 info
->d
.proxy
.klass
= klass
;
1950 res
= mono_mb_create_and_cache_full (cache
, klass
, mb
, isint_sig
, isint_sig
->param_count
+ 16, info
, NULL
);
1957 mono_upgrade_remote_class_wrapper (MonoReflectionType
*rtype_raw
, MonoTransparentProxy
*tproxy_raw
)
1960 MONO_HANDLE_DCL (MonoReflectionType
, rtype
);
1961 MONO_HANDLE_DCL (MonoTransparentProxy
, tproxy
);
1962 MonoDomain
*domain
= MONO_HANDLE_DOMAIN (tproxy
);
1963 MonoClass
*klass
= mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (rtype
, type
));
1964 mono_upgrade_remote_class (domain
, MONO_HANDLE_CAST (MonoObject
, tproxy
), klass
, error
);
1968 #else /* DISABLE_REMOTING */
1971 mono_remoting_init (void)
1975 #endif /* DISABLE_REMOTING */
1977 /* mono_get_xdomain_marshal_type()
1978 * Returns the kind of marshalling that a type needs for cross domain calls.
1980 static MonoXDomainMarshalType
1981 mono_get_xdomain_marshal_type (MonoType
*t
)
1984 case MONO_TYPE_VOID
:
1985 g_assert_not_reached ();
1989 case MONO_TYPE_BOOLEAN
:
1992 case MONO_TYPE_CHAR
:
1999 return MONO_MARSHAL_NONE
;
2000 case MONO_TYPE_STRING
:
2001 return MONO_MARSHAL_COPY
;
2002 case MONO_TYPE_ARRAY
:
2003 case MONO_TYPE_SZARRAY
: {
2004 MonoClass
*elem_class
= m_class_get_element_class (mono_class_from_mono_type_internal (t
));
2005 if (mono_get_xdomain_marshal_type (m_class_get_byval_arg (elem_class
)) != MONO_MARSHAL_SERIALIZE
)
2006 return MONO_MARSHAL_COPY
;
2012 return MONO_MARSHAL_SERIALIZE
;
2015 /* Replace the given array element by a copy in the current domain */
2017 xdomain_copy_array_element_inplace (MonoArrayHandle arr
, int i
, MonoError
*error
)
2019 HANDLE_FUNCTION_ENTER ();
2021 MonoObjectHandle item
= MONO_HANDLE_NEW (MonoObject
, NULL
);
2022 MONO_HANDLE_ARRAY_GETREF (item
, arr
, i
);
2024 MonoObjectHandle item_copy
= mono_marshal_xdomain_copy_value_handle (item
, error
);
2025 goto_if_nok (error
, leave
);
2026 MONO_HANDLE_ARRAY_SETREF (arr
, i
, item_copy
);
2028 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
2032 * mono_marshal_xdomain_copy_value_handle:
2033 * \param val The value to copy.
2034 * \param error set on failure.
2035 * Makes a copy of \p val suitable for the current domain.
2036 * On failure returns NULL and sets \p error.
2039 mono_marshal_xdomain_copy_value_handle (MonoObjectHandle val
, MonoError
*error
)
2042 MonoObjectHandle result
= MONO_HANDLE_NEW (MonoObject
, NULL
);
2043 if (MONO_HANDLE_IS_NULL (val
))
2047 domain
= mono_domain_get ();
2050 klass
= mono_handle_class (val
);
2052 switch (m_class_get_byval_arg (klass
)->type
) {
2053 case MONO_TYPE_VOID
:
2054 g_assert_not_reached ();
2058 case MONO_TYPE_BOOLEAN
:
2061 case MONO_TYPE_CHAR
:
2067 case MONO_TYPE_R8
: {
2068 uint32_t gchandle
= mono_gchandle_from_handle (val
, TRUE
);
2069 MonoObjectHandle res
= MONO_HANDLE_NEW (MonoObject
, mono_value_box_checked (domain
, klass
, ((char*)MONO_HANDLE_RAW (val
)) + sizeof(MonoObject
), error
)); /* FIXME use handles in mono_value_box_checked */
2070 mono_gchandle_free_internal (gchandle
);
2071 goto_if_nok (error
, leave
);
2072 MONO_HANDLE_ASSIGN (result
, res
);
2075 case MONO_TYPE_STRING
: {
2076 MonoStringHandle str
= MONO_HANDLE_CAST (MonoString
, val
);
2077 uint32_t gchandle
= mono_gchandle_from_handle (val
, TRUE
);
2078 MonoStringHandle res
= mono_string_new_utf16_handle (domain
, mono_string_chars_internal (MONO_HANDLE_RAW (str
)), mono_string_handle_length (str
), error
);
2079 mono_gchandle_free_internal (gchandle
);
2080 goto_if_nok (error
, leave
);
2081 MONO_HANDLE_ASSIGN (result
, res
);
2084 case MONO_TYPE_ARRAY
:
2085 case MONO_TYPE_SZARRAY
: {
2086 MonoArrayHandle arr
= MONO_HANDLE_CAST (MonoArray
, val
);
2087 MonoXDomainMarshalType mt
= mono_get_xdomain_marshal_type (m_class_get_byval_arg (m_class_get_element_class (klass
)));
2088 if (mt
== MONO_MARSHAL_SERIALIZE
)
2090 MonoArrayHandle acopy
= mono_array_clone_in_domain (domain
, arr
, error
);
2091 goto_if_nok (error
, leave
);
2093 if (mt
== MONO_MARSHAL_COPY
) {
2094 int i
, len
= mono_array_handle_length (acopy
);
2095 for (i
= 0; i
< len
; i
++) {
2096 if (!xdomain_copy_array_element_inplace (acopy
, i
, error
))
2100 MONO_HANDLE_ASSIGN (result
, acopy
);
2111 /* mono_marshal_xdomain_copy_value
2112 * Makes a copy of "val" suitable for the current domain.
2115 mono_marshal_xdomain_copy_value (MonoObject
* val_raw
, MonoError
*error
)
2117 HANDLE_FUNCTION_ENTER ();
2118 /* FIXME callers of mono_marshal_xdomain_copy_value should use handles */
2119 MONO_HANDLE_DCL (MonoObject
, val
);
2120 MonoObjectHandle result
= mono_marshal_xdomain_copy_value_handle (val
, error
);
2121 HANDLE_FUNCTION_RETURN_OBJ (result
);
2124 /* mono_marshal_xdomain_copy_value
2125 * Makes a copy of "val" suitable for the current domain.
2128 ves_icall_mono_marshal_xdomain_copy_value_impl (MonoObjectHandle val
, MonoError
*error
)
2130 return mono_marshal_xdomain_copy_value_handle (val
, error
);
2134 mono_context_set_icall (MonoAppContext
*new_context_raw
)
2136 HANDLE_FUNCTION_ENTER ();
2137 MONO_HANDLE_DCL (MonoAppContext
, new_context
);
2138 mono_context_set_handle (new_context
);
2139 HANDLE_FUNCTION_RETURN ();
2142 static MonoAppContext
*
2143 mono_context_get_icall (void)
2145 HANDLE_FUNCTION_ENTER ();
2146 MonoAppContextHandle context
= mono_context_get_handle ();
2147 HANDLE_FUNCTION_RETURN_OBJ (context
);