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"
29 MONO_MARSHAL_NONE
, /* No marshalling needed */
30 MONO_MARSHAL_COPY
, /* Can be copied by value to the new domain */
31 MONO_MARSHAL_COPY_OUT
, /* out parameter that needs to be copied back to the original instance */
32 MONO_MARSHAL_SERIALIZE
/* Value needs to be serialized into the new domain */
33 } MonoXDomainMarshalType
;
35 #ifndef DISABLE_REMOTING
37 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
41 #include "mono/cil/opcode.def"
46 struct _MonoRemotingMethods
{
48 MonoMethod
*invoke_with_check
;
49 MonoMethod
*xdomain_invoke
;
50 MonoMethod
*xdomain_dispatch
;
53 typedef struct _MonoRemotingMethods MonoRemotingMethods
;
56 mono_remoting_wrapper (MonoMethod
*method
, gpointer
*params
);
58 static MonoException
*
59 mono_remoting_update_exception (MonoException
*exc
);
62 mono_marshal_set_domain_by_id (gint32 id
, MonoBoolean push
);
65 mono_marshal_check_domain_image (gint32 domain_id
, MonoImage
*image
);
68 mono_upgrade_remote_class_wrapper (MonoReflectionType
*rtype
, MonoTransparentProxy
*tproxy
);
70 static MonoXDomainMarshalType
71 mono_get_xdomain_marshal_type (MonoType
*t
);
74 mono_marshal_xdomain_copy_out_value (MonoObject
*src
, MonoObject
*dst
);
76 static MonoReflectionType
*
77 type_from_handle (MonoType
*handle
);
80 mono_context_set_icall (MonoAppContext
*new_context
);
82 static MonoAppContext
*
83 mono_context_get_icall (void);
86 /* Class lazy loading functions */
87 static GENERATE_GET_CLASS_WITH_CACHE (remoting_services
, "System.Runtime.Remoting", "RemotingServices")
88 static GENERATE_GET_CLASS_WITH_CACHE (call_context
, "System.Runtime.Remoting.Messaging", "CallContext")
89 static GENERATE_GET_CLASS_WITH_CACHE (context
, "System.Runtime.Remoting.Contexts", "Context")
91 static mono_mutex_t remoting_mutex
;
92 static gboolean remoting_mutex_inited
;
94 static MonoClass
*byte_array_class
;
96 static MonoMethod
*method_rs_serialize
, *method_rs_deserialize
, *method_exc_fixexc
, *method_rs_appdomain_target
;
97 static MonoMethod
*method_set_call_context
, *method_needs_context_sink
, *method_rs_serialize_exc
;
101 mono_compile_method_icall (MonoMethod
*method
);
104 register_icall (gpointer func
, const char *name
, const char *sigstr
, gboolean save
)
106 MonoMethodSignature
*sig
= mono_create_icall_signature (sigstr
);
108 mono_register_jit_icall (func
, name
, sig
, save
);
114 g_assert (remoting_mutex_inited
);
115 mono_os_mutex_lock (&remoting_mutex
);
119 remoting_unlock (void)
121 g_assert (remoting_mutex_inited
);
122 mono_os_mutex_unlock (&remoting_mutex
);
126 * Return the hash table pointed to by VAR, lazily creating it if neccesary.
129 get_cache (GHashTable
**var
, GHashFunc hash_func
, GCompareFunc equal_func
)
135 g_hash_table_new (hash_func
, equal_func
);
136 mono_memory_barrier ();
145 get_cache_full (GHashTable
**var
, GHashFunc hash_func
, GCompareFunc equal_func
, GDestroyNotify key_destroy_func
, GDestroyNotify value_destroy_func
)
151 g_hash_table_new_full (hash_func
, equal_func
, key_destroy_func
, value_destroy_func
);
152 mono_memory_barrier ();
161 mono_remoting_init (void)
163 mono_os_mutex_init (&remoting_mutex
);
164 remoting_mutex_inited
= TRUE
;
168 mono_remoting_marshal_init (void)
172 static gboolean module_initialized
= FALSE
;
173 static gboolean icalls_registered
= FALSE
;
175 if (module_initialized
)
178 byte_array_class
= mono_class_create_array (mono_defaults
.byte_class
, 1);
181 klass
= mono_class_get_remoting_services_class ();
182 method_rs_serialize
= mono_class_get_method_from_name (klass
, "SerializeCallData", -1);
183 g_assert (method_rs_serialize
);
184 method_rs_deserialize
= mono_class_get_method_from_name (klass
, "DeserializeCallData", -1);
185 g_assert (method_rs_deserialize
);
186 method_rs_serialize_exc
= mono_class_get_method_from_name (klass
, "SerializeExceptionData", -1);
187 g_assert (method_rs_serialize_exc
);
189 klass
= mono_defaults
.real_proxy_class
;
190 method_rs_appdomain_target
= mono_class_get_method_from_name (klass
, "GetAppDomainTarget", -1);
191 g_assert (method_rs_appdomain_target
);
193 klass
= mono_defaults
.exception_class
;
194 method_exc_fixexc
= mono_class_get_method_from_name (klass
, "FixRemotingException", -1);
195 g_assert (method_exc_fixexc
);
197 klass
= mono_class_get_call_context_class ();
198 method_set_call_context
= mono_class_get_method_from_name (klass
, "SetCurrentCallContext", -1);
199 g_assert (method_set_call_context
);
201 klass
= mono_class_get_context_class ();
202 method_needs_context_sink
= mono_class_get_method_from_name (klass
, "get_NeedsContextSink", -1);
203 g_assert (method_needs_context_sink
);
208 if (!icalls_registered
) {
209 register_icall (type_from_handle
, "type_from_handle", "object ptr", FALSE
);
210 register_icall (mono_marshal_set_domain_by_id
, "mono_marshal_set_domain_by_id", "int32 int32 int32", FALSE
);
211 register_icall (mono_marshal_check_domain_image
, "mono_marshal_check_domain_image", "int32 int32 ptr", FALSE
);
212 register_icall (ves_icall_mono_marshal_xdomain_copy_value
, "ves_icall_mono_marshal_xdomain_copy_value", "object object", FALSE
);
213 register_icall (mono_marshal_xdomain_copy_out_value
, "mono_marshal_xdomain_copy_out_value", "void object object", FALSE
);
214 register_icall (mono_remoting_wrapper
, "mono_remoting_wrapper", "object ptr ptr", FALSE
);
215 register_icall (mono_remoting_update_exception
, "mono_remoting_update_exception", "object object", FALSE
);
216 register_icall (mono_upgrade_remote_class_wrapper
, "mono_upgrade_remote_class_wrapper", "void object object", FALSE
);
219 register_icall (mono_compile_method_icall
, "mono_compile_method_icall", "ptr ptr", FALSE
);
222 register_icall (mono_context_get_icall
, "mono_context_get_icall", "object", FALSE
);
223 register_icall (mono_context_set_icall
, "mono_context_set_icall", "void object", FALSE
);
227 icalls_registered
= TRUE
;
229 mono_loader_unlock ();
231 module_initialized
= TRUE
;
234 /* This is an icall, it will return NULL and set pending exception on failure */
235 static MonoReflectionType
*
236 type_from_handle (MonoType
*handle
)
239 MonoReflectionType
*ret
;
240 MonoDomain
*domain
= mono_domain_get ();
241 MonoClass
*klass
= mono_class_from_mono_type (handle
);
243 mono_class_init (klass
);
245 ret
= mono_type_get_object_checked (domain
, handle
, error
);
246 mono_error_set_pending_exception (error
);
253 mono_mb_emit_proxy_check (MonoMethodBuilder
*mb
, int branch_code
)
256 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoObject
, vtable
));
257 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
258 mono_mb_emit_icon (mb
, MONO_STRUCT_OFFSET (MonoVTable
, klass
));
259 mono_mb_emit_byte (mb
, CEE_ADD
);
260 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
261 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
262 mono_mb_emit_byte (mb
, CEE_MONO_CLASSCONST
);
263 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_defaults
.transparent_proxy_class
));
264 pos
= mono_mb_emit_branch (mb
, branch_code
);
269 mono_mb_emit_xdomain_check (MonoMethodBuilder
*mb
, int branch_code
)
272 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
273 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
274 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRealProxy
, target_domain_id
));
275 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
276 mono_mb_emit_icon (mb
, -1);
277 pos
= mono_mb_emit_branch (mb
, branch_code
);
282 mono_mb_emit_contextbound_check (MonoMethodBuilder
*mb
, int branch_code
)
284 static int offset
= -1;
288 mono_class_contextbound_bit_offset (&offset
, &mask
);
290 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, remote_class
));
291 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
292 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRemoteClass
, proxy_class
));
293 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
294 mono_mb_emit_ldflda (mb
, offset
);
295 mono_mb_emit_byte (mb
, CEE_LDIND_U1
);
296 mono_mb_emit_icon (mb
, mask
);
297 mono_mb_emit_byte (mb
, CEE_AND
);
298 mono_mb_emit_icon (mb
, 0);
299 return mono_mb_emit_branch (mb
, branch_code
);
301 #endif /* !DISABLE_JIT */
303 static inline MonoMethod
*
304 mono_marshal_remoting_find_in_cache (MonoMethod
*method
, int wrapper_type
)
306 MonoMethod
*res
= NULL
;
307 MonoRemotingMethods
*wrps
= NULL
;
309 mono_marshal_lock_internal ();
310 if (mono_method_get_wrapper_cache (method
)->remoting_invoke_cache
)
311 wrps
= (MonoRemotingMethods
*)g_hash_table_lookup (mono_method_get_wrapper_cache (method
)->remoting_invoke_cache
, method
);
314 switch (wrapper_type
) {
315 case MONO_WRAPPER_REMOTING_INVOKE
: res
= wrps
->invoke
; break;
316 case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
: res
= wrps
->invoke_with_check
; break;
317 case MONO_WRAPPER_XDOMAIN_INVOKE
: res
= wrps
->xdomain_invoke
; break;
318 case MONO_WRAPPER_XDOMAIN_DISPATCH
: res
= wrps
->xdomain_dispatch
; break;
322 /* it is important to do the unlock after the load from wrps, since in
323 * mono_remoting_mb_create_and_cache () we drop the marshal lock to be able
324 * to take the loader lock and some other thread may set the fields.
326 mono_marshal_unlock_internal ();
330 /* Create the method from the builder and place it in the cache */
331 static inline MonoMethod
*
332 mono_remoting_mb_create_and_cache (MonoMethod
*key
, MonoMethodBuilder
*mb
,
333 MonoMethodSignature
*sig
, int max_stack
, WrapperInfo
*info
)
335 MonoMethod
**res
= NULL
;
336 MonoRemotingMethods
*wrps
;
339 cache
= get_cache_full (&mono_method_get_wrapper_cache (key
)->remoting_invoke_cache
, mono_aligned_addr_hash
, NULL
, NULL
, g_free
);
341 mono_marshal_lock_internal ();
342 wrps
= (MonoRemotingMethods
*)g_hash_table_lookup (cache
, key
);
344 wrps
= g_new0 (MonoRemotingMethods
, 1);
345 g_hash_table_insert (cache
, key
, wrps
);
348 switch (mb
->method
->wrapper_type
) {
349 case MONO_WRAPPER_REMOTING_INVOKE
: res
= &wrps
->invoke
; break;
350 case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
: res
= &wrps
->invoke_with_check
; break;
351 case MONO_WRAPPER_XDOMAIN_INVOKE
: res
= &wrps
->xdomain_invoke
; break;
352 case MONO_WRAPPER_XDOMAIN_DISPATCH
: res
= &wrps
->xdomain_dispatch
; break;
353 default: g_assert_not_reached (); break;
355 mono_marshal_unlock_internal ();
359 newm
= mono_mb_create_method (mb
, sig
, max_stack
);
361 mono_marshal_lock_internal ();
364 mono_marshal_set_wrapper_info (*res
, info
);
365 mono_marshal_unlock_internal ();
367 mono_marshal_unlock_internal ();
368 mono_free_method (newm
);
376 mono_remoting_wrapper (MonoMethod
*method
, gpointer
*params
)
379 MonoMethodMessage
*msg
;
380 MonoTransparentProxy
*this_obj
;
381 MonoObject
*res
, *exc
;
384 this_obj
= *((MonoTransparentProxy
**)params
[0]);
387 g_assert (mono_object_is_transparent_proxy (this_obj
));
389 /* skip the this pointer */
392 if (mono_class_is_contextbound (this_obj
->remote_class
->proxy_class
) && this_obj
->rp
->context
== (MonoObject
*) mono_context_get ())
395 MonoMethodSignature
*sig
= mono_method_signature (method
);
396 int count
= sig
->param_count
;
397 gpointer
* mparams
= (gpointer
*) alloca(count
*sizeof(gpointer
));
399 for (i
=0; i
<count
; i
++) {
400 MonoClass
*klass
= mono_class_from_mono_type (sig
->params
[i
]);
401 if (m_class_is_valuetype (klass
)) {
402 if (sig
->params
[i
]->byref
) {
403 mparams
[i
] = *((gpointer
*)params
[i
]);
405 /* runtime_invoke expects a boxed instance */
406 if (mono_class_is_nullable (mono_class_from_mono_type (sig
->params
[i
]))) {
407 mparams
[i
] = mono_nullable_box ((guint8
*)params
[i
], klass
, error
);
408 goto_if_nok (error
, fail
);
410 mparams
[i
] = params
[i
];
413 mparams
[i
] = *((gpointer
**)params
[i
]);
417 res
= mono_runtime_invoke_checked (method
, m_class_is_valuetype (method
->klass
)? mono_object_unbox ((MonoObject
*)this_obj
): this_obj
, mparams
, error
);
418 goto_if_nok (error
, fail
);
423 msg
= mono_method_call_message_new (method
, params
, NULL
, NULL
, NULL
, error
);
424 goto_if_nok (error
, fail
);
426 res
= mono_remoting_invoke ((MonoObject
*)this_obj
->rp
, msg
, &exc
, &out_args
, error
);
427 goto_if_nok (error
, fail
);
431 exc
= (MonoObject
*) mono_remoting_update_exception ((MonoException
*)exc
);
432 mono_error_set_exception_instance (error
, (MonoException
*)exc
);
436 mono_method_return_message_restore (method
, params
, out_args
, error
);
437 goto_if_nok (error
, fail
);
441 mono_error_set_pending_exception (error
);
446 * Handles exception transformation at appdomain call boundary.
447 * Note this is called from target appdomain inside xdomain wrapper, but from
448 * source domain in the mono_remoting_wrapper slowpath.
450 static MonoException
*
451 mono_remoting_update_exception (MonoException
*exc
)
453 MonoInternalThread
*thread
;
454 MonoClass
*klass
= mono_object_get_class ((MonoObject
*)exc
);
456 /* Serialization error can only happen when still in the target appdomain */
457 if (!(mono_class_get_flags (klass
) & TYPE_ATTRIBUTE_SERIALIZABLE
)) {
459 char *aname
= mono_stringify_assembly_name (&m_class_get_image (klass
)->assembly
->aname
);
460 char *message
= g_strdup_printf ("Type '%s' in Assembly '%s' is not marked as serializable", m_class_get_name (klass
), aname
);
461 ret
= mono_get_exception_serialization (message
);
467 thread
= mono_thread_internal_current ();
468 if (mono_object_get_class ((MonoObject
*)exc
) == mono_defaults
.threadabortexception_class
&&
469 thread
->flags
& MONO_THREAD_FLAG_APPDOMAIN_ABORT
) {
470 mono_thread_internal_reset_abort (thread
);
471 return mono_get_exception_appdomain_unloaded ();
478 * mono_marshal_get_remoting_invoke:
481 mono_marshal_get_remoting_invoke (MonoMethod
*method
, MonoError
*error
)
483 MonoMethodSignature
*sig
;
484 MonoMethodBuilder
*mb
;
492 if (method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE
|| method
->wrapper_type
== MONO_WRAPPER_XDOMAIN_INVOKE
)
495 /* this seems to be the best plase to put this, as all remoting invokes seem to get filtered through here */
497 if (mono_class_is_com_object (method
->klass
) || method
->klass
== mono_class_try_get_com_object_class ()) {
498 MonoVTable
*vtable
= mono_class_vtable_checked (mono_domain_get (), method
->klass
, error
);
499 return_val_if_nok (error
, NULL
);
501 if (!mono_vtable_is_remote (vtable
)) {
502 return mono_cominterop_get_invoke (method
);
507 sig
= mono_signature_no_pinvoke (method
);
509 /* we cant remote methods without this pointer */
513 if ((res
= mono_marshal_remoting_find_in_cache (method
, MONO_WRAPPER_REMOTING_INVOKE
)))
516 mono_remoting_marshal_init ();
518 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_REMOTING_INVOKE
);
521 mb
->method
->save_lmf
= 1;
523 params_var
= mono_mb_emit_save_args (mb
, sig
, TRUE
);
525 mono_mb_emit_ptr (mb
, method
);
526 mono_mb_emit_ldloc (mb
, params_var
);
527 mono_mb_emit_icall (mb
, mono_remoting_wrapper
);
528 // FIXME: this interrupt checkpoint code is a no-op since 'mb'
529 // is a MONO_WRAPPER_REMOTING_INVOKE, and
530 // mono_thread_interruption_checkpoint_request (FALSE)
531 // considers such wrappers "protected" and always returns
532 // NULL as if there's no pending interruption.
533 mono_marshal_emit_thread_interrupt_checkpoint (mb
);
535 if (sig
->ret
->type
== MONO_TYPE_VOID
) {
536 mono_mb_emit_byte (mb
, CEE_POP
);
537 mono_mb_emit_byte (mb
, CEE_RET
);
539 mono_mb_emit_restore_result (mb
, sig
->ret
);
543 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
544 info
->d
.remoting
.method
= method
;
545 res
= mono_remoting_mb_create_and_cache (method
, mb
, sig
, sig
->param_count
+ 16, info
);
551 /* mono_marshal_xdomain_copy_out_value()
552 * Copies the contents of the src instance into the dst instance. src and dst
553 * must have the same type, and if they are arrays, the same size.
555 * This is an icall, it may use mono_error_set_pending_exception
558 mono_marshal_xdomain_copy_out_value (MonoObject
*src
, MonoObject
*dst
)
561 if (src
== NULL
|| dst
== NULL
) return;
563 g_assert (mono_object_class (src
) == mono_object_class (dst
));
565 switch (m_class_get_byval_arg (mono_object_class (src
))->type
) {
566 case MONO_TYPE_ARRAY
:
567 case MONO_TYPE_SZARRAY
: {
568 int mt
= mono_get_xdomain_marshal_type (m_class_get_byval_arg (m_class_get_element_class (mono_object_class (src
))));
569 if (mt
== MONO_MARSHAL_SERIALIZE
) return;
570 if (mt
== MONO_MARSHAL_COPY
) {
571 int i
, len
= mono_array_length ((MonoArray
*)dst
);
572 for (i
= 0; i
< len
; i
++) {
573 MonoObject
*item
= (MonoObject
*)mono_array_get ((MonoArray
*)src
, gpointer
, i
);
574 MonoObject
*item_copy
= mono_marshal_xdomain_copy_value (item
, error
);
575 if (mono_error_set_pending_exception (error
))
577 mono_array_setref ((MonoArray
*)dst
, i
, item_copy
);
580 mono_array_full_copy ((MonoArray
*)src
, (MonoArray
*)dst
);
591 #if !defined (DISABLE_JIT)
593 mono_marshal_emit_xdomain_copy_value (MonoMethodBuilder
*mb
, MonoClass
*pclass
)
595 mono_mb_emit_icall (mb
, ves_icall_mono_marshal_xdomain_copy_value
);
596 mono_mb_emit_op (mb
, CEE_CASTCLASS
, pclass
);
600 mono_marshal_emit_xdomain_copy_out_value (MonoMethodBuilder
*mb
, MonoClass
*pclass
)
602 mono_mb_emit_icall (mb
, mono_marshal_xdomain_copy_out_value
);
606 /* mono_marshal_supports_fast_xdomain()
607 * Returns TRUE if the method can use the fast xdomain wrapper.
610 mono_marshal_supports_fast_xdomain (MonoMethod
*method
)
612 return !mono_class_is_contextbound (method
->klass
) &&
613 !((method
->flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
) && (strcmp (".ctor", method
->name
) == 0));
617 mono_marshal_set_domain_by_id (gint32 id
, MonoBoolean push
)
619 MonoDomain
*current_domain
= mono_domain_get ();
620 MonoDomain
*domain
= mono_domain_get_by_id (id
);
622 if (!domain
|| !mono_domain_set (domain
, FALSE
)) {
623 mono_set_pending_exception (mono_get_exception_appdomain_unloaded ());
628 mono_thread_push_appdomain_ref (domain
);
630 mono_thread_pop_appdomain_ref ();
632 return current_domain
->domain_id
;
635 #if !defined (DISABLE_JIT)
637 mono_marshal_emit_switch_domain (MonoMethodBuilder
*mb
)
639 mono_mb_emit_icall (mb
, mono_marshal_set_domain_by_id
);
643 mono_compile_method_icall (MonoMethod
*method
)
646 gpointer result
= mono_compile_method_checked (method
, error
);
647 mono_error_set_pending_exception (error
);
651 /* mono_marshal_emit_load_domain_method ()
652 * Loads into the stack a pointer to the code of the provided method for
653 * the current domain.
656 mono_marshal_emit_load_domain_method (MonoMethodBuilder
*mb
, MonoMethod
*method
)
658 /* We need a pointer to the method for the running domain (not the domain
659 * that compiles the method).
661 mono_mb_emit_ptr (mb
, method
);
662 mono_mb_emit_icall (mb
, mono_compile_method_icall
);
666 /* mono_marshal_check_domain_image ()
667 * Returns TRUE if the image is loaded in the specified
668 * application domain.
671 mono_marshal_check_domain_image (gint32 domain_id
, MonoImage
*image
)
676 MonoDomain
*domain
= mono_domain_get_by_id (domain_id
);
680 mono_domain_assemblies_lock (domain
);
681 for (tmp
= domain
->domain_assemblies
; tmp
; tmp
= tmp
->next
) {
682 ass
= (MonoAssembly
*)tmp
->data
;
683 if (ass
->image
== image
)
686 mono_domain_assemblies_unlock (domain
);
691 /* mono_marshal_get_xappdomain_dispatch ()
692 * Generates a method that dispatches a method call from another domain into
693 * the current domain.
696 mono_marshal_get_xappdomain_dispatch (MonoMethod
*method
, int *marshal_types
, int complex_count
, int complex_out_count
, int ret_marshal_type
)
698 MonoMethodSignature
*sig
, *csig
;
699 MonoMethodBuilder
*mb
;
701 int i
, j
, param_index
, copy_locals_base
;
702 MonoClass
*ret_class
= NULL
;
703 int loc_array
=0, loc_return
=0, loc_serialized_exc
=0;
704 MonoExceptionClause
*main_clause
;
706 gboolean copy_return
;
709 if ((res
= mono_marshal_remoting_find_in_cache (method
, MONO_WRAPPER_XDOMAIN_DISPATCH
)))
712 sig
= mono_method_signature (method
);
713 copy_return
= (sig
->ret
->type
!= MONO_TYPE_VOID
&& ret_marshal_type
!= MONO_MARSHAL_SERIALIZE
);
716 csig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 3 + sig
->param_count
- complex_count
);
717 csig
->params
[j
++] = mono_get_object_type ();
718 csig
->params
[j
++] = m_class_get_this_arg (byte_array_class
);
719 csig
->params
[j
++] = m_class_get_this_arg (byte_array_class
);
720 for (i
= 0; i
< sig
->param_count
; i
++) {
721 if (marshal_types
[i
] != MONO_MARSHAL_SERIALIZE
)
722 csig
->params
[j
++] = sig
->params
[i
];
725 csig
->ret
= sig
->ret
;
727 csig
->ret
= mono_get_void_type ();
729 csig
->hasthis
= FALSE
;
731 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_XDOMAIN_DISPATCH
);
732 mb
->method
->save_lmf
= 1;
737 loc_serialized_exc
= mono_mb_add_local (mb
, m_class_get_byval_arg (byte_array_class
));
738 if (complex_count
> 0)
739 loc_array
= mono_mb_add_local (mb
, mono_get_object_type ());
740 if (sig
->ret
->type
!= MONO_TYPE_VOID
) {
741 loc_return
= mono_mb_add_local (mb
, sig
->ret
);
742 ret_class
= mono_class_from_mono_type (sig
->ret
);
747 main_clause
= (MonoExceptionClause
*)mono_image_alloc0 (m_class_get_image (method
->klass
), sizeof (MonoExceptionClause
));
748 main_clause
->try_offset
= mono_mb_get_label (mb
);
750 /* Clean the call context */
752 mono_mb_emit_byte (mb
, CEE_LDNULL
);
753 mono_mb_emit_managed_call (mb
, method_set_call_context
, NULL
);
754 mono_mb_emit_byte (mb
, CEE_POP
);
756 /* Deserialize call data */
758 mono_mb_emit_ldarg (mb
, 1);
759 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
760 mono_mb_emit_byte (mb
, CEE_DUP
);
761 pos
= mono_mb_emit_short_branch (mb
, CEE_BRFALSE_S
);
763 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
764 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
766 if (complex_count
> 0)
767 mono_mb_emit_stloc (mb
, loc_array
);
769 mono_mb_emit_byte (mb
, CEE_POP
);
771 mono_mb_patch_short_branch (mb
, pos
);
773 /* Get the target object */
775 mono_mb_emit_ldarg (mb
, 0);
776 mono_mb_emit_managed_call (mb
, method_rs_appdomain_target
, NULL
);
778 /* Load the arguments */
780 copy_locals_base
= mb
->locals
;
781 param_index
= 3; // Index of the first non-serialized parameter of this wrapper
783 for (i
= 0; i
< sig
->param_count
; i
++) {
784 MonoType
*pt
= sig
->params
[i
];
785 MonoClass
*pclass
= mono_class_from_mono_type (pt
);
786 switch (marshal_types
[i
]) {
787 case MONO_MARSHAL_SERIALIZE
: {
788 /* take the value from the serialized array */
789 mono_mb_emit_ldloc (mb
, loc_array
);
790 mono_mb_emit_icon (mb
, j
++);
792 if (m_class_is_valuetype (pclass
)) {
793 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
794 mono_mb_emit_op (mb
, CEE_UNBOX
, pclass
);
796 mono_mb_emit_op (mb
, CEE_LDELEMA
, pclass
);
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
);
802 mono_mb_emit_op (mb
, CEE_LDOBJ
, pclass
);
804 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
805 if (pclass
!= mono_defaults
.object_class
) {
806 mono_mb_emit_op (mb
, CEE_CASTCLASS
, pclass
);
812 case MONO_MARSHAL_COPY_OUT
: {
813 /* Keep a local copy of the value since we need to copy it back after the call */
814 int copy_local
= mono_mb_add_local (mb
, m_class_get_byval_arg (pclass
));
815 mono_mb_emit_ldarg (mb
, param_index
++);
816 mono_marshal_emit_xdomain_copy_value (mb
, pclass
);
817 mono_mb_emit_byte (mb
, CEE_DUP
);
818 mono_mb_emit_stloc (mb
, copy_local
);
821 case MONO_MARSHAL_COPY
: {
822 mono_mb_emit_ldarg (mb
, param_index
);
824 mono_mb_emit_byte (mb
, CEE_DUP
);
825 mono_mb_emit_byte (mb
, CEE_DUP
);
826 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
827 mono_marshal_emit_xdomain_copy_value (mb
, pclass
);
828 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
830 mono_marshal_emit_xdomain_copy_value (mb
, pclass
);
835 case MONO_MARSHAL_NONE
:
836 mono_mb_emit_ldarg (mb
, param_index
++);
841 /* Make the call to the real object */
843 mono_marshal_emit_thread_force_interrupt_checkpoint (mb
);
845 mono_mb_emit_op (mb
, CEE_CALLVIRT
, method
);
847 if (sig
->ret
->type
!= MONO_TYPE_VOID
)
848 mono_mb_emit_stloc (mb
, loc_return
);
850 /* copy back MONO_MARSHAL_COPY_OUT parameters */
854 for (i
= 0; i
< sig
->param_count
; i
++) {
855 if (marshal_types
[i
] == MONO_MARSHAL_SERIALIZE
) continue;
856 if (marshal_types
[i
] == MONO_MARSHAL_COPY_OUT
) {
857 mono_mb_emit_ldloc (mb
, copy_locals_base
+ (j
++));
858 mono_mb_emit_ldarg (mb
, param_index
);
859 mono_marshal_emit_xdomain_copy_out_value (mb
, mono_class_from_mono_type (sig
->params
[i
]));
864 /* Serialize the return values */
866 if (complex_out_count
> 0) {
867 /* Reset parameters in the array that don't need to be serialized back */
869 for (i
= 0; i
< sig
->param_count
; i
++) {
870 if (marshal_types
[i
] != MONO_MARSHAL_SERIALIZE
) continue;
871 if (!sig
->params
[i
]->byref
) {
872 mono_mb_emit_ldloc (mb
, loc_array
);
873 mono_mb_emit_icon (mb
, j
);
874 mono_mb_emit_byte (mb
, CEE_LDNULL
);
875 mono_mb_emit_byte (mb
, CEE_STELEM_REF
);
880 /* Add the return value to the array */
882 if (ret_marshal_type
== MONO_MARSHAL_SERIALIZE
) {
883 mono_mb_emit_ldloc (mb
, loc_array
);
884 mono_mb_emit_icon (mb
, complex_count
); /* The array has an additional slot to hold the ret value */
885 mono_mb_emit_ldloc (mb
, loc_return
);
887 g_assert (ret_class
); /*FIXME properly fail here*/
888 if (m_class_is_valuetype (ret_class
)) {
889 mono_mb_emit_op (mb
, CEE_BOX
, ret_class
);
891 mono_mb_emit_byte (mb
, CEE_STELEM_REF
);
896 mono_mb_emit_ldarg (mb
, 1);
897 mono_mb_emit_ldloc (mb
, loc_array
);
898 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
899 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
900 } else if (ret_marshal_type
== MONO_MARSHAL_SERIALIZE
) {
901 mono_mb_emit_ldarg (mb
, 1);
902 mono_mb_emit_ldloc (mb
, loc_return
);
903 if (m_class_is_valuetype (ret_class
)) {
904 mono_mb_emit_op (mb
, CEE_BOX
, ret_class
);
906 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
907 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
909 mono_mb_emit_ldarg (mb
, 1);
910 mono_mb_emit_byte (mb
, CEE_LDNULL
);
911 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
912 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
915 mono_mb_emit_ldarg (mb
, 2);
916 mono_mb_emit_byte (mb
, CEE_LDNULL
);
917 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
918 pos_leave
= mono_mb_emit_branch (mb
, CEE_LEAVE
);
920 /* Main exception catch */
921 main_clause
->flags
= MONO_EXCEPTION_CLAUSE_NONE
;
922 main_clause
->try_len
= mono_mb_get_pos (mb
) - main_clause
->try_offset
;
923 main_clause
->data
.catch_class
= mono_defaults
.object_class
;
926 main_clause
->handler_offset
= mono_mb_get_label (mb
);
928 mono_mb_emit_icall (mb
, mono_remoting_update_exception
);
929 mono_mb_emit_op (mb
, CEE_CASTCLASS
, mono_defaults
.exception_class
);
930 mono_mb_emit_managed_call (mb
, method_rs_serialize_exc
, NULL
);
931 mono_mb_emit_stloc (mb
, loc_serialized_exc
);
932 mono_mb_emit_ldarg (mb
, 2);
933 mono_mb_emit_ldloc (mb
, loc_serialized_exc
);
934 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
935 mono_mb_emit_branch (mb
, CEE_LEAVE
);
937 main_clause
->handler_len
= mono_mb_get_pos (mb
) - main_clause
->handler_offset
;
939 mono_mb_patch_branch (mb
, pos_leave
);
942 mono_mb_emit_ldloc (mb
, loc_return
);
944 mono_mb_emit_byte (mb
, CEE_RET
);
946 mono_mb_set_clauses (mb
, 1, main_clause
);
949 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
950 info
->d
.remoting
.method
= method
;
951 res
= mono_remoting_mb_create_and_cache (method
, mb
, csig
, csig
->param_count
+ 16, info
);
958 * mono_marshal_get_xappdomain_invoke:
959 * Generates a fast remoting wrapper for cross app domain calls.
962 mono_marshal_get_xappdomain_invoke (MonoMethod
*method
, MonoError
*error
)
964 MonoMethodSignature
*sig
;
965 MonoMethodBuilder
*mb
;
967 int i
, j
, complex_count
, complex_out_count
, copy_locals_base
;
969 MonoClass
*ret_class
= NULL
;
970 MonoMethod
*xdomain_method
;
971 int ret_marshal_type
= MONO_MARSHAL_NONE
;
972 int loc_array
=0, loc_serialized_data
=-1, loc_real_proxy
;
973 int loc_old_domainid
, loc_domainid
, loc_return
=0, loc_serialized_exc
=0, loc_context
;
974 int pos
, pos_dispatch
, pos_noex
;
975 gboolean copy_return
= FALSE
;
981 if (method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE
|| method
->wrapper_type
== MONO_WRAPPER_XDOMAIN_INVOKE
)
984 /* we cant remote methods without this pointer */
985 if (!mono_method_signature (method
)->hasthis
)
988 mono_remoting_marshal_init ();
990 if (!mono_marshal_supports_fast_xdomain (method
))
991 return mono_marshal_get_remoting_invoke (method
, error
);
993 if ((res
= mono_marshal_remoting_find_in_cache (method
, MONO_WRAPPER_XDOMAIN_INVOKE
)))
996 sig
= mono_signature_no_pinvoke (method
);
998 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_XDOMAIN_INVOKE
);
999 mb
->method
->save_lmf
= 1;
1001 /* Count the number of parameters that need to be serialized */
1003 marshal_types
= (int *)alloca (sizeof (int) * sig
->param_count
);
1004 complex_count
= complex_out_count
= 0;
1005 for (i
= 0; i
< sig
->param_count
; i
++) {
1006 MonoType
*ptype
= sig
->params
[i
];
1007 int mt
= mono_get_xdomain_marshal_type (ptype
);
1009 /* If the [Out] attribute is applied to a parameter that can be internally copied,
1010 * the copy will be made by reusing the original object instance
1012 if ((ptype
->attrs
& PARAM_ATTRIBUTE_OUT
) != 0 && mt
== MONO_MARSHAL_COPY
&& !ptype
->byref
)
1013 mt
= MONO_MARSHAL_COPY_OUT
;
1014 else if (mt
== MONO_MARSHAL_SERIALIZE
) {
1016 if (ptype
->byref
) complex_out_count
++;
1018 marshal_types
[i
] = mt
;
1021 if (sig
->ret
->type
!= MONO_TYPE_VOID
) {
1022 ret_marshal_type
= mono_get_xdomain_marshal_type (sig
->ret
);
1023 ret_class
= mono_class_from_mono_type (sig
->ret
);
1024 copy_return
= ret_marshal_type
!= MONO_MARSHAL_SERIALIZE
;
1030 MonoType
*object_type
= mono_get_object_type ();
1031 MonoType
*byte_array_type
= m_class_get_byval_arg (byte_array_class
);
1032 MonoType
*int32_type
= mono_get_int32_type ();
1033 if (complex_count
> 0)
1034 loc_array
= mono_mb_add_local (mb
, object_type
);
1035 loc_serialized_data
= mono_mb_add_local (mb
, byte_array_type
);
1036 loc_real_proxy
= mono_mb_add_local (mb
, object_type
);
1038 loc_return
= mono_mb_add_local (mb
, sig
->ret
);
1039 loc_old_domainid
= mono_mb_add_local (mb
, int32_type
);
1040 loc_domainid
= mono_mb_add_local (mb
, int32_type
);
1041 loc_serialized_exc
= mono_mb_add_local (mb
, byte_array_type
);
1042 loc_context
= mono_mb_add_local (mb
, object_type
);
1044 /* Save thread domain data */
1046 mono_mb_emit_icall (mb
, mono_context_get_icall
);
1047 mono_mb_emit_byte (mb
, CEE_DUP
);
1048 mono_mb_emit_stloc (mb
, loc_context
);
1050 /* If the thread is not running in the default context, it needs to go
1051 * through the whole remoting sink, since the context is going to change
1053 mono_mb_emit_managed_call (mb
, method_needs_context_sink
, NULL
);
1054 pos
= mono_mb_emit_short_branch (mb
, CEE_BRTRUE_S
);
1056 /* Another case in which the fast path can't be used: when the target domain
1057 * has a different image for the same assembly.
1060 /* Get the target domain id */
1062 mono_mb_emit_ldarg (mb
, 0);
1063 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
1064 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1065 mono_mb_emit_byte (mb
, CEE_DUP
);
1066 mono_mb_emit_stloc (mb
, loc_real_proxy
);
1068 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRealProxy
, target_domain_id
));
1069 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
1070 mono_mb_emit_stloc (mb
, loc_domainid
);
1072 /* Check if the target domain has the same image for the required assembly */
1074 mono_mb_emit_ldloc (mb
, loc_domainid
);
1075 mono_mb_emit_ptr (mb
, m_class_get_image (method
->klass
));
1076 mono_mb_emit_icall (mb
, mono_marshal_check_domain_image
);
1077 pos_dispatch
= mono_mb_emit_short_branch (mb
, CEE_BRTRUE_S
);
1079 /* Use the whole remoting sink to dispatch this message */
1081 mono_mb_patch_short_branch (mb
, pos
);
1083 mono_mb_emit_ldarg (mb
, 0);
1084 for (i
= 0; i
< sig
->param_count
; i
++)
1085 mono_mb_emit_ldarg (mb
, i
+ 1);
1087 MonoMethod
* remoting_invoke_method
= mono_marshal_get_remoting_invoke (method
, error
);
1088 if (!is_ok (error
)) {
1092 mono_mb_emit_managed_call (mb
, remoting_invoke_method
, NULL
);
1093 mono_mb_emit_byte (mb
, CEE_RET
);
1094 mono_mb_patch_short_branch (mb
, pos_dispatch
);
1096 /* Create the array that will hold the parameters to be serialized */
1098 if (complex_count
> 0) {
1099 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 */
1100 mono_mb_emit_op (mb
, CEE_NEWARR
, mono_defaults
.object_class
);
1103 for (i
= 0; i
< sig
->param_count
; i
++) {
1105 if (marshal_types
[i
] != MONO_MARSHAL_SERIALIZE
) continue;
1106 pclass
= mono_class_from_mono_type (sig
->params
[i
]);
1107 mono_mb_emit_byte (mb
, CEE_DUP
);
1108 mono_mb_emit_icon (mb
, j
);
1109 mono_mb_emit_ldarg (mb
, i
+ 1); /* 0=this */
1110 if (sig
->params
[i
]->byref
) {
1111 if (m_class_is_valuetype (pclass
))
1112 mono_mb_emit_op (mb
, CEE_LDOBJ
, pclass
);
1114 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1116 if (m_class_is_valuetype (pclass
))
1117 mono_mb_emit_op (mb
, CEE_BOX
, pclass
);
1118 mono_mb_emit_byte (mb
, CEE_STELEM_REF
);
1121 mono_mb_emit_stloc (mb
, loc_array
);
1123 /* Serialize parameters */
1125 mono_mb_emit_ldloc (mb
, loc_array
);
1126 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
1127 mono_mb_emit_stloc (mb
, loc_serialized_data
);
1129 mono_mb_emit_byte (mb
, CEE_LDNULL
);
1130 mono_mb_emit_managed_call (mb
, method_rs_serialize
, NULL
);
1131 mono_mb_emit_stloc (mb
, loc_serialized_data
);
1136 mono_mb_emit_ldloc (mb
, loc_domainid
);
1137 mono_mb_emit_byte (mb
, CEE_LDC_I4_1
);
1138 mono_marshal_emit_switch_domain (mb
);
1139 mono_mb_emit_stloc (mb
, loc_old_domainid
);
1141 /* Load the arguments */
1143 mono_mb_emit_ldloc (mb
, loc_real_proxy
);
1144 mono_mb_emit_ldloc_addr (mb
, loc_serialized_data
);
1145 mono_mb_emit_ldloc_addr (mb
, loc_serialized_exc
);
1147 copy_locals_base
= mb
->locals
;
1148 for (i
= 0; i
< sig
->param_count
; i
++) {
1149 switch (marshal_types
[i
]) {
1150 case MONO_MARSHAL_SERIALIZE
:
1152 case MONO_MARSHAL_COPY
: {
1153 mono_mb_emit_ldarg (mb
, i
+1);
1154 if (sig
->params
[i
]->byref
) {
1155 /* make a local copy of the byref parameter. The real parameter
1156 * will be updated after the xdomain call
1158 MonoClass
*pclass
= mono_class_from_mono_type (sig
->params
[i
]);
1159 int copy_local
= mono_mb_add_local (mb
, m_class_get_byval_arg (pclass
));
1160 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1161 mono_mb_emit_stloc (mb
, copy_local
);
1162 mono_mb_emit_ldloc_addr (mb
, copy_local
);
1166 case MONO_MARSHAL_COPY_OUT
:
1167 case MONO_MARSHAL_NONE
:
1168 mono_mb_emit_ldarg (mb
, i
+1);
1173 /* Make the call to the invoke wrapper in the target domain */
1175 xdomain_method
= mono_marshal_get_xappdomain_dispatch (method
, marshal_types
, complex_count
, complex_out_count
, ret_marshal_type
);
1176 mono_marshal_emit_load_domain_method (mb
, xdomain_method
);
1177 mono_mb_emit_calli (mb
, mono_method_signature (xdomain_method
));
1180 mono_mb_emit_stloc (mb
, loc_return
);
1184 mono_mb_emit_ldloc (mb
, loc_old_domainid
);
1185 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
1186 mono_marshal_emit_switch_domain (mb
);
1187 mono_mb_emit_byte (mb
, CEE_POP
);
1189 /* Restore thread domain data */
1191 mono_mb_emit_ldloc (mb
, loc_context
);
1192 mono_mb_emit_icall (mb
, mono_context_set_icall
);
1194 /* if (loc_serialized_exc != null) ... */
1196 mono_mb_emit_ldloc (mb
, loc_serialized_exc
);
1197 pos_noex
= mono_mb_emit_short_branch (mb
, CEE_BRFALSE_S
);
1199 mono_mb_emit_ldloc (mb
, loc_serialized_exc
);
1200 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
1201 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
1202 mono_mb_emit_op (mb
, CEE_CASTCLASS
, mono_defaults
.exception_class
);
1203 mono_mb_emit_managed_call (mb
, method_exc_fixexc
, NULL
);
1204 mono_mb_emit_byte (mb
, CEE_THROW
);
1205 mono_mb_patch_short_branch (mb
, pos_noex
);
1207 /* copy back non-serialized output parameters */
1210 for (i
= 0; i
< sig
->param_count
; i
++) {
1211 if (!sig
->params
[i
]->byref
|| marshal_types
[i
] != MONO_MARSHAL_COPY
) continue;
1212 mono_mb_emit_ldarg (mb
, i
+ 1);
1213 mono_mb_emit_ldloc (mb
, copy_locals_base
+ (j
++));
1214 mono_marshal_emit_xdomain_copy_value (mb
, mono_class_from_mono_type (sig
->params
[i
]));
1215 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
1218 /* Deserialize out parameters */
1220 if (complex_out_count
> 0) {
1221 mono_mb_emit_ldloc (mb
, loc_serialized_data
);
1222 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
1223 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
1224 mono_mb_emit_stloc (mb
, loc_array
);
1226 /* Copy back output parameters and return type */
1229 for (i
= 0; i
< sig
->param_count
; i
++) {
1230 if (marshal_types
[i
] != MONO_MARSHAL_SERIALIZE
) continue;
1231 if (sig
->params
[i
]->byref
) {
1232 MonoClass
*pclass
= mono_class_from_mono_type (sig
->params
[i
]);
1233 mono_mb_emit_ldarg (mb
, i
+ 1);
1234 mono_mb_emit_ldloc (mb
, loc_array
);
1235 mono_mb_emit_icon (mb
, j
);
1236 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
1237 if (m_class_is_valuetype (pclass
)) {
1238 mono_mb_emit_op (mb
, CEE_UNBOX
, pclass
);
1239 mono_mb_emit_op (mb
, CEE_LDOBJ
, pclass
);
1240 mono_mb_emit_op (mb
, CEE_STOBJ
, pclass
);
1242 if (pclass
!= mono_defaults
.object_class
)
1243 mono_mb_emit_op (mb
, CEE_CASTCLASS
, pclass
);
1244 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
1250 if (ret_marshal_type
== MONO_MARSHAL_SERIALIZE
) {
1251 mono_mb_emit_ldloc (mb
, loc_array
);
1252 mono_mb_emit_icon (mb
, complex_count
);
1253 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
1254 if (m_class_is_valuetype (ret_class
)) {
1255 mono_mb_emit_op (mb
, CEE_UNBOX
, ret_class
);
1256 mono_mb_emit_op (mb
, CEE_LDOBJ
, ret_class
);
1259 } else if (ret_marshal_type
== MONO_MARSHAL_SERIALIZE
) {
1260 mono_mb_emit_ldloc (mb
, loc_serialized_data
);
1261 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
1262 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
1263 if (m_class_is_valuetype (ret_class
)) {
1264 mono_mb_emit_op (mb
, CEE_UNBOX
, ret_class
);
1265 mono_mb_emit_op (mb
, CEE_LDOBJ
, ret_class
);
1266 } else if (ret_class
!= mono_defaults
.object_class
) {
1267 mono_mb_emit_op (mb
, CEE_CASTCLASS
, ret_class
);
1270 mono_mb_emit_ldloc (mb
, loc_serialized_data
);
1271 mono_mb_emit_byte (mb
, CEE_DUP
);
1272 pos
= mono_mb_emit_short_branch (mb
, CEE_BRFALSE_S
);
1273 mono_marshal_emit_xdomain_copy_value (mb
, byte_array_class
);
1275 mono_mb_patch_short_branch (mb
, pos
);
1276 mono_mb_emit_managed_call (mb
, method_rs_deserialize
, NULL
);
1277 mono_mb_emit_byte (mb
, CEE_POP
);
1281 mono_mb_emit_ldloc (mb
, loc_return
);
1282 if (ret_marshal_type
== MONO_MARSHAL_COPY
)
1283 mono_marshal_emit_xdomain_copy_value (mb
, ret_class
);
1286 mono_mb_emit_byte (mb
, CEE_RET
);
1287 #endif /* DISABLE_JIT */
1289 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1290 info
->d
.remoting
.method
= method
;
1291 res
= mono_remoting_mb_create_and_cache (method
, mb
, sig
, sig
->param_count
+ 16, info
);
1298 * mono_marshal_get_remoting_invoke_for_target:
1301 mono_marshal_get_remoting_invoke_for_target (MonoMethod
*method
, MonoRemotingTarget target_type
, MonoError
*error
)
1304 if (target_type
== MONO_REMOTING_TARGET_APPDOMAIN
) {
1305 return mono_marshal_get_xappdomain_invoke (method
, error
);
1306 } else if (target_type
== MONO_REMOTING_TARGET_COMINTEROP
) {
1308 return mono_cominterop_get_invoke (method
);
1310 g_assert_not_reached ();
1313 return mono_marshal_get_remoting_invoke (method
, error
);
1319 G_GNUC_UNUSED
static gpointer
1320 mono_marshal_load_remoting_wrapper (MonoRealProxy
*rp
, MonoMethod
*method
)
1323 MonoMethod
*marshal_method
= NULL
;
1324 if (rp
->target_domain_id
!= -1)
1325 marshal_method
= mono_marshal_get_xappdomain_invoke (method
, error
);
1327 marshal_method
= mono_marshal_get_remoting_invoke (method
, error
);
1328 mono_error_assert_ok (error
);
1329 gpointer compiled_ptr
= mono_compile_method_checked (marshal_method
, error
);
1330 mono_error_assert_ok (error
);
1331 return compiled_ptr
;
1335 * mono_marshal_get_remoting_invoke_with_check:
1338 mono_marshal_get_remoting_invoke_with_check (MonoMethod
*method
, MonoError
*error
)
1340 MonoMethodSignature
*sig
;
1341 MonoMethodBuilder
*mb
;
1342 MonoMethod
*res
, *native
;
1344 int i
, pos
, pos_rem
;
1349 if (method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
)
1352 /* we cant remote methods without this pointer */
1353 g_assert (mono_method_signature (method
)->hasthis
);
1355 if ((res
= mono_marshal_remoting_find_in_cache (method
, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
)))
1358 sig
= mono_signature_no_pinvoke (method
);
1360 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
);
1363 for (i
= 0; i
<= sig
->param_count
; i
++)
1364 mono_mb_emit_ldarg (mb
, i
);
1366 mono_mb_emit_ldarg (mb
, 0);
1367 pos
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
1369 if (mono_marshal_supports_fast_xdomain (method
)) {
1370 mono_mb_emit_ldarg (mb
, 0);
1371 pos_rem
= mono_mb_emit_xdomain_check (mb
, CEE_BEQ
);
1373 /* wrapper for cross app domain calls */
1374 native
= mono_marshal_get_xappdomain_invoke (method
, error
);
1375 if (!is_ok (error
)) {
1379 mono_mb_emit_managed_call (mb
, native
, mono_method_signature (native
));
1380 mono_mb_emit_byte (mb
, CEE_RET
);
1382 mono_mb_patch_branch (mb
, pos_rem
);
1384 /* wrapper for normal remote calls */
1385 native
= mono_marshal_get_remoting_invoke (method
, error
);
1386 if (!is_ok (error
)) {
1390 mono_mb_emit_managed_call (mb
, native
, mono_method_signature (native
));
1391 mono_mb_emit_byte (mb
, CEE_RET
);
1394 mono_mb_patch_branch (mb
, pos
);
1395 mono_mb_emit_managed_call (mb
, method
, mono_method_signature (method
));
1396 mono_mb_emit_byte (mb
, CEE_RET
);
1399 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1400 info
->d
.remoting
.method
= method
;
1401 res
= mono_remoting_mb_create_and_cache (method
, mb
, sig
, sig
->param_count
+ 16, info
);
1408 * mono_marshal_get_ldfld_wrapper:
1409 * \param type the type of the field
1411 * This method generates a function which can be use to load a field with type
1412 * \p type from an object. The generated function has the following signature:
1414 * <code><i>type</i> ldfld_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset)</code>
1417 mono_marshal_get_ldfld_wrapper (MonoType
*type
)
1419 MonoMethodSignature
*sig
;
1420 MonoMethodBuilder
*mb
;
1426 int t
, pos0
, pos1
= 0;
1427 static MonoMethod
* tp_load
= NULL
;
1429 type
= mono_type_get_underlying_type (type
);
1434 if (type
->type
== MONO_TYPE_SZARRAY
) {
1435 klass
= mono_defaults
.array_class
;
1436 } else if (type
->type
== MONO_TYPE_VALUETYPE
) {
1437 klass
= type
->data
.klass
;
1438 } else if (t
== MONO_TYPE_OBJECT
|| t
== MONO_TYPE_CLASS
|| t
== MONO_TYPE_STRING
) {
1439 klass
= mono_defaults
.object_class
;
1440 } else if (t
== MONO_TYPE_PTR
|| t
== MONO_TYPE_FNPTR
) {
1441 klass
= mono_defaults
.int_class
;
1442 } else if (t
== MONO_TYPE_GENERICINST
) {
1443 if (mono_type_generic_inst_is_valuetype (type
))
1444 klass
= mono_class_from_mono_type (type
);
1446 klass
= mono_defaults
.object_class
;
1448 klass
= mono_class_from_mono_type (type
);
1451 klass
= mono_defaults
.int_class
;
1454 cache
= get_cache (&m_class_get_image (klass
)->ldfld_wrapper_cache
, mono_aligned_addr_hash
, NULL
);
1455 if ((res
= mono_marshal_find_in_cache (cache
, klass
)))
1458 #ifndef DISABLE_REMOTING
1460 tp_load
= mono_class_get_method_from_name (mono_defaults
.transparent_proxy_class
, "LoadRemoteFieldNew", -1);
1461 g_assert (tp_load
!= NULL
);
1465 /* we add the %p pointer value of klass because class names are not unique */
1466 name
= g_strdup_printf ("__ldfld_wrapper_%p_%s.%s", klass
, m_class_get_name_space (klass
), m_class_get_name (klass
));
1467 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_LDFLD
);
1470 MonoType
*object_type
= mono_get_object_type ();
1471 MonoType
*int_type
= mono_get_int_type ();
1472 sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 4);
1473 sig
->params
[0] = object_type
;
1474 sig
->params
[1] = int_type
;
1475 sig
->params
[2] = int_type
;
1476 sig
->params
[3] = int_type
;
1477 sig
->ret
= m_class_get_byval_arg (klass
);
1480 mono_mb_emit_ldarg (mb
, 0);
1481 pos0
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
1483 #ifndef DISABLE_REMOTING
1484 mono_mb_emit_ldarg (mb
, 0);
1485 mono_mb_emit_ldarg (mb
, 1);
1486 mono_mb_emit_ldarg (mb
, 2);
1488 mono_mb_emit_managed_call (mb
, tp_load
, NULL
);
1491 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
1492 csig->params [0] = mono_get_object_type ();
1493 csig->params [1] = mono_get_int_type ();
1494 csig->params [2] = mono_get_int_type ();
1495 csig->ret = m_class_get_this_arg (klass);
1498 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
1499 mono_marshal_emit_thread_interrupt_checkpoint (mb);
1502 if (m_class_is_valuetype (klass
)) {
1503 mono_mb_emit_op (mb
, CEE_UNBOX
, klass
);
1504 pos1
= mono_mb_emit_branch (mb
, CEE_BR
);
1506 mono_mb_emit_byte (mb
, CEE_RET
);
1510 mono_mb_patch_branch (mb
, pos0
);
1512 mono_mb_emit_ldarg (mb
, 0);
1513 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1514 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
1515 mono_mb_emit_ldarg (mb
, 3);
1516 mono_mb_emit_byte (mb
, CEE_ADD
);
1518 if (m_class_is_valuetype (klass
))
1519 mono_mb_patch_branch (mb
, pos1
);
1524 case MONO_TYPE_BOOLEAN
:
1525 case MONO_TYPE_CHAR
:
1534 case MONO_TYPE_ARRAY
:
1535 case MONO_TYPE_SZARRAY
:
1536 case MONO_TYPE_OBJECT
:
1537 case MONO_TYPE_CLASS
:
1538 case MONO_TYPE_STRING
:
1542 case MONO_TYPE_FNPTR
:
1543 mono_mb_emit_byte (mb
, mono_type_to_ldind (type
));
1545 case MONO_TYPE_VALUETYPE
:
1546 g_assert (!m_class_is_enumtype (klass
));
1547 mono_mb_emit_op (mb
, CEE_LDOBJ
, klass
);
1549 case MONO_TYPE_GENERICINST
:
1550 if (mono_type_generic_inst_is_valuetype (type
)) {
1551 mono_mb_emit_op (mb
, CEE_LDOBJ
, klass
);
1553 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1557 case MONO_TYPE_MVAR
:
1558 mono_mb_emit_op (mb
, CEE_LDOBJ
, klass
);
1561 g_warning ("type %x not implemented", type
->type
);
1562 g_assert_not_reached ();
1565 mono_mb_emit_byte (mb
, CEE_RET
);
1566 #endif /* DISABLE_JIT */
1568 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1569 info
->d
.proxy
.klass
= klass
;
1570 res
= mono_mb_create_and_cache_full (cache
, klass
,
1571 mb
, sig
, sig
->param_count
+ 16, info
, NULL
);
1578 * mono_marshal_get_ldflda_wrapper:
1579 * @type: the type of the field
1581 * This method generates a function which can be used to load a field address
1582 * from an object. The generated function has the following signature:
1583 * gpointer ldflda_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset);
1586 mono_marshal_get_ldflda_wrapper (MonoType
*type
)
1588 MonoMethodSignature
*sig
;
1589 MonoMethodBuilder
*mb
;
1595 int t
, pos0
, pos1
, pos2
, pos3
;
1597 type
= mono_type_get_underlying_type (type
);
1601 if (type
->type
== MONO_TYPE_SZARRAY
) {
1602 klass
= mono_defaults
.array_class
;
1603 } else if (type
->type
== MONO_TYPE_VALUETYPE
) {
1604 klass
= type
->data
.klass
;
1605 } else if (t
== MONO_TYPE_OBJECT
|| t
== MONO_TYPE_CLASS
|| t
== MONO_TYPE_STRING
) {
1606 klass
= mono_defaults
.object_class
;
1607 } else if (t
== MONO_TYPE_PTR
|| t
== MONO_TYPE_FNPTR
) {
1608 klass
= mono_defaults
.int_class
;
1609 } else if (t
== MONO_TYPE_GENERICINST
) {
1610 if (mono_type_generic_inst_is_valuetype (type
))
1611 klass
= mono_class_from_mono_type (type
);
1613 klass
= mono_defaults
.object_class
;
1615 klass
= mono_class_from_mono_type (type
);
1618 klass
= mono_defaults
.int_class
;
1621 cache
= get_cache (&m_class_get_image (klass
)->ldflda_wrapper_cache
, mono_aligned_addr_hash
, NULL
);
1622 if ((res
= mono_marshal_find_in_cache (cache
, klass
)))
1625 mono_remoting_marshal_init ();
1627 /* we add the %p pointer value of klass because class names are not unique */
1628 name
= g_strdup_printf ("__ldflda_wrapper_%p_%s.%s", klass
, m_class_get_name_space (klass
), m_class_get_name (klass
));
1629 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_LDFLDA
);
1632 MonoType
*object_type
= mono_get_object_type ();
1633 MonoType
*int_type
= mono_get_int_type ();
1634 sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 4);
1635 sig
->params
[0] = object_type
;
1636 sig
->params
[1] = int_type
;
1637 sig
->params
[2] = int_type
;
1638 sig
->params
[3] = int_type
;
1639 sig
->ret
= int_type
;
1642 /* if typeof (this) != transparent_proxy goto pos0 */
1643 mono_mb_emit_ldarg (mb
, 0);
1644 pos0
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
1646 /* if same_appdomain goto pos1 */
1647 mono_mb_emit_ldarg (mb
, 0);
1648 pos1
= mono_mb_emit_xdomain_check (mb
, CEE_BEQ
);
1650 mono_mb_emit_exception_full (mb
, "System", "InvalidOperationException", "Attempt to load field address from object in another appdomain.");
1652 /* same app domain */
1653 mono_mb_patch_branch (mb
, pos1
);
1655 /* if typeof (this) != contextbound goto pos2 */
1656 mono_mb_emit_ldarg (mb
, 0);
1657 pos2
= mono_mb_emit_contextbound_check (mb
, CEE_BEQ
);
1659 /* if this->rp->context == mono_context_get goto pos3 */
1660 mono_mb_emit_ldarg (mb
, 0);
1661 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
1662 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1663 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRealProxy
, context
));
1664 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1665 mono_mb_emit_icall (mb
, mono_context_get_icall
);
1666 pos3
= mono_mb_emit_branch (mb
, CEE_BEQ
);
1668 mono_mb_emit_exception_full (mb
, "System", "InvalidOperationException", "Attempt to load field address from object in another context.");
1670 mono_mb_patch_branch (mb
, pos2
);
1671 mono_mb_patch_branch (mb
, pos3
);
1673 /* return the address of the field from this->rp->unwrapped_server */
1674 mono_mb_emit_ldarg (mb
, 0);
1675 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
1676 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1677 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoRealProxy
, unwrapped_server
));
1678 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1679 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1680 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
1681 mono_mb_emit_ldarg (mb
, 3);
1682 mono_mb_emit_byte (mb
, CEE_ADD
);
1683 mono_mb_emit_byte (mb
, CEE_RET
);
1685 /* not a proxy: return the address of the field directly */
1686 mono_mb_patch_branch (mb
, pos0
);
1688 mono_mb_emit_ldarg (mb
, 0);
1689 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1690 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
1691 mono_mb_emit_ldarg (mb
, 3);
1692 mono_mb_emit_byte (mb
, CEE_ADD
);
1694 mono_mb_emit_byte (mb
, CEE_RET
);
1697 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1698 info
->d
.proxy
.klass
= klass
;
1699 res
= mono_mb_create_and_cache_full (cache
, klass
,
1700 mb
, sig
, sig
->param_count
+ 16,
1709 * mono_marshal_get_stfld_wrapper:
1710 * \param type the type of the field
1712 * This method generates a function which can be use to store a field with type
1713 * \p type. The generated function has the following signature:
1715 * <code>void stfld_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset, <i>type</i> val)</code>
1718 mono_marshal_get_stfld_wrapper (MonoType
*type
)
1720 MonoMethodSignature
*sig
;
1721 MonoMethodBuilder
*mb
;
1728 static MonoMethod
*tp_store
= NULL
;
1730 type
= mono_type_get_underlying_type (type
);
1734 if (type
->type
== MONO_TYPE_SZARRAY
) {
1735 klass
= mono_defaults
.array_class
;
1736 } else if (type
->type
== MONO_TYPE_VALUETYPE
) {
1737 klass
= type
->data
.klass
;
1738 } else if (t
== MONO_TYPE_OBJECT
|| t
== MONO_TYPE_CLASS
|| t
== MONO_TYPE_STRING
) {
1739 klass
= mono_defaults
.object_class
;
1740 } else if (t
== MONO_TYPE_PTR
|| t
== MONO_TYPE_FNPTR
) {
1741 klass
= mono_defaults
.int_class
;
1742 } else if (t
== MONO_TYPE_GENERICINST
) {
1743 if (mono_type_generic_inst_is_valuetype (type
))
1744 klass
= mono_class_from_mono_type (type
);
1746 klass
= mono_defaults
.object_class
;
1748 klass
= mono_class_from_mono_type (type
);
1751 klass
= mono_defaults
.int_class
;
1754 cache
= get_cache (&m_class_get_image (klass
)->stfld_wrapper_cache
, mono_aligned_addr_hash
, NULL
);
1755 if ((res
= mono_marshal_find_in_cache (cache
, klass
)))
1758 #ifndef DISABLE_REMOTING
1760 tp_store
= mono_class_get_method_from_name (mono_defaults
.transparent_proxy_class
, "StoreRemoteField", -1);
1761 g_assert (tp_store
!= NULL
);
1765 /* we add the %p pointer value of klass because class names are not unique */
1766 name
= g_strdup_printf ("__stfld_wrapper_%p_%s.%s", klass
, m_class_get_name_space (klass
), m_class_get_name (klass
));
1767 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_STFLD
);
1771 MonoType
*object_type
= mono_get_object_type ();
1772 MonoType
*int_type
= mono_get_int_type ();
1773 MonoType
*void_type
= mono_get_void_type ();
1774 sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 5);
1775 sig
->params
[0] = object_type
;
1776 sig
->params
[1] = int_type
;
1777 sig
->params
[2] = int_type
;
1778 sig
->params
[3] = int_type
;
1779 sig
->params
[4] = m_class_get_byval_arg (klass
);
1780 sig
->ret
= void_type
;
1783 mono_mb_emit_ldarg (mb
, 0);
1784 pos
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
1786 #ifndef DISABLE_REMOTING
1787 mono_mb_emit_ldarg (mb
, 0);
1788 mono_mb_emit_ldarg (mb
, 1);
1789 mono_mb_emit_ldarg (mb
, 2);
1790 mono_mb_emit_ldarg (mb
, 4);
1791 if (m_class_is_valuetype (klass
))
1792 mono_mb_emit_op (mb
, CEE_BOX
, klass
);
1794 mono_mb_emit_managed_call (mb
, tp_store
, NULL
);
1796 mono_mb_emit_byte (mb
, CEE_RET
);
1799 mono_mb_patch_branch (mb
, pos
);
1801 mono_mb_emit_ldarg (mb
, 0);
1802 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1803 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
1804 mono_mb_emit_ldarg (mb
, 3);
1805 mono_mb_emit_byte (mb
, CEE_ADD
);
1806 mono_mb_emit_ldarg (mb
, 4);
1811 case MONO_TYPE_BOOLEAN
:
1812 case MONO_TYPE_CHAR
:
1821 case MONO_TYPE_ARRAY
:
1822 case MONO_TYPE_SZARRAY
:
1823 case MONO_TYPE_OBJECT
:
1824 case MONO_TYPE_CLASS
:
1825 case MONO_TYPE_STRING
:
1829 case MONO_TYPE_FNPTR
:
1830 mono_mb_emit_byte (mb
, mono_type_to_stind (type
));
1832 case MONO_TYPE_VALUETYPE
:
1833 g_assert (!m_class_is_enumtype (klass
));
1834 mono_mb_emit_op (mb
, CEE_STOBJ
, klass
);
1836 case MONO_TYPE_GENERICINST
:
1838 case MONO_TYPE_MVAR
:
1839 mono_mb_emit_op (mb
, CEE_STOBJ
, klass
);
1842 g_warning ("type %x not implemented", type
->type
);
1843 g_assert_not_reached ();
1846 mono_mb_emit_byte (mb
, CEE_RET
);
1849 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1850 info
->d
.proxy
.klass
= klass
;
1851 res
= mono_mb_create_and_cache_full (cache
, klass
,
1852 mb
, sig
, sig
->param_count
+ 16,
1860 * mono_marshal_get_proxy_cancast:
1863 mono_marshal_get_proxy_cancast (MonoClass
*klass
)
1865 static MonoMethodSignature
*isint_sig
= NULL
;
1869 int pos_failed
, pos_end
;
1870 char *name
, *klass_name
;
1871 MonoMethod
*can_cast_to
;
1872 MonoMethodDesc
*desc
;
1873 MonoMethodBuilder
*mb
;
1875 cache
= get_cache (&m_class_get_image (klass
)->proxy_isinst_cache
, mono_aligned_addr_hash
, NULL
);
1876 if ((res
= mono_marshal_find_in_cache (cache
, klass
)))
1880 isint_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 1);
1881 isint_sig
->params
[0] = mono_get_object_type ();
1882 isint_sig
->ret
= mono_get_object_type ();
1883 isint_sig
->pinvoke
= 0;
1886 klass_name
= mono_type_full_name (m_class_get_byval_arg (klass
));
1887 name
= g_strdup_printf ("__proxy_isinst_wrapper_%s", klass_name
);
1888 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_PROXY_ISINST
);
1889 g_free (klass_name
);
1892 mb
->method
->save_lmf
= 1;
1895 /* get the real proxy from the transparent proxy*/
1896 mono_mb_emit_ldarg (mb
, 0);
1897 mono_mb_emit_ldflda (mb
, MONO_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
1898 mono_mb_emit_byte (mb
, CEE_LDIND_REF
);
1900 /* get the reflection type from the type handle */
1901 mono_mb_emit_ptr (mb
, m_class_get_byval_arg (klass
));
1902 mono_mb_emit_icall (mb
, type_from_handle
);
1904 mono_mb_emit_ldarg (mb
, 0);
1906 /* make the call to CanCastTo (type, ob) */
1907 desc
= mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE
);
1908 can_cast_to
= mono_method_desc_search_in_class (desc
, mono_defaults
.iremotingtypeinfo_class
);
1909 g_assert (can_cast_to
);
1910 mono_method_desc_free (desc
);
1911 mono_mb_emit_op (mb
, CEE_CALLVIRT
, can_cast_to
);
1913 pos_failed
= mono_mb_emit_branch (mb
, CEE_BRFALSE
);
1915 /* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
1916 mono_mb_emit_ptr (mb
, m_class_get_byval_arg (klass
));
1917 mono_mb_emit_icall (mb
, type_from_handle
);
1918 mono_mb_emit_ldarg (mb
, 0);
1920 mono_mb_emit_icall (mb
, mono_upgrade_remote_class_wrapper
);
1921 mono_marshal_emit_thread_interrupt_checkpoint (mb
);
1923 mono_mb_emit_ldarg (mb
, 0);
1924 pos_end
= mono_mb_emit_branch (mb
, CEE_BR
);
1928 mono_mb_patch_branch (mb
, pos_failed
);
1929 mono_mb_emit_byte (mb
, CEE_LDNULL
);
1933 mono_mb_patch_branch (mb
, pos_end
);
1934 mono_mb_emit_byte (mb
, CEE_RET
);
1937 info
= mono_wrapper_info_create (mb
, WRAPPER_SUBTYPE_NONE
);
1938 info
->d
.proxy
.klass
= klass
;
1939 res
= mono_mb_create_and_cache_full (cache
, klass
, mb
, isint_sig
, isint_sig
->param_count
+ 16, info
, NULL
);
1946 mono_upgrade_remote_class_wrapper (MonoReflectionType
*rtype_raw
, MonoTransparentProxy
*tproxy_raw
)
1949 MONO_HANDLE_DCL (MonoReflectionType
, rtype
);
1950 MONO_HANDLE_DCL (MonoTransparentProxy
, tproxy
);
1951 MonoDomain
*domain
= MONO_HANDLE_DOMAIN (tproxy
);
1952 MonoClass
*klass
= mono_class_from_mono_type (MONO_HANDLE_GETVAL (rtype
, type
));
1953 mono_upgrade_remote_class (domain
, MONO_HANDLE_CAST (MonoObject
, tproxy
), klass
, error
);
1957 #else /* DISABLE_REMOTING */
1960 mono_remoting_init (void)
1964 #endif /* DISABLE_REMOTING */
1966 /* mono_get_xdomain_marshal_type()
1967 * Returns the kind of marshalling that a type needs for cross domain calls.
1969 static MonoXDomainMarshalType
1970 mono_get_xdomain_marshal_type (MonoType
*t
)
1973 case MONO_TYPE_VOID
:
1974 g_assert_not_reached ();
1978 case MONO_TYPE_BOOLEAN
:
1981 case MONO_TYPE_CHAR
:
1988 return MONO_MARSHAL_NONE
;
1989 case MONO_TYPE_STRING
:
1990 return MONO_MARSHAL_COPY
;
1991 case MONO_TYPE_ARRAY
:
1992 case MONO_TYPE_SZARRAY
: {
1993 MonoClass
*elem_class
= m_class_get_element_class (mono_class_from_mono_type (t
));
1994 if (mono_get_xdomain_marshal_type (m_class_get_byval_arg (elem_class
)) != MONO_MARSHAL_SERIALIZE
)
1995 return MONO_MARSHAL_COPY
;
2001 return MONO_MARSHAL_SERIALIZE
;
2004 /* Replace the given array element by a copy in the current domain */
2006 xdomain_copy_array_element_inplace (MonoArrayHandle arr
, int i
, MonoError
*error
)
2008 HANDLE_FUNCTION_ENTER ();
2010 MonoObjectHandle item
= MONO_HANDLE_NEW (MonoObject
, NULL
);
2011 MONO_HANDLE_ARRAY_GETREF (item
, arr
, i
);
2013 MonoObjectHandle item_copy
= mono_marshal_xdomain_copy_value_handle (item
, error
);
2014 goto_if_nok (error
, leave
);
2015 MONO_HANDLE_ARRAY_SETREF (arr
, i
, item_copy
);
2017 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
2021 * mono_marshal_xdomain_copy_value_handle:
2022 * \param val The value to copy.
2023 * \param error set on failure.
2024 * Makes a copy of \p val suitable for the current domain.
2025 * On failure returns NULL and sets \p error.
2028 mono_marshal_xdomain_copy_value_handle (MonoObjectHandle val
, MonoError
*error
)
2031 MonoObjectHandle result
= MONO_HANDLE_NEW (MonoObject
, NULL
);
2032 if (MONO_HANDLE_IS_NULL (val
))
2035 MonoDomain
*domain
= mono_domain_get ();
2037 MonoClass
*klass
= mono_handle_class (val
);
2039 switch (m_class_get_byval_arg (klass
)->type
) {
2040 case MONO_TYPE_VOID
:
2041 g_assert_not_reached ();
2045 case MONO_TYPE_BOOLEAN
:
2048 case MONO_TYPE_CHAR
:
2054 case MONO_TYPE_R8
: {
2055 uint32_t gchandle
= mono_gchandle_from_handle (val
, TRUE
);
2056 MonoObjectHandle res
= MONO_HANDLE_NEW (MonoObject
, mono_value_box_checked (domain
, klass
, ((char*)val
) + sizeof(MonoObject
), error
)); /* FIXME use handles in mono_value_box_checked */
2057 mono_gchandle_free (gchandle
);
2058 goto_if_nok (error
, leave
);
2059 MONO_HANDLE_ASSIGN (result
, res
);
2062 case MONO_TYPE_STRING
: {
2063 MonoStringHandle str
= MONO_HANDLE_CAST (MonoString
, val
);
2064 uint32_t gchandle
= mono_gchandle_from_handle (val
, TRUE
);
2065 MonoStringHandle res
= mono_string_new_utf16_handle (domain
, mono_string_chars (MONO_HANDLE_RAW (str
)), mono_string_handle_length (str
), error
);
2066 mono_gchandle_free (gchandle
);
2067 goto_if_nok (error
, leave
);
2068 MONO_HANDLE_ASSIGN (result
, res
);
2071 case MONO_TYPE_ARRAY
:
2072 case MONO_TYPE_SZARRAY
: {
2073 MonoArrayHandle arr
= MONO_HANDLE_CAST (MonoArray
, val
);
2074 MonoXDomainMarshalType mt
= mono_get_xdomain_marshal_type (m_class_get_byval_arg (m_class_get_element_class (klass
)));
2075 if (mt
== MONO_MARSHAL_SERIALIZE
)
2077 MonoArrayHandle acopy
= mono_array_clone_in_domain (domain
, arr
, error
);
2078 goto_if_nok (error
, leave
);
2080 if (mt
== MONO_MARSHAL_COPY
) {
2081 int i
, len
= mono_array_handle_length (acopy
);
2082 for (i
= 0; i
< len
; i
++) {
2083 if (!xdomain_copy_array_element_inplace (acopy
, i
, error
))
2087 MONO_HANDLE_ASSIGN (result
, acopy
);
2098 /* mono_marshal_xdomain_copy_value
2099 * Makes a copy of "val" suitable for the current domain.
2102 mono_marshal_xdomain_copy_value (MonoObject
* val_raw
, MonoError
*error
)
2104 HANDLE_FUNCTION_ENTER ();
2105 /* FIXME callers of mono_marshal_xdomain_copy_value should use handles */
2106 MONO_HANDLE_DCL (MonoObject
, val
);
2107 MonoObjectHandle result
= mono_marshal_xdomain_copy_value_handle (val
, error
);
2108 HANDLE_FUNCTION_RETURN_OBJ (result
);
2111 /* mono_marshal_xdomain_copy_value
2112 * Makes a copy of "val" suitable for the current domain.
2115 ves_icall_mono_marshal_xdomain_copy_value (MonoObject
*val
)
2118 MonoObject
*result
= mono_marshal_xdomain_copy_value (val
, error
);
2119 mono_error_set_pending_exception (error
);
2124 mono_context_set_icall (MonoAppContext
*new_context_raw
)
2126 HANDLE_FUNCTION_ENTER ();
2127 MONO_HANDLE_DCL (MonoAppContext
, new_context
);
2128 mono_context_set_handle (new_context
);
2129 HANDLE_FUNCTION_RETURN ();
2132 static MonoAppContext
*
2133 mono_context_get_icall (void)
2135 HANDLE_FUNCTION_ENTER ();
2136 MonoAppContextHandle context
= mono_context_get_handle ();
2137 HANDLE_FUNCTION_RETURN_OBJ (context
);