remoting.c 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180
  1. /**
  2. * \file
  3. * Remoting support
  4. *
  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)
  8. *
  9. * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  10. */
  11. #include "config.h"
  12. #include "mono/metadata/handle.h"
  13. #include "mono/metadata/method-builder-ilgen-internals.h"
  14. #include "mono/metadata/remoting.h"
  15. #include "mono/metadata/marshal.h"
  16. #include "mono/metadata/marshal-internals.h"
  17. #include "mono/metadata/abi-details.h"
  18. #include "mono/metadata/class-init.h"
  19. #include "mono/metadata/cominterop.h"
  20. #include "mono/metadata/tabledefs.h"
  21. #include "mono/metadata/exception.h"
  22. #include "mono/metadata/debug-helpers.h"
  23. #include "mono/metadata/domain-internals.h"
  24. #include "mono/metadata/reflection-internals.h"
  25. #include "mono/metadata/assembly.h"
  26. #include "icall-decl.h"
  27. #include "icall-signatures.h"
  28. typedef enum {
  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;
  34. #ifndef DISABLE_REMOTING
  35. #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
  36. a = i,
  37. enum {
  38. #include "mono/cil/opcode.def"
  39. LAST = 0xff
  40. };
  41. #undef OPDEF
  42. struct _MonoRemotingMethods {
  43. MonoMethod *invoke;
  44. MonoMethod *invoke_with_check;
  45. MonoMethod *xdomain_invoke;
  46. MonoMethod *xdomain_dispatch;
  47. };
  48. typedef struct _MonoRemotingMethods MonoRemotingMethods;
  49. static MonoObject *
  50. mono_remoting_wrapper (MonoMethod *method, gpointer *params);
  51. static MonoException *
  52. mono_remoting_update_exception (MonoException *exc);
  53. static gint32
  54. mono_marshal_set_domain_by_id (gint32 id, MonoBoolean push);
  55. static gboolean
  56. mono_marshal_check_domain_image (gint32 domain_id, MonoImage *image);
  57. MONO_API void
  58. mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy);
  59. static MonoXDomainMarshalType
  60. mono_get_xdomain_marshal_type (MonoType *t);
  61. static void
  62. mono_marshal_xdomain_copy_out_value (MonoObject *src, MonoObject *dst);
  63. static MonoReflectionType *
  64. type_from_handle (MonoType *handle);
  65. static void
  66. mono_context_set_icall (MonoAppContext *new_context);
  67. static MonoAppContext*
  68. mono_context_get_icall (void);
  69. static MonoObject*
  70. mono_marshal_xdomain_copy_value (MonoObject* val_raw, MonoError *error);
  71. /* Class lazy loading functions */
  72. static GENERATE_GET_CLASS_WITH_CACHE (remoting_services, "System.Runtime.Remoting", "RemotingServices")
  73. static GENERATE_GET_CLASS_WITH_CACHE (call_context, "System.Runtime.Remoting.Messaging", "CallContext")
  74. static GENERATE_GET_CLASS_WITH_CACHE (context, "System.Runtime.Remoting.Contexts", "Context")
  75. static mono_mutex_t remoting_mutex;
  76. static gboolean remoting_mutex_inited;
  77. static MonoClass *byte_array_class;
  78. #ifndef DISABLE_JIT
  79. static MonoMethod *method_rs_serialize, *method_rs_deserialize, *method_exc_fixexc, *method_rs_appdomain_target;
  80. static MonoMethod *method_set_call_context, *method_needs_context_sink, *method_rs_serialize_exc;
  81. #endif
  82. static gpointer
  83. mono_compile_method_icall (MonoMethod *method);
  84. // func is an identifier, that names a function, and is also in jit-icall-reg.h,
  85. // and therefore a field in mono_jit_icall_info and can be token pasted into an enum value.
  86. //
  87. // The name of func must be linkable for AOT, for example g_free does not work (monoeg_g_free instead),
  88. // nor does the C++ overload fmod (mono_fmod instead). These functions therefore
  89. // must be extern "C".
  90. //
  91. // This is not the same as other register_icall (last parameter NULL vs. #func)
  92. #define register_icall(func, sig, save) \
  93. (mono_register_jit_icall_info (&mono_get_jit_icall_info ()->func, func, #func, (sig), (save), NULL))
  94. static void
  95. remoting_lock (void)
  96. {
  97. g_assert (remoting_mutex_inited);
  98. mono_os_mutex_lock (&remoting_mutex);
  99. }
  100. static void
  101. remoting_unlock (void)
  102. {
  103. g_assert (remoting_mutex_inited);
  104. mono_os_mutex_unlock (&remoting_mutex);
  105. }
  106. /*
  107. * Return the hash table pointed to by VAR, lazily creating it if neccesary.
  108. */
  109. static GHashTable*
  110. get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func)
  111. {
  112. if (!(*var)) {
  113. remoting_lock ();
  114. if (!(*var)) {
  115. GHashTable *cache =
  116. g_hash_table_new (hash_func, equal_func);
  117. mono_memory_barrier ();
  118. *var = cache;
  119. }
  120. remoting_unlock ();
  121. }
  122. return *var;
  123. }
  124. static GHashTable*
  125. get_cache_full (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
  126. {
  127. if (!(*var)) {
  128. remoting_lock ();
  129. if (!(*var)) {
  130. GHashTable *cache =
  131. g_hash_table_new_full (hash_func, equal_func, key_destroy_func, value_destroy_func);
  132. mono_memory_barrier ();
  133. *var = cache;
  134. }
  135. remoting_unlock ();
  136. }
  137. return *var;
  138. }
  139. void
  140. mono_remoting_init (void)
  141. {
  142. mono_os_mutex_init (&remoting_mutex);
  143. remoting_mutex_inited = TRUE;
  144. }
  145. static void
  146. mono_remoting_marshal_init (void)
  147. {
  148. ERROR_DECL (error);
  149. MonoClass *klass;
  150. static gboolean module_initialized = FALSE;
  151. static gboolean icalls_registered = FALSE;
  152. if (module_initialized)
  153. return;
  154. byte_array_class = mono_class_create_array (mono_defaults.byte_class, 1);
  155. #ifndef DISABLE_JIT
  156. klass = mono_class_get_remoting_services_class ();
  157. method_rs_serialize = mono_class_get_method_from_name_checked (klass, "SerializeCallData", -1, 0, error);
  158. mono_error_assert_ok (error);
  159. g_assert (method_rs_serialize);
  160. method_rs_deserialize = mono_class_get_method_from_name_checked (klass, "DeserializeCallData", -1, 0, error);
  161. mono_error_assert_ok (error);
  162. g_assert (method_rs_deserialize);
  163. method_rs_serialize_exc = mono_class_get_method_from_name_checked (klass, "SerializeExceptionData", -1, 0, error);
  164. mono_error_assert_ok (error);
  165. g_assert (method_rs_serialize_exc);
  166. klass = mono_defaults.real_proxy_class;
  167. method_rs_appdomain_target = mono_class_get_method_from_name_checked (klass, "GetAppDomainTarget", -1, 0, error);
  168. mono_error_assert_ok (error);
  169. g_assert (method_rs_appdomain_target);
  170. klass = mono_defaults.exception_class;
  171. method_exc_fixexc = mono_class_get_method_from_name_checked (klass, "FixRemotingException", -1, 0, error);
  172. mono_error_assert_ok (error);
  173. g_assert (method_exc_fixexc);
  174. klass = mono_class_get_call_context_class ();
  175. method_set_call_context = mono_class_get_method_from_name_checked (klass, "SetCurrentCallContext", -1, 0, error);
  176. mono_error_assert_ok (error);
  177. g_assert (method_set_call_context);
  178. klass = mono_class_get_context_class ();
  179. method_needs_context_sink = mono_class_get_method_from_name_checked (klass, "get_NeedsContextSink", -1, 0, error);
  180. mono_error_assert_ok (error);
  181. g_assert (method_needs_context_sink);
  182. #endif
  183. mono_loader_lock ();
  184. if (!icalls_registered) {
  185. register_icall (type_from_handle, mono_icall_sig_object_ptr, FALSE);
  186. register_icall (mono_marshal_set_domain_by_id, mono_icall_sig_int32_int32_int32, FALSE);
  187. register_icall (mono_marshal_check_domain_image, mono_icall_sig_int32_int32_ptr, FALSE);
  188. register_icall (ves_icall_mono_marshal_xdomain_copy_value, mono_icall_sig_object_object, FALSE);
  189. register_icall (mono_marshal_xdomain_copy_out_value, mono_icall_sig_void_object_object, FALSE);
  190. register_icall (mono_remoting_wrapper, mono_icall_sig_object_ptr_ptr, FALSE);
  191. register_icall (mono_remoting_update_exception, mono_icall_sig_object_object, FALSE);
  192. register_icall (mono_upgrade_remote_class_wrapper, mono_icall_sig_void_object_object, FALSE);
  193. #ifndef DISABLE_JIT
  194. register_icall (mono_compile_method_icall, mono_icall_sig_ptr_ptr, FALSE);
  195. #endif
  196. register_icall (mono_context_get_icall, mono_icall_sig_object, FALSE);
  197. register_icall (mono_context_set_icall, mono_icall_sig_void_object, FALSE);
  198. }
  199. icalls_registered = TRUE;
  200. mono_loader_unlock ();
  201. module_initialized = TRUE;
  202. }
  203. // This is an icall, it will return NULL and set pending exception (in
  204. // mono_type_from_handle wrapper) on failure.
  205. static MonoReflectionType *
  206. type_from_handle (MonoType *handle)
  207. {
  208. return mono_type_from_handle (handle);
  209. }
  210. #ifndef DISABLE_JIT
  211. static int
  212. mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
  213. {
  214. int pos;
  215. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoObject, vtable));
  216. mono_mb_emit_byte (mb, CEE_LDIND_I);
  217. mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoVTable, klass));
  218. mono_mb_emit_byte (mb, CEE_ADD);
  219. mono_mb_emit_byte (mb, CEE_LDIND_I);
  220. mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
  221. mono_mb_emit_byte (mb, CEE_MONO_CLASSCONST);
  222. mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
  223. pos = mono_mb_emit_branch (mb, branch_code);
  224. return pos;
  225. }
  226. static int
  227. mono_mb_emit_xdomain_check (MonoMethodBuilder *mb, int branch_code)
  228. {
  229. int pos;
  230. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
  231. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  232. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRealProxy, target_domain_id));
  233. mono_mb_emit_byte (mb, CEE_LDIND_I4);
  234. mono_mb_emit_icon (mb, -1);
  235. pos = mono_mb_emit_branch (mb, branch_code);
  236. return pos;
  237. }
  238. static int
  239. mono_mb_emit_contextbound_check (MonoMethodBuilder *mb, int branch_code)
  240. {
  241. static int offset = -1;
  242. static guint8 mask;
  243. if (offset < 0)
  244. mono_class_contextbound_bit_offset (&offset, &mask);
  245. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
  246. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  247. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
  248. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  249. mono_mb_emit_ldflda (mb, offset);
  250. mono_mb_emit_byte (mb, CEE_LDIND_U1);
  251. mono_mb_emit_icon (mb, mask);
  252. mono_mb_emit_byte (mb, CEE_AND);
  253. mono_mb_emit_icon (mb, 0);
  254. return mono_mb_emit_branch (mb, branch_code);
  255. }
  256. #endif /* !DISABLE_JIT */
  257. static MonoMethod*
  258. mono_marshal_remoting_find_in_cache (MonoMethod *method, int wrapper_type)
  259. {
  260. MonoMethod *res = NULL;
  261. MonoRemotingMethods *wrps = NULL;
  262. mono_marshal_lock_internal ();
  263. if (mono_method_get_wrapper_cache (method)->remoting_invoke_cache)
  264. wrps = (MonoRemotingMethods *)g_hash_table_lookup (mono_method_get_wrapper_cache (method)->remoting_invoke_cache, method);
  265. if (wrps) {
  266. switch (wrapper_type) {
  267. case MONO_WRAPPER_REMOTING_INVOKE: res = wrps->invoke; break;
  268. case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: res = wrps->invoke_with_check; break;
  269. case MONO_WRAPPER_XDOMAIN_INVOKE: res = wrps->xdomain_invoke; break;
  270. case MONO_WRAPPER_XDOMAIN_DISPATCH: res = wrps->xdomain_dispatch; break;
  271. }
  272. }
  273. /* it is important to do the unlock after the load from wrps, since in
  274. * mono_remoting_mb_create_and_cache () we drop the marshal lock to be able
  275. * to take the loader lock and some other thread may set the fields.
  276. */
  277. mono_marshal_unlock_internal ();
  278. return res;
  279. }
  280. /* Create the method from the builder and place it in the cache */
  281. static MonoMethod*
  282. mono_remoting_mb_create_and_cache (MonoMethod *key, MonoMethodBuilder *mb,
  283. MonoMethodSignature *sig, int max_stack, WrapperInfo *info)
  284. {
  285. MonoMethod **res = NULL;
  286. MonoRemotingMethods *wrps;
  287. GHashTable *cache;
  288. cache = get_cache_full (&mono_method_get_wrapper_cache (key)->remoting_invoke_cache, mono_aligned_addr_hash, NULL, NULL, g_free);
  289. mono_marshal_lock_internal ();
  290. wrps = (MonoRemotingMethods *)g_hash_table_lookup (cache, key);
  291. if (!wrps) {
  292. wrps = g_new0 (MonoRemotingMethods, 1);
  293. g_hash_table_insert (cache, key, wrps);
  294. }
  295. switch (mb->method->wrapper_type) {
  296. case MONO_WRAPPER_REMOTING_INVOKE: res = &wrps->invoke; break;
  297. case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: res = &wrps->invoke_with_check; break;
  298. case MONO_WRAPPER_XDOMAIN_INVOKE: res = &wrps->xdomain_invoke; break;
  299. case MONO_WRAPPER_XDOMAIN_DISPATCH: res = &wrps->xdomain_dispatch; break;
  300. default: g_assert_not_reached (); break;
  301. }
  302. mono_marshal_unlock_internal ();
  303. if (*res == NULL) {
  304. MonoMethod *newm;
  305. newm = mono_mb_create_method (mb, sig, max_stack);
  306. mono_marshal_lock_internal ();
  307. if (!*res) {
  308. *res = newm;
  309. mono_marshal_set_wrapper_info (*res, info);
  310. mono_marshal_unlock_internal ();
  311. } else {
  312. mono_marshal_unlock_internal ();
  313. mono_free_method (newm);
  314. }
  315. }
  316. return *res;
  317. }
  318. static MonoObject *
  319. mono_remoting_wrapper (MonoMethod *method, gpointer *params)
  320. {
  321. ERROR_DECL (error);
  322. MonoMethodMessage *msg;
  323. MonoTransparentProxy *this_obj;
  324. MonoObject *res, *exc;
  325. MonoArray *out_args;
  326. this_obj = *((MonoTransparentProxy **)params [0]);
  327. g_assert (this_obj);
  328. g_assert (mono_object_is_transparent_proxy (this_obj));
  329. /* skip the this pointer */
  330. params++;
  331. if (mono_class_is_contextbound (this_obj->remote_class->proxy_class) && this_obj->rp->context == (MonoObject *) mono_context_get ())
  332. {
  333. int i;
  334. MonoMethodSignature *sig = mono_method_signature_internal (method);
  335. int count = sig->param_count;
  336. gpointer* mparams = g_newa (gpointer, count);
  337. for (i=0; i<count; i++) {
  338. MonoClass *klass = mono_class_from_mono_type_internal (sig->params [i]);
  339. if (m_class_is_valuetype (klass)) {
  340. if (sig->params [i]->byref) {
  341. mparams[i] = *((gpointer *)params [i]);
  342. } else {
  343. /* runtime_invoke expects a boxed instance */
  344. if (mono_class_is_nullable (mono_class_from_mono_type_internal (sig->params [i]))) {
  345. mparams[i] = mono_nullable_box ((guint8 *)params [i], klass, error);
  346. goto_if_nok (error, fail);
  347. } else
  348. mparams[i] = params [i];
  349. }
  350. } else {
  351. mparams[i] = *((gpointer**)params [i]);
  352. }
  353. }
  354. res = mono_runtime_invoke_checked (method, m_class_is_valuetype (method->klass)? mono_object_unbox_internal ((MonoObject*)this_obj): this_obj, mparams, error);
  355. goto_if_nok (error, fail);
  356. return res;
  357. }
  358. msg = mono_method_call_message_new (method, params, NULL, NULL, NULL, error);
  359. goto_if_nok (error, fail);
  360. res = mono_remoting_invoke ((MonoObject *)this_obj->rp, msg, &exc, &out_args, error);
  361. goto_if_nok (error, fail);
  362. if (exc) {
  363. error_init (error);
  364. exc = (MonoObject*) mono_remoting_update_exception ((MonoException*)exc);
  365. mono_error_set_exception_instance (error, (MonoException *)exc);
  366. goto fail;
  367. }
  368. mono_method_return_message_restore (method, params, out_args, error);
  369. goto_if_nok (error, fail);
  370. return res;
  371. fail:
  372. mono_error_set_pending_exception (error);
  373. return NULL;
  374. }
  375. /*
  376. * Handles exception transformation at appdomain call boundary.
  377. * Note this is called from target appdomain inside xdomain wrapper, but from
  378. * source domain in the mono_remoting_wrapper slowpath.
  379. */
  380. static MonoException *
  381. mono_remoting_update_exception (MonoException *exc)
  382. {
  383. MonoInternalThread *thread;
  384. MonoClass *klass = mono_object_class (exc);
  385. /* Serialization error can only happen when still in the target appdomain */
  386. if (!(mono_class_get_flags (klass) & TYPE_ATTRIBUTE_SERIALIZABLE)) {
  387. MonoException *ret;
  388. char *aname = mono_stringify_assembly_name (&m_class_get_image (klass)->assembly->aname);
  389. char *message = g_strdup_printf ("Type '%s' in Assembly '%s' is not marked as serializable", m_class_get_name (klass), aname);
  390. ret = mono_get_exception_serialization (message);
  391. g_free (aname);
  392. g_free (message);
  393. return ret;
  394. }
  395. thread = mono_thread_internal_current ();
  396. if (mono_object_class (exc) == mono_defaults.threadabortexception_class &&
  397. thread->flags & MONO_THREAD_FLAG_APPDOMAIN_ABORT) {
  398. mono_thread_internal_reset_abort (thread);
  399. return mono_get_exception_appdomain_unloaded ();
  400. }
  401. return exc;
  402. }
  403. /**
  404. * mono_marshal_get_remoting_invoke:
  405. */
  406. MonoMethod *
  407. mono_marshal_get_remoting_invoke (MonoMethod *method, MonoError *error)
  408. {
  409. MonoMethodSignature *sig;
  410. MonoMethodBuilder *mb;
  411. MonoMethod *res;
  412. int params_var;
  413. WrapperInfo *info;
  414. g_assert (method);
  415. error_init (error);
  416. if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE || method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE)
  417. return method;
  418. /* this seems to be the best plase to put this, as all remoting invokes seem to get filtered through here */
  419. #ifndef DISABLE_COM
  420. if (mono_class_is_com_object (method->klass) || method->klass == mono_class_try_get_com_object_class ()) {
  421. MonoVTable *vtable = mono_class_vtable_checked (mono_domain_get (), method->klass, error);
  422. return_val_if_nok (error, NULL);
  423. if (!mono_vtable_is_remote (vtable)) {
  424. return mono_cominterop_get_invoke (method);
  425. }
  426. }
  427. #endif
  428. sig = mono_signature_no_pinvoke (method);
  429. /* we cant remote methods without this pointer */
  430. if (!sig->hasthis)
  431. return method;
  432. if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_REMOTING_INVOKE)))
  433. return res;
  434. mono_remoting_marshal_init ();
  435. mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
  436. #ifndef DISABLE_JIT
  437. mb->method->save_lmf = 1;
  438. params_var = mono_mb_emit_save_args (mb, sig, TRUE);
  439. mono_mb_emit_ptr (mb, method);
  440. mono_mb_emit_ldloc (mb, params_var);
  441. mono_mb_emit_icall (mb, mono_remoting_wrapper);
  442. // FIXME: this interrupt checkpoint code is a no-op since 'mb'
  443. // is a MONO_WRAPPER_REMOTING_INVOKE, and
  444. // mono_thread_interruption_checkpoint_request (FALSE)
  445. // considers such wrappers "protected" and always returns
  446. // NULL as if there's no pending interruption.
  447. mono_marshal_emit_thread_interrupt_checkpoint (mb);
  448. if (sig->ret->type == MONO_TYPE_VOID) {
  449. mono_mb_emit_byte (mb, CEE_POP);
  450. mono_mb_emit_byte (mb, CEE_RET);
  451. } else {
  452. mono_mb_emit_restore_result (mb, sig->ret);
  453. }
  454. #endif
  455. info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
  456. info->d.remoting.method = method;
  457. res = mono_remoting_mb_create_and_cache (method, mb, sig, sig->param_count + 16, info);
  458. mono_mb_free (mb);
  459. return res;
  460. }
  461. /* mono_marshal_xdomain_copy_out_value()
  462. * Copies the contents of the src instance into the dst instance. src and dst
  463. * must have the same type, and if they are arrays, the same size.
  464. *
  465. * This is an icall, it may use mono_error_set_pending_exception
  466. */
  467. static void
  468. mono_marshal_xdomain_copy_out_value (MonoObject *src, MonoObject *dst)
  469. {
  470. ERROR_DECL (error);
  471. if (src == NULL || dst == NULL) return;
  472. g_assert (mono_object_class (src) == mono_object_class (dst));
  473. switch (m_class_get_byval_arg (mono_object_class (src))->type) {
  474. case MONO_TYPE_ARRAY:
  475. case MONO_TYPE_SZARRAY: {
  476. int mt = mono_get_xdomain_marshal_type (m_class_get_byval_arg (m_class_get_element_class (mono_object_class (src))));
  477. if (mt == MONO_MARSHAL_SERIALIZE) return;
  478. if (mt == MONO_MARSHAL_COPY) {
  479. int i, len = mono_array_length_internal ((MonoArray *)dst);
  480. for (i = 0; i < len; i++) {
  481. MonoObject *item = (MonoObject *)mono_array_get_internal ((MonoArray *)src, gpointer, i);
  482. MonoObject *item_copy = mono_marshal_xdomain_copy_value (item, error);
  483. if (mono_error_set_pending_exception (error))
  484. return;
  485. mono_array_setref_internal ((MonoArray *)dst, i, item_copy);
  486. }
  487. } else {
  488. mono_array_full_copy ((MonoArray *)src, (MonoArray *)dst);
  489. }
  490. return;
  491. }
  492. default:
  493. break;
  494. }
  495. }
  496. #if !defined (DISABLE_JIT)
  497. static void
  498. mono_marshal_emit_xdomain_copy_value (MonoMethodBuilder *mb, MonoClass *pclass)
  499. {
  500. mono_mb_emit_icall (mb, ves_icall_mono_marshal_xdomain_copy_value);
  501. mono_mb_emit_op (mb, CEE_CASTCLASS, pclass);
  502. }
  503. static void
  504. mono_marshal_emit_xdomain_copy_out_value (MonoMethodBuilder *mb, MonoClass *pclass)
  505. {
  506. mono_mb_emit_icall (mb, mono_marshal_xdomain_copy_out_value);
  507. }
  508. #endif
  509. /* mono_marshal_supports_fast_xdomain()
  510. * Returns TRUE if the method can use the fast xdomain wrapper.
  511. */
  512. static gboolean
  513. mono_marshal_supports_fast_xdomain (MonoMethod *method)
  514. {
  515. return !mono_class_is_contextbound (method->klass) &&
  516. !((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && (strcmp (".ctor", method->name) == 0));
  517. }
  518. static gint32
  519. mono_marshal_set_domain_by_id (gint32 id, MonoBoolean push)
  520. {
  521. MonoDomain *current_domain = mono_domain_get ();
  522. MonoDomain *domain = mono_domain_get_by_id (id);
  523. if (!domain || !mono_domain_set_fast (domain, FALSE)) {
  524. mono_set_pending_exception (mono_get_exception_appdomain_unloaded ());
  525. return 0;
  526. }
  527. if (push)
  528. mono_thread_push_appdomain_ref (domain);
  529. else
  530. mono_thread_pop_appdomain_ref ();
  531. return current_domain->domain_id;
  532. }
  533. #if !defined (DISABLE_JIT)
  534. static void
  535. mono_marshal_emit_switch_domain (MonoMethodBuilder *mb)
  536. {
  537. mono_mb_emit_icall (mb, mono_marshal_set_domain_by_id);
  538. }
  539. gpointer
  540. mono_compile_method_icall (MonoMethod *method)
  541. {
  542. ERROR_DECL (error);
  543. gpointer result = mono_compile_method_checked (method, error);
  544. mono_error_set_pending_exception (error);
  545. return result;
  546. }
  547. /* mono_marshal_emit_load_domain_method ()
  548. * Loads into the stack a pointer to the code of the provided method for
  549. * the current domain.
  550. */
  551. static void
  552. mono_marshal_emit_load_domain_method (MonoMethodBuilder *mb, MonoMethod *method)
  553. {
  554. /* We need a pointer to the method for the running domain (not the domain
  555. * that compiles the method).
  556. */
  557. mono_mb_emit_ptr (mb, method);
  558. mono_mb_emit_icall (mb, mono_compile_method_icall);
  559. }
  560. #endif
  561. /* mono_marshal_check_domain_image ()
  562. * Returns TRUE if the image is loaded in the specified
  563. * application domain.
  564. */
  565. static gboolean
  566. mono_marshal_check_domain_image (gint32 domain_id, MonoImage *image)
  567. {
  568. MonoAssembly* ass;
  569. GSList *tmp;
  570. MonoDomain *domain = mono_domain_get_by_id (domain_id);
  571. if (!domain)
  572. return FALSE;
  573. mono_domain_assemblies_lock (domain);
  574. for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
  575. ass = (MonoAssembly *)tmp->data;
  576. if (ass->image == image)
  577. break;
  578. }
  579. mono_domain_assemblies_unlock (domain);
  580. return tmp != NULL;
  581. }
  582. /* mono_marshal_get_xappdomain_dispatch ()
  583. * Generates a method that dispatches a method call from another domain into
  584. * the current domain.
  585. */
  586. static MonoMethod *
  587. mono_marshal_get_xappdomain_dispatch (MonoMethod *method, int *marshal_types, int complex_count, int complex_out_count, int ret_marshal_type)
  588. {
  589. MonoMethodSignature *sig, *csig;
  590. MonoMethodBuilder *mb;
  591. MonoMethod *res;
  592. int i, j, param_index, copy_locals_base;
  593. MonoClass *ret_class = NULL;
  594. int loc_array=0, loc_return=0, loc_serialized_exc=0;
  595. MonoExceptionClause *main_clause;
  596. int pos, pos_leave;
  597. gboolean copy_return;
  598. WrapperInfo *info;
  599. if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_XDOMAIN_DISPATCH)))
  600. return res;
  601. sig = mono_method_signature_internal (method);
  602. copy_return = (sig->ret->type != MONO_TYPE_VOID && ret_marshal_type != MONO_MARSHAL_SERIALIZE);
  603. j = 0;
  604. csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3 + sig->param_count - complex_count);
  605. csig->params [j++] = mono_get_object_type ();
  606. csig->params [j++] = m_class_get_this_arg (byte_array_class);
  607. csig->params [j++] = m_class_get_this_arg (byte_array_class);
  608. for (i = 0; i < sig->param_count; i++) {
  609. if (marshal_types [i] != MONO_MARSHAL_SERIALIZE)
  610. csig->params [j++] = sig->params [i];
  611. }
  612. if (copy_return)
  613. csig->ret = sig->ret;
  614. else
  615. csig->ret = mono_get_void_type ();
  616. csig->pinvoke = 1;
  617. csig->hasthis = FALSE;
  618. mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_XDOMAIN_DISPATCH);
  619. mb->method->save_lmf = 1;
  620. #ifndef DISABLE_JIT
  621. /* Locals */
  622. loc_serialized_exc = mono_mb_add_local (mb, m_class_get_byval_arg (byte_array_class));
  623. if (complex_count > 0)
  624. loc_array = mono_mb_add_local (mb, mono_get_object_type ());
  625. if (sig->ret->type != MONO_TYPE_VOID) {
  626. loc_return = mono_mb_add_local (mb, sig->ret);
  627. ret_class = mono_class_from_mono_type_internal (sig->ret);
  628. }
  629. /* try */
  630. main_clause = (MonoExceptionClause *)mono_image_alloc0 (m_class_get_image (method->klass), sizeof (MonoExceptionClause));
  631. main_clause->try_offset = mono_mb_get_label (mb);
  632. /* Clean the call context */
  633. mono_mb_emit_byte (mb, CEE_LDNULL);
  634. mono_mb_emit_managed_call (mb, method_set_call_context, NULL);
  635. mono_mb_emit_byte (mb, CEE_POP);
  636. /* Deserialize call data */
  637. mono_mb_emit_ldarg (mb, 1);
  638. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  639. pos = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
  640. mono_mb_emit_ldarg (mb, 1);
  641. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  642. mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
  643. mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
  644. if (complex_count > 0)
  645. mono_mb_emit_stloc (mb, loc_array);
  646. else
  647. mono_mb_emit_byte (mb, CEE_POP);
  648. mono_mb_patch_short_branch (mb, pos);
  649. /* Get the target object */
  650. mono_mb_emit_ldarg (mb, 0);
  651. mono_mb_emit_managed_call (mb, method_rs_appdomain_target, NULL);
  652. /* Load the arguments */
  653. copy_locals_base = mb->locals;
  654. param_index = 3; // Index of the first non-serialized parameter of this wrapper
  655. j = 0;
  656. for (i = 0; i < sig->param_count; i++) {
  657. MonoType *pt = sig->params [i];
  658. MonoClass *pclass = mono_class_from_mono_type_internal (pt);
  659. switch (marshal_types [i]) {
  660. case MONO_MARSHAL_SERIALIZE: {
  661. /* take the value from the serialized array */
  662. mono_mb_emit_ldloc (mb, loc_array);
  663. mono_mb_emit_icon (mb, j++);
  664. if (pt->byref) {
  665. if (m_class_is_valuetype (pclass)) {
  666. mono_mb_emit_byte (mb, CEE_LDELEM_REF);
  667. mono_mb_emit_op (mb, CEE_UNBOX, pclass);
  668. } else {
  669. mono_mb_emit_op (mb, CEE_LDELEMA, pclass);
  670. }
  671. } else {
  672. if (m_class_is_valuetype (pclass)) {
  673. mono_mb_emit_byte (mb, CEE_LDELEM_REF);
  674. mono_mb_emit_op (mb, CEE_UNBOX, pclass);
  675. mono_mb_emit_op (mb, CEE_LDOBJ, pclass);
  676. } else {
  677. mono_mb_emit_byte (mb, CEE_LDELEM_REF);
  678. if (pclass != mono_defaults.object_class) {
  679. mono_mb_emit_op (mb, CEE_CASTCLASS, pclass);
  680. }
  681. }
  682. }
  683. break;
  684. }
  685. case MONO_MARSHAL_COPY_OUT: {
  686. /* Keep a local copy of the value since we need to copy it back after the call */
  687. int copy_local = mono_mb_add_local (mb, m_class_get_byval_arg (pclass));
  688. mono_mb_emit_ldarg (mb, param_index++);
  689. mono_marshal_emit_xdomain_copy_value (mb, pclass);
  690. mono_mb_emit_byte (mb, CEE_DUP);
  691. mono_mb_emit_stloc (mb, copy_local);
  692. break;
  693. }
  694. case MONO_MARSHAL_COPY: {
  695. mono_mb_emit_ldarg (mb, param_index);
  696. if (pt->byref) {
  697. mono_mb_emit_byte (mb, CEE_DUP);
  698. mono_mb_emit_byte (mb, CEE_DUP);
  699. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  700. mono_marshal_emit_xdomain_copy_value (mb, pclass);
  701. mono_mb_emit_byte (mb, CEE_STIND_REF);
  702. } else {
  703. mono_marshal_emit_xdomain_copy_value (mb, pclass);
  704. }
  705. param_index++;
  706. break;
  707. }
  708. case MONO_MARSHAL_NONE:
  709. mono_mb_emit_ldarg (mb, param_index++);
  710. break;
  711. }
  712. }
  713. /* Make the call to the real object */
  714. mono_marshal_emit_thread_force_interrupt_checkpoint (mb);
  715. mono_mb_emit_op (mb, CEE_CALLVIRT, method);
  716. if (sig->ret->type != MONO_TYPE_VOID)
  717. mono_mb_emit_stloc (mb, loc_return);
  718. /* copy back MONO_MARSHAL_COPY_OUT parameters */
  719. j = 0;
  720. param_index = 3;
  721. for (i = 0; i < sig->param_count; i++) {
  722. if (marshal_types [i] == MONO_MARSHAL_SERIALIZE) continue;
  723. if (marshal_types [i] == MONO_MARSHAL_COPY_OUT) {
  724. mono_mb_emit_ldloc (mb, copy_locals_base + (j++));
  725. mono_mb_emit_ldarg (mb, param_index);
  726. mono_marshal_emit_xdomain_copy_out_value (mb, mono_class_from_mono_type_internal (sig->params [i]));
  727. }
  728. param_index++;
  729. }
  730. /* Serialize the return values */
  731. if (complex_out_count > 0) {
  732. /* Reset parameters in the array that don't need to be serialized back */
  733. j = 0;
  734. for (i = 0; i < sig->param_count; i++) {
  735. if (marshal_types[i] != MONO_MARSHAL_SERIALIZE) continue;
  736. if (!sig->params [i]->byref) {
  737. mono_mb_emit_ldloc (mb, loc_array);
  738. mono_mb_emit_icon (mb, j);
  739. mono_mb_emit_byte (mb, CEE_LDNULL);
  740. mono_mb_emit_byte (mb, CEE_STELEM_REF);
  741. }
  742. j++;
  743. }
  744. /* Add the return value to the array */
  745. if (ret_marshal_type == MONO_MARSHAL_SERIALIZE) {
  746. mono_mb_emit_ldloc (mb, loc_array);
  747. mono_mb_emit_icon (mb, complex_count); /* The array has an additional slot to hold the ret value */
  748. mono_mb_emit_ldloc (mb, loc_return);
  749. g_assert (ret_class); /*FIXME properly fail here*/
  750. if (m_class_is_valuetype (ret_class)) {
  751. mono_mb_emit_op (mb, CEE_BOX, ret_class);
  752. }
  753. mono_mb_emit_byte (mb, CEE_STELEM_REF);
  754. }
  755. /* Serialize */
  756. mono_mb_emit_ldarg (mb, 1);
  757. mono_mb_emit_ldloc (mb, loc_array);
  758. mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
  759. mono_mb_emit_byte (mb, CEE_STIND_REF);
  760. } else if (ret_marshal_type == MONO_MARSHAL_SERIALIZE) {
  761. mono_mb_emit_ldarg (mb, 1);
  762. mono_mb_emit_ldloc (mb, loc_return);
  763. if (m_class_is_valuetype (ret_class)) {
  764. mono_mb_emit_op (mb, CEE_BOX, ret_class);
  765. }
  766. mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
  767. mono_mb_emit_byte (mb, CEE_STIND_REF);
  768. } else {
  769. mono_mb_emit_ldarg (mb, 1);
  770. mono_mb_emit_byte (mb, CEE_LDNULL);
  771. mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
  772. mono_mb_emit_byte (mb, CEE_STIND_REF);
  773. }
  774. mono_mb_emit_ldarg (mb, 2);
  775. mono_mb_emit_byte (mb, CEE_LDNULL);
  776. mono_mb_emit_byte (mb, CEE_STIND_REF);
  777. pos_leave = mono_mb_emit_branch (mb, CEE_LEAVE);
  778. /* Main exception catch */
  779. main_clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
  780. main_clause->try_len = mono_mb_get_pos (mb) - main_clause->try_offset;
  781. main_clause->data.catch_class = mono_defaults.object_class;
  782. /* handler code */
  783. main_clause->handler_offset = mono_mb_get_label (mb);
  784. mono_mb_emit_icall (mb, mono_remoting_update_exception);
  785. mono_mb_emit_op (mb, CEE_CASTCLASS, mono_defaults.exception_class);
  786. mono_mb_emit_managed_call (mb, method_rs_serialize_exc, NULL);
  787. mono_mb_emit_stloc (mb, loc_serialized_exc);
  788. mono_mb_emit_ldarg (mb, 2);
  789. mono_mb_emit_ldloc (mb, loc_serialized_exc);
  790. mono_mb_emit_byte (mb, CEE_STIND_REF);
  791. mono_mb_emit_branch (mb, CEE_LEAVE);
  792. main_clause->handler_len = mono_mb_get_pos (mb) - main_clause->handler_offset;
  793. /* end catch */
  794. mono_mb_patch_branch (mb, pos_leave);
  795. if (copy_return)
  796. mono_mb_emit_ldloc (mb, loc_return);
  797. mono_mb_emit_byte (mb, CEE_RET);
  798. mono_mb_set_clauses (mb, 1, main_clause);
  799. #endif
  800. info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
  801. info->d.remoting.method = method;
  802. res = mono_remoting_mb_create_and_cache (method, mb, csig, csig->param_count + 16, info);
  803. mono_mb_free (mb);
  804. return res;
  805. }
  806. /**
  807. * mono_marshal_get_xappdomain_invoke:
  808. * Generates a fast remoting wrapper for cross app domain calls.
  809. */
  810. MonoMethod *
  811. mono_marshal_get_xappdomain_invoke (MonoMethod *method, MonoError *error)
  812. {
  813. MonoMethodSignature *sig;
  814. MonoMethodBuilder *mb;
  815. MonoMethod *res;
  816. int i, j, complex_count, complex_out_count, copy_locals_base;
  817. int *marshal_types;
  818. MonoClass *ret_class = NULL;
  819. MonoMethod *xdomain_method;
  820. int ret_marshal_type = MONO_MARSHAL_NONE;
  821. int loc_array=0, loc_serialized_data=-1, loc_real_proxy;
  822. int loc_old_domainid, loc_domainid, loc_return=0, loc_serialized_exc=0, loc_context;
  823. int pos, pos_dispatch, pos_noex;
  824. gboolean copy_return = FALSE;
  825. WrapperInfo *info;
  826. g_assert (method);
  827. error_init (error);
  828. if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE || method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE)
  829. return method;
  830. /* we cant remote methods without this pointer */
  831. if (!mono_method_signature_internal (method)->hasthis)
  832. return method;
  833. mono_remoting_marshal_init ();
  834. if (!mono_marshal_supports_fast_xdomain (method))
  835. return mono_marshal_get_remoting_invoke (method, error);
  836. if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_XDOMAIN_INVOKE)))
  837. return res;
  838. sig = mono_signature_no_pinvoke (method);
  839. mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_XDOMAIN_INVOKE);
  840. mb->method->save_lmf = 1;
  841. /* Count the number of parameters that need to be serialized */
  842. marshal_types = g_newa (int, sig->param_count);
  843. complex_count = complex_out_count = 0;
  844. gboolean has_byreflike = FALSE;
  845. for (i = 0; i < sig->param_count; i++) {
  846. MonoType *ptype = sig->params[i];
  847. int mt = mono_get_xdomain_marshal_type (ptype);
  848. /* If the [Out] attribute is applied to a parameter that can be internally copied,
  849. * the copy will be made by reusing the original object instance
  850. */
  851. if ((ptype->attrs & PARAM_ATTRIBUTE_OUT) != 0 && mt == MONO_MARSHAL_COPY && !ptype->byref)
  852. mt = MONO_MARSHAL_COPY_OUT;
  853. else if (mt == MONO_MARSHAL_SERIALIZE) {
  854. complex_count++;
  855. if (ptype->byref) complex_out_count++;
  856. }
  857. marshal_types [i] = mt;
  858. /* Can't make a xdomain wrapper for a method with an IsByRefLike result */
  859. if (!ptype->byref && m_class_is_byreflike (mono_class_from_mono_type_internal (ptype))) {
  860. has_byreflike = TRUE;
  861. }
  862. }
  863. if (sig->ret->type != MONO_TYPE_VOID) {
  864. ret_marshal_type = mono_get_xdomain_marshal_type (sig->ret);
  865. ret_class = mono_class_from_mono_type_internal (sig->ret);
  866. copy_return = ret_marshal_type != MONO_MARSHAL_SERIALIZE;
  867. }
  868. /* Can't make a xdomain wrapper for a method with an IsByRefLike result */
  869. if (!sig->ret->byref && m_class_is_byreflike (mono_class_from_mono_type_internal (sig->ret))) {
  870. has_byreflike = TRUE;
  871. }
  872. /* Locals */
  873. #ifndef DISABLE_JIT
  874. if (has_byreflike) {
  875. /* Make a wrapper that throws a NotImplementedException if it's ever called */
  876. mono_mb_emit_exception (mb, "NotImplementedException", "Cross AppDomain calls with IsByRefLike parameter or return types are not implemented");
  877. info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
  878. info->d.remoting.method = method;
  879. res = mono_remoting_mb_create_and_cache (method, mb, sig, sig->param_count + 16, info);
  880. mono_mb_free (mb);
  881. return res;
  882. }
  883. MonoType *object_type = mono_get_object_type ();
  884. MonoType *byte_array_type = m_class_get_byval_arg (byte_array_class);
  885. MonoType *int32_type = mono_get_int32_type ();
  886. if (complex_count > 0)
  887. loc_array = mono_mb_add_local (mb, object_type);
  888. loc_serialized_data = mono_mb_add_local (mb, byte_array_type);
  889. loc_real_proxy = mono_mb_add_local (mb, object_type);
  890. if (copy_return)
  891. loc_return = mono_mb_add_local (mb, sig->ret);
  892. loc_old_domainid = mono_mb_add_local (mb, int32_type);
  893. loc_domainid = mono_mb_add_local (mb, int32_type);
  894. loc_serialized_exc = mono_mb_add_local (mb, byte_array_type);
  895. loc_context = mono_mb_add_local (mb, object_type);
  896. /* Save thread domain data */
  897. mono_mb_emit_icall (mb, mono_context_get_icall);
  898. mono_mb_emit_byte (mb, CEE_DUP);
  899. mono_mb_emit_stloc (mb, loc_context);
  900. /* If the thread is not running in the default context, it needs to go
  901. * through the whole remoting sink, since the context is going to change
  902. */
  903. mono_mb_emit_managed_call (mb, method_needs_context_sink, NULL);
  904. pos = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
  905. /* Another case in which the fast path can't be used: when the target domain
  906. * has a different image for the same assembly.
  907. */
  908. /* Get the target domain id */
  909. mono_mb_emit_ldarg (mb, 0);
  910. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
  911. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  912. mono_mb_emit_byte (mb, CEE_DUP);
  913. mono_mb_emit_stloc (mb, loc_real_proxy);
  914. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRealProxy, target_domain_id));
  915. mono_mb_emit_byte (mb, CEE_LDIND_I4);
  916. mono_mb_emit_stloc (mb, loc_domainid);
  917. /* Check if the target domain has the same image for the required assembly */
  918. mono_mb_emit_ldloc (mb, loc_domainid);
  919. mono_mb_emit_ptr (mb, m_class_get_image (method->klass));
  920. mono_mb_emit_icall (mb, mono_marshal_check_domain_image);
  921. pos_dispatch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
  922. /* Use the whole remoting sink to dispatch this message */
  923. mono_mb_patch_short_branch (mb, pos);
  924. mono_mb_emit_ldarg (mb, 0);
  925. for (i = 0; i < sig->param_count; i++)
  926. mono_mb_emit_ldarg (mb, i + 1);
  927. MonoMethod * remoting_invoke_method = mono_marshal_get_remoting_invoke (method, error);
  928. if (!is_ok (error)) {
  929. mono_mb_free (mb);
  930. return NULL;
  931. }
  932. mono_mb_emit_managed_call (mb, remoting_invoke_method, NULL);
  933. mono_mb_emit_byte (mb, CEE_RET);
  934. mono_mb_patch_short_branch (mb, pos_dispatch);
  935. /* Create the array that will hold the parameters to be serialized */
  936. if (complex_count > 0) {
  937. 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 */
  938. mono_mb_emit_op (mb, CEE_NEWARR, mono_defaults.object_class);
  939. j = 0;
  940. for (i = 0; i < sig->param_count; i++) {
  941. MonoClass *pclass;
  942. if (marshal_types [i] != MONO_MARSHAL_SERIALIZE) continue;
  943. pclass = mono_class_from_mono_type_internal (sig->params[i]);
  944. mono_mb_emit_byte (mb, CEE_DUP);
  945. mono_mb_emit_icon (mb, j);
  946. mono_mb_emit_ldarg (mb, i + 1); /* 0=this */
  947. if (sig->params[i]->byref) {
  948. if (m_class_is_valuetype (pclass))
  949. mono_mb_emit_op (mb, CEE_LDOBJ, pclass);
  950. else
  951. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  952. }
  953. if (m_class_is_valuetype (pclass))
  954. mono_mb_emit_op (mb, CEE_BOX, pclass);
  955. mono_mb_emit_byte (mb, CEE_STELEM_REF);
  956. j++;
  957. }
  958. mono_mb_emit_stloc (mb, loc_array);
  959. /* Serialize parameters */
  960. mono_mb_emit_ldloc (mb, loc_array);
  961. mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
  962. mono_mb_emit_stloc (mb, loc_serialized_data);
  963. } else {
  964. mono_mb_emit_byte (mb, CEE_LDNULL);
  965. mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
  966. mono_mb_emit_stloc (mb, loc_serialized_data);
  967. }
  968. /* switch domain */
  969. mono_mb_emit_ldloc (mb, loc_domainid);
  970. mono_mb_emit_byte (mb, CEE_LDC_I4_1);
  971. mono_marshal_emit_switch_domain (mb);
  972. mono_mb_emit_stloc (mb, loc_old_domainid);
  973. /* Load the arguments */
  974. mono_mb_emit_ldloc (mb, loc_real_proxy);
  975. mono_mb_emit_ldloc_addr (mb, loc_serialized_data);
  976. mono_mb_emit_ldloc_addr (mb, loc_serialized_exc);
  977. copy_locals_base = mb->locals;
  978. for (i = 0; i < sig->param_count; i++) {
  979. switch (marshal_types [i]) {
  980. case MONO_MARSHAL_SERIALIZE:
  981. continue;
  982. case MONO_MARSHAL_COPY: {
  983. mono_mb_emit_ldarg (mb, i+1);
  984. if (sig->params [i]->byref) {
  985. /* make a local copy of the byref parameter. The real parameter
  986. * will be updated after the xdomain call
  987. */
  988. MonoClass *pclass = mono_class_from_mono_type_internal (sig->params [i]);
  989. int copy_local = mono_mb_add_local (mb, m_class_get_byval_arg (pclass));
  990. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  991. mono_mb_emit_stloc (mb, copy_local);
  992. mono_mb_emit_ldloc_addr (mb, copy_local);
  993. }
  994. break;
  995. }
  996. case MONO_MARSHAL_COPY_OUT:
  997. case MONO_MARSHAL_NONE:
  998. mono_mb_emit_ldarg (mb, i+1);
  999. break;
  1000. }
  1001. }
  1002. /* Make the call to the invoke wrapper in the target domain */
  1003. xdomain_method = mono_marshal_get_xappdomain_dispatch (method, marshal_types, complex_count, complex_out_count, ret_marshal_type);
  1004. mono_marshal_emit_load_domain_method (mb, xdomain_method);
  1005. mono_mb_emit_calli (mb, mono_method_signature_internal (xdomain_method));
  1006. if (copy_return)
  1007. mono_mb_emit_stloc (mb, loc_return);
  1008. /* Switch domain */
  1009. mono_mb_emit_ldloc (mb, loc_old_domainid);
  1010. mono_mb_emit_byte (mb, CEE_LDC_I4_0);
  1011. mono_marshal_emit_switch_domain (mb);
  1012. mono_mb_emit_byte (mb, CEE_POP);
  1013. /* Restore thread domain data */
  1014. mono_mb_emit_ldloc (mb, loc_context);
  1015. mono_mb_emit_icall (mb, mono_context_set_icall);
  1016. /* if (loc_serialized_exc != null) ... */
  1017. mono_mb_emit_ldloc (mb, loc_serialized_exc);
  1018. pos_noex = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
  1019. mono_mb_emit_ldloc (mb, loc_serialized_exc);
  1020. mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
  1021. mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
  1022. mono_mb_emit_op (mb, CEE_CASTCLASS, mono_defaults.exception_class);
  1023. mono_mb_emit_managed_call (mb, method_exc_fixexc, NULL);
  1024. mono_mb_emit_byte (mb, CEE_THROW);
  1025. mono_mb_patch_short_branch (mb, pos_noex);
  1026. /* copy back non-serialized output parameters */
  1027. j = 0;
  1028. for (i = 0; i < sig->param_count; i++) {
  1029. if (!sig->params [i]->byref || marshal_types [i] != MONO_MARSHAL_COPY) continue;
  1030. mono_mb_emit_ldarg (mb, i + 1);
  1031. mono_mb_emit_ldloc (mb, copy_locals_base + (j++));
  1032. mono_marshal_emit_xdomain_copy_value (mb, mono_class_from_mono_type_internal (sig->params [i]));
  1033. mono_mb_emit_byte (mb, CEE_STIND_REF);
  1034. }
  1035. /* Deserialize out parameters */
  1036. if (complex_out_count > 0) {
  1037. mono_mb_emit_ldloc (mb, loc_serialized_data);
  1038. mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
  1039. mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
  1040. mono_mb_emit_stloc (mb, loc_array);
  1041. /* Copy back output parameters and return type */
  1042. j = 0;
  1043. for (i = 0; i < sig->param_count; i++) {
  1044. if (marshal_types [i] != MONO_MARSHAL_SERIALIZE) continue;
  1045. if (sig->params[i]->byref) {
  1046. MonoClass *pclass = mono_class_from_mono_type_internal (sig->params [i]);
  1047. mono_mb_emit_ldarg (mb, i + 1);
  1048. mono_mb_emit_ldloc (mb, loc_array);
  1049. mono_mb_emit_icon (mb, j);
  1050. mono_mb_emit_byte (mb, CEE_LDELEM_REF);
  1051. if (m_class_is_valuetype (pclass)) {
  1052. mono_mb_emit_op (mb, CEE_UNBOX, pclass);
  1053. mono_mb_emit_op (mb, CEE_LDOBJ, pclass);
  1054. mono_mb_emit_op (mb, CEE_STOBJ, pclass);
  1055. } else {
  1056. if (pclass != mono_defaults.object_class)
  1057. mono_mb_emit_op (mb, CEE_CASTCLASS, pclass);
  1058. mono_mb_emit_byte (mb, CEE_STIND_REF);
  1059. }
  1060. }
  1061. j++;
  1062. }
  1063. if (ret_marshal_type == MONO_MARSHAL_SERIALIZE) {
  1064. mono_mb_emit_ldloc (mb, loc_array);
  1065. mono_mb_emit_icon (mb, complex_count);
  1066. mono_mb_emit_byte (mb, CEE_LDELEM_REF);
  1067. if (m_class_is_valuetype (ret_class)) {
  1068. mono_mb_emit_op (mb, CEE_UNBOX, ret_class);
  1069. mono_mb_emit_op (mb, CEE_LDOBJ, ret_class);
  1070. }
  1071. }
  1072. } else if (ret_marshal_type == MONO_MARSHAL_SERIALIZE) {
  1073. mono_mb_emit_ldloc (mb, loc_serialized_data);
  1074. mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
  1075. mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
  1076. if (m_class_is_valuetype (ret_class)) {
  1077. mono_mb_emit_op (mb, CEE_UNBOX, ret_class);
  1078. mono_mb_emit_op (mb, CEE_LDOBJ, ret_class);
  1079. } else if (ret_class != mono_defaults.object_class) {
  1080. mono_mb_emit_op (mb, CEE_CASTCLASS, ret_class);
  1081. }
  1082. } else {
  1083. mono_mb_emit_ldloc (mb, loc_serialized_data);
  1084. mono_mb_emit_byte (mb, CEE_DUP);
  1085. pos = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
  1086. mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
  1087. mono_mb_patch_short_branch (mb, pos);
  1088. mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
  1089. mono_mb_emit_byte (mb, CEE_POP);
  1090. }
  1091. if (copy_return) {
  1092. mono_mb_emit_ldloc (mb, loc_return);
  1093. if (ret_marshal_type == MONO_MARSHAL_COPY)
  1094. mono_marshal_emit_xdomain_copy_value (mb, ret_class);
  1095. }
  1096. mono_mb_emit_byte (mb, CEE_RET);
  1097. #endif /* DISABLE_JIT */
  1098. info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
  1099. info->d.remoting.method = method;
  1100. res = mono_remoting_mb_create_and_cache (method, mb, sig, sig->param_count + 16, info);
  1101. mono_mb_free (mb);
  1102. return res;
  1103. }
  1104. /**
  1105. * mono_marshal_get_remoting_invoke_for_target:
  1106. */
  1107. MonoMethod *
  1108. mono_marshal_get_remoting_invoke_for_target (MonoMethod *method, MonoRemotingTarget target_type, MonoError *error)
  1109. {
  1110. error_init (error);
  1111. if (target_type == MONO_REMOTING_TARGET_APPDOMAIN) {
  1112. return mono_marshal_get_xappdomain_invoke (method, error);
  1113. } else if (target_type == MONO_REMOTING_TARGET_COMINTEROP) {
  1114. #ifndef DISABLE_COM
  1115. return mono_cominterop_get_invoke (method);
  1116. #else
  1117. g_assert_not_reached ();
  1118. #endif
  1119. } else {
  1120. return mono_marshal_get_remoting_invoke (method, error);
  1121. }
  1122. /* Not erached */
  1123. return NULL;
  1124. }
  1125. G_GNUC_UNUSED static gpointer
  1126. mono_marshal_load_remoting_wrapper (MonoRealProxy *rp, MonoMethod *method)
  1127. {
  1128. ERROR_DECL (error);
  1129. MonoMethod *marshal_method = NULL;
  1130. if (rp->target_domain_id != -1)
  1131. marshal_method = mono_marshal_get_xappdomain_invoke (method, error);
  1132. else
  1133. marshal_method = mono_marshal_get_remoting_invoke (method, error);
  1134. mono_error_assert_ok (error);
  1135. gpointer compiled_ptr = mono_compile_method_checked (marshal_method, error);
  1136. mono_error_assert_ok (error);
  1137. return compiled_ptr;
  1138. }
  1139. /**
  1140. * mono_marshal_get_remoting_invoke_with_check:
  1141. */
  1142. MonoMethod *
  1143. mono_marshal_get_remoting_invoke_with_check (MonoMethod *method, MonoError *error)
  1144. {
  1145. MonoMethodSignature *sig;
  1146. MonoMethodBuilder *mb;
  1147. MonoMethod *res, *native;
  1148. WrapperInfo *info;
  1149. int i, pos, pos_rem;
  1150. g_assert (method);
  1151. error_init (error);
  1152. if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
  1153. return method;
  1154. /* we cant remote methods without this pointer */
  1155. g_assert (mono_method_signature_internal (method)->hasthis);
  1156. if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)))
  1157. return res;
  1158. sig = mono_signature_no_pinvoke (method);
  1159. mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
  1160. #ifndef DISABLE_JIT
  1161. for (i = 0; i <= sig->param_count; i++)
  1162. mono_mb_emit_ldarg (mb, i);
  1163. mono_mb_emit_ldarg (mb, 0);
  1164. pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
  1165. if (mono_marshal_supports_fast_xdomain (method)) {
  1166. mono_mb_emit_ldarg (mb, 0);
  1167. pos_rem = mono_mb_emit_xdomain_check (mb, CEE_BEQ);
  1168. /* wrapper for cross app domain calls */
  1169. native = mono_marshal_get_xappdomain_invoke (method, error);
  1170. if (!is_ok (error)) {
  1171. mono_mb_free (mb);
  1172. return NULL;
  1173. }
  1174. mono_mb_emit_managed_call (mb, native, mono_method_signature_internal (native));
  1175. mono_mb_emit_byte (mb, CEE_RET);
  1176. mono_mb_patch_branch (mb, pos_rem);
  1177. }
  1178. /* wrapper for normal remote calls */
  1179. native = mono_marshal_get_remoting_invoke (method, error);
  1180. if (!is_ok (error)) {
  1181. mono_mb_free (mb);
  1182. return NULL;
  1183. }
  1184. mono_mb_emit_managed_call (mb, native, mono_method_signature_internal (native));
  1185. mono_mb_emit_byte (mb, CEE_RET);
  1186. /* not a proxy */
  1187. mono_mb_patch_branch (mb, pos);
  1188. mono_mb_emit_managed_call (mb, method, mono_method_signature_internal (method));
  1189. mono_mb_emit_byte (mb, CEE_RET);
  1190. #endif
  1191. info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
  1192. info->d.remoting.method = method;
  1193. res = mono_remoting_mb_create_and_cache (method, mb, sig, sig->param_count + 16, info);
  1194. mono_mb_free (mb);
  1195. return res;
  1196. }
  1197. /**
  1198. * mono_marshal_get_ldfld_wrapper:
  1199. * \param type the type of the field
  1200. *
  1201. * This method generates a function which can be use to load a field with type
  1202. * \p type from an object. The generated function has the following signature:
  1203. *
  1204. * <code><i>type</i> ldfld_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset)</code>
  1205. */
  1206. MonoMethod *
  1207. mono_marshal_get_ldfld_wrapper (MonoType *type)
  1208. {
  1209. MonoMethodSignature *sig;
  1210. MonoMethodBuilder *mb;
  1211. MonoMethod *res;
  1212. MonoClass *klass;
  1213. GHashTable *cache;
  1214. WrapperInfo *info;
  1215. char *name;
  1216. int t, pos0, pos1 = 0;
  1217. type = mono_type_get_underlying_type (type);
  1218. t = type->type;
  1219. if (!type->byref) {
  1220. if (type->type == MONO_TYPE_SZARRAY) {
  1221. klass = mono_defaults.array_class;
  1222. } else if (type->type == MONO_TYPE_VALUETYPE) {
  1223. klass = type->data.klass;
  1224. } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING) {
  1225. klass = mono_defaults.object_class;
  1226. } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
  1227. klass = mono_defaults.int_class;
  1228. } else if (t == MONO_TYPE_GENERICINST) {
  1229. if (mono_type_generic_inst_is_valuetype (type))
  1230. klass = mono_class_from_mono_type_internal (type);
  1231. else
  1232. klass = mono_defaults.object_class;
  1233. } else {
  1234. klass = mono_class_from_mono_type_internal (type);
  1235. }
  1236. } else {
  1237. klass = mono_defaults.int_class;
  1238. }
  1239. cache = get_cache (&m_class_get_image (klass)->ldfld_wrapper_cache, mono_aligned_addr_hash, NULL);
  1240. if ((res = mono_marshal_find_in_cache (cache, klass)))
  1241. return res;
  1242. #ifndef DISABLE_REMOTING
  1243. MONO_STATIC_POINTER_INIT (MonoMethod, tp_load)
  1244. ERROR_DECL (error);
  1245. tp_load = mono_class_get_method_from_name_checked (mono_defaults.transparent_proxy_class, "LoadRemoteFieldNew", -1, 0, error);
  1246. mono_error_assert_ok (error);
  1247. g_assert (tp_load != NULL);
  1248. MONO_STATIC_POINTER_INIT_END (MonoMethod, tp_load)
  1249. #endif
  1250. /* we add the %p pointer value of klass because class names are not unique */
  1251. name = g_strdup_printf ("__ldfld_wrapper_%p_%s.%s", klass, m_class_get_name_space (klass), m_class_get_name (klass));
  1252. mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
  1253. g_free (name);
  1254. MonoType *object_type = mono_get_object_type ();
  1255. MonoType *int_type = mono_get_int_type ();
  1256. sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
  1257. sig->params [0] = object_type;
  1258. sig->params [1] = int_type;
  1259. sig->params [2] = int_type;
  1260. sig->params [3] = int_type;
  1261. sig->ret = m_class_get_byval_arg (klass);
  1262. #ifndef DISABLE_JIT
  1263. mono_mb_emit_ldarg (mb, 0);
  1264. pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
  1265. #ifndef DISABLE_REMOTING
  1266. mono_mb_emit_ldarg (mb, 0);
  1267. mono_mb_emit_ldarg (mb, 1);
  1268. mono_mb_emit_ldarg (mb, 2);
  1269. mono_mb_emit_managed_call (mb, tp_load, NULL);
  1270. /*
  1271. csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
  1272. csig->params [0] = mono_get_object_type ();
  1273. csig->params [1] = mono_get_int_type ();
  1274. csig->params [2] = mono_get_int_type ();
  1275. csig->ret = m_class_get_this_arg (klass);
  1276. csig->pinvoke = 1;
  1277. mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
  1278. mono_marshal_emit_thread_interrupt_checkpoint (mb);
  1279. */
  1280. if (m_class_is_valuetype (klass)) {
  1281. mono_mb_emit_op (mb, CEE_UNBOX, klass);
  1282. pos1 = mono_mb_emit_branch (mb, CEE_BR);
  1283. } else {
  1284. mono_mb_emit_byte (mb, CEE_RET);
  1285. }
  1286. #endif
  1287. mono_mb_patch_branch (mb, pos0);
  1288. mono_mb_emit_ldarg (mb, 0);
  1289. mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
  1290. mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
  1291. mono_mb_emit_ldarg (mb, 3);
  1292. mono_mb_emit_byte (mb, CEE_ADD);
  1293. if (m_class_is_valuetype (klass))
  1294. mono_mb_patch_branch (mb, pos1);
  1295. switch (t) {
  1296. case MONO_TYPE_I1:
  1297. case MONO_TYPE_U1:
  1298. case MONO_TYPE_BOOLEAN:
  1299. case MONO_TYPE_CHAR:
  1300. case MONO_TYPE_I2:
  1301. case MONO_TYPE_U2:
  1302. case MONO_TYPE_I4:
  1303. case MONO_TYPE_U4:
  1304. case MONO_TYPE_I8:
  1305. case MONO_TYPE_U8:
  1306. case MONO_TYPE_R4:
  1307. case MONO_TYPE_R8:
  1308. case MONO_TYPE_ARRAY:
  1309. case MONO_TYPE_SZARRAY:
  1310. case MONO_TYPE_OBJECT:
  1311. case MONO_TYPE_CLASS:
  1312. case MONO_TYPE_STRING:
  1313. case MONO_TYPE_I:
  1314. case MONO_TYPE_U:
  1315. case MONO_TYPE_PTR:
  1316. case MONO_TYPE_FNPTR:
  1317. mono_mb_emit_byte (mb, mono_type_to_ldind (type));
  1318. break;
  1319. case MONO_TYPE_VALUETYPE:
  1320. g_assert (!m_class_is_enumtype (klass));
  1321. mono_mb_emit_op (mb, CEE_LDOBJ, klass);
  1322. break;
  1323. case MONO_TYPE_GENERICINST:
  1324. if (mono_type_generic_inst_is_valuetype (type)) {
  1325. mono_mb_emit_op (mb, CEE_LDOBJ, klass);
  1326. } else {
  1327. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  1328. }
  1329. break;
  1330. case MONO_TYPE_VAR:
  1331. case MONO_TYPE_MVAR:
  1332. mono_mb_emit_op (mb, CEE_LDOBJ, klass);
  1333. break;
  1334. default:
  1335. g_warning ("type %x not implemented", type->type);
  1336. g_assert_not_reached ();
  1337. }
  1338. mono_mb_emit_byte (mb, CEE_RET);
  1339. #endif /* DISABLE_JIT */
  1340. info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
  1341. info->d.proxy.klass = klass;
  1342. res = mono_mb_create_and_cache_full (cache, klass,
  1343. mb, sig, sig->param_count + 16, info, NULL);
  1344. mono_mb_free (mb);
  1345. return res;
  1346. }
  1347. /*
  1348. * mono_marshal_get_ldflda_wrapper:
  1349. * @type: the type of the field
  1350. *
  1351. * This method generates a function which can be used to load a field address
  1352. * from an object. The generated function has the following signature:
  1353. * gpointer ldflda_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset);
  1354. */
  1355. MonoMethod *
  1356. mono_marshal_get_ldflda_wrapper (MonoType *type)
  1357. {
  1358. MonoMethodSignature *sig;
  1359. MonoMethodBuilder *mb;
  1360. MonoMethod *res;
  1361. MonoClass *klass;
  1362. GHashTable *cache;
  1363. WrapperInfo *info;
  1364. char *name;
  1365. int t, pos0, pos1, pos2, pos3;
  1366. type = mono_type_get_underlying_type (type);
  1367. t = type->type;
  1368. if (!type->byref) {
  1369. if (type->type == MONO_TYPE_SZARRAY) {
  1370. klass = mono_defaults.array_class;
  1371. } else if (type->type == MONO_TYPE_VALUETYPE) {
  1372. klass = type->data.klass;
  1373. } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING) {
  1374. klass = mono_defaults.object_class;
  1375. } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
  1376. klass = mono_defaults.int_class;
  1377. } else if (t == MONO_TYPE_GENERICINST) {
  1378. if (mono_type_generic_inst_is_valuetype (type))
  1379. klass = mono_class_from_mono_type_internal (type);
  1380. else
  1381. klass = mono_defaults.object_class;
  1382. } else {
  1383. klass = mono_class_from_mono_type_internal (type);
  1384. }
  1385. } else {
  1386. klass = mono_defaults.int_class;
  1387. }
  1388. cache = get_cache (&m_class_get_image (klass)->ldflda_wrapper_cache, mono_aligned_addr_hash, NULL);
  1389. if ((res = mono_marshal_find_in_cache (cache, klass)))
  1390. return res;
  1391. mono_remoting_marshal_init ();
  1392. /* we add the %p pointer value of klass because class names are not unique */
  1393. name = g_strdup_printf ("__ldflda_wrapper_%p_%s.%s", klass, m_class_get_name_space (klass), m_class_get_name (klass));
  1394. mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLDA);
  1395. g_free (name);
  1396. MonoType *object_type = mono_get_object_type ();
  1397. MonoType *int_type = mono_get_int_type ();
  1398. sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
  1399. sig->params [0] = object_type;
  1400. sig->params [1] = int_type;
  1401. sig->params [2] = int_type;
  1402. sig->params [3] = int_type;
  1403. sig->ret = int_type;
  1404. #ifndef DISABLE_JIT
  1405. /* if typeof (this) != transparent_proxy goto pos0 */
  1406. mono_mb_emit_ldarg (mb, 0);
  1407. pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
  1408. /* if same_appdomain goto pos1 */
  1409. mono_mb_emit_ldarg (mb, 0);
  1410. pos1 = mono_mb_emit_xdomain_check (mb, CEE_BEQ);
  1411. mono_mb_emit_exception_full (mb, "System", "InvalidOperationException", "Attempt to load field address from object in another appdomain.");
  1412. /* same app domain */
  1413. mono_mb_patch_branch (mb, pos1);
  1414. /* if typeof (this) != contextbound goto pos2 */
  1415. mono_mb_emit_ldarg (mb, 0);
  1416. pos2 = mono_mb_emit_contextbound_check (mb, CEE_BEQ);
  1417. /* if this->rp->context == mono_context_get goto pos3 */
  1418. mono_mb_emit_ldarg (mb, 0);
  1419. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
  1420. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  1421. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRealProxy, context));
  1422. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  1423. mono_mb_emit_icall (mb, mono_context_get_icall);
  1424. pos3 = mono_mb_emit_branch (mb, CEE_BEQ);
  1425. mono_mb_emit_exception_full (mb, "System", "InvalidOperationException", "Attempt to load field address from object in another context.");
  1426. mono_mb_patch_branch (mb, pos2);
  1427. mono_mb_patch_branch (mb, pos3);
  1428. /* return the address of the field from this->rp->unwrapped_server */
  1429. mono_mb_emit_ldarg (mb, 0);
  1430. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
  1431. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  1432. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRealProxy, unwrapped_server));
  1433. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  1434. mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
  1435. mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
  1436. mono_mb_emit_ldarg (mb, 3);
  1437. mono_mb_emit_byte (mb, CEE_ADD);
  1438. mono_mb_emit_byte (mb, CEE_RET);
  1439. /* not a proxy: return the address of the field directly */
  1440. mono_mb_patch_branch (mb, pos0);
  1441. mono_mb_emit_ldarg (mb, 0);
  1442. mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
  1443. mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
  1444. mono_mb_emit_ldarg (mb, 3);
  1445. mono_mb_emit_byte (mb, CEE_ADD);
  1446. mono_mb_emit_byte (mb, CEE_RET);
  1447. #endif
  1448. info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
  1449. info->d.proxy.klass = klass;
  1450. res = mono_mb_create_and_cache_full (cache, klass,
  1451. mb, sig, sig->param_count + 16,
  1452. info, NULL);
  1453. mono_mb_free (mb);
  1454. return res;
  1455. }
  1456. /**
  1457. * mono_marshal_get_stfld_wrapper:
  1458. * \param type the type of the field
  1459. *
  1460. * This method generates a function which can be use to store a field with type
  1461. * \p type. The generated function has the following signature:
  1462. *
  1463. * <code>void stfld_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset, <i>type</i> val)</code>
  1464. */
  1465. MonoMethod *
  1466. mono_marshal_get_stfld_wrapper (MonoType *type)
  1467. {
  1468. MonoMethodSignature *sig;
  1469. MonoMethodBuilder *mb;
  1470. MonoMethod *res;
  1471. MonoClass *klass;
  1472. GHashTable *cache;
  1473. WrapperInfo *info;
  1474. char *name;
  1475. int t, pos;
  1476. type = mono_type_get_underlying_type (type);
  1477. t = type->type;
  1478. if (!type->byref) {
  1479. if (type->type == MONO_TYPE_SZARRAY) {
  1480. klass = mono_defaults.array_class;
  1481. } else if (type->type == MONO_TYPE_VALUETYPE) {
  1482. klass = type->data.klass;
  1483. } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING) {
  1484. klass = mono_defaults.object_class;
  1485. } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
  1486. klass = mono_defaults.int_class;
  1487. } else if (t == MONO_TYPE_GENERICINST) {
  1488. if (mono_type_generic_inst_is_valuetype (type))
  1489. klass = mono_class_from_mono_type_internal (type);
  1490. else
  1491. klass = mono_defaults.object_class;
  1492. } else {
  1493. klass = mono_class_from_mono_type_internal (type);
  1494. }
  1495. } else {
  1496. klass = mono_defaults.int_class;
  1497. }
  1498. cache = get_cache (&m_class_get_image (klass)->stfld_wrapper_cache, mono_aligned_addr_hash, NULL);
  1499. if ((res = mono_marshal_find_in_cache (cache, klass)))
  1500. return res;
  1501. #ifndef DISABLE_REMOTING
  1502. MONO_STATIC_POINTER_INIT (MonoMethod, tp_store)
  1503. ERROR_DECL (error);
  1504. tp_store = mono_class_get_method_from_name_checked (mono_defaults.transparent_proxy_class, "StoreRemoteField", -1, 0, error);
  1505. mono_error_assert_ok (error);
  1506. g_assert (tp_store != NULL);
  1507. MONO_STATIC_POINTER_INIT_END (MonoMethod, tp_store)
  1508. #endif
  1509. /* we add the %p pointer value of klass because class names are not unique */
  1510. name = g_strdup_printf ("__stfld_wrapper_%p_%s.%s", klass, m_class_get_name_space (klass), m_class_get_name (klass));
  1511. mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
  1512. g_free (name);
  1513. MonoType *object_type = mono_get_object_type ();
  1514. MonoType *int_type = mono_get_int_type ();
  1515. MonoType *void_type = mono_get_void_type ();
  1516. sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
  1517. sig->params [0] = object_type;
  1518. sig->params [1] = int_type;
  1519. sig->params [2] = int_type;
  1520. sig->params [3] = int_type;
  1521. sig->params [4] = m_class_get_byval_arg (klass);
  1522. sig->ret = void_type;
  1523. #ifndef DISABLE_JIT
  1524. mono_mb_emit_ldarg (mb, 0);
  1525. pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
  1526. #ifndef DISABLE_REMOTING
  1527. mono_mb_emit_ldarg (mb, 0);
  1528. mono_mb_emit_ldarg (mb, 1);
  1529. mono_mb_emit_ldarg (mb, 2);
  1530. mono_mb_emit_ldarg (mb, 4);
  1531. if (m_class_is_valuetype (klass))
  1532. mono_mb_emit_op (mb, CEE_BOX, klass);
  1533. mono_mb_emit_managed_call (mb, tp_store, NULL);
  1534. mono_mb_emit_byte (mb, CEE_RET);
  1535. #endif
  1536. mono_mb_patch_branch (mb, pos);
  1537. mono_mb_emit_ldarg (mb, 0);
  1538. mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
  1539. mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
  1540. mono_mb_emit_ldarg (mb, 3);
  1541. mono_mb_emit_byte (mb, CEE_ADD);
  1542. mono_mb_emit_ldarg (mb, 4);
  1543. switch (t) {
  1544. case MONO_TYPE_I1:
  1545. case MONO_TYPE_U1:
  1546. case MONO_TYPE_BOOLEAN:
  1547. case MONO_TYPE_CHAR:
  1548. case MONO_TYPE_I2:
  1549. case MONO_TYPE_U2:
  1550. case MONO_TYPE_I4:
  1551. case MONO_TYPE_U4:
  1552. case MONO_TYPE_I8:
  1553. case MONO_TYPE_U8:
  1554. case MONO_TYPE_R4:
  1555. case MONO_TYPE_R8:
  1556. case MONO_TYPE_ARRAY:
  1557. case MONO_TYPE_SZARRAY:
  1558. case MONO_TYPE_OBJECT:
  1559. case MONO_TYPE_CLASS:
  1560. case MONO_TYPE_STRING:
  1561. case MONO_TYPE_I:
  1562. case MONO_TYPE_U:
  1563. case MONO_TYPE_PTR:
  1564. case MONO_TYPE_FNPTR:
  1565. mono_mb_emit_byte (mb, mono_type_to_stind (type));
  1566. break;
  1567. case MONO_TYPE_VALUETYPE:
  1568. g_assert (!m_class_is_enumtype (klass));
  1569. mono_mb_emit_op (mb, CEE_STOBJ, klass);
  1570. break;
  1571. case MONO_TYPE_GENERICINST:
  1572. case MONO_TYPE_VAR:
  1573. case MONO_TYPE_MVAR:
  1574. mono_mb_emit_op (mb, CEE_STOBJ, klass);
  1575. break;
  1576. default:
  1577. g_warning ("type %x not implemented", type->type);
  1578. g_assert_not_reached ();
  1579. }
  1580. mono_mb_emit_byte (mb, CEE_RET);
  1581. #endif
  1582. info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
  1583. info->d.proxy.klass = klass;
  1584. res = mono_mb_create_and_cache_full (cache, klass,
  1585. mb, sig, sig->param_count + 16,
  1586. info, NULL);
  1587. mono_mb_free (mb);
  1588. return res;
  1589. }
  1590. /**
  1591. * mono_marshal_get_proxy_cancast:
  1592. */
  1593. MonoMethod *
  1594. mono_marshal_get_proxy_cancast (MonoClass *klass)
  1595. {
  1596. static MonoMethodSignature *isint_sig = NULL;
  1597. GHashTable *cache;
  1598. MonoMethod *res;
  1599. WrapperInfo *info;
  1600. int pos_failed, pos_end;
  1601. char *name, *klass_name;
  1602. MonoMethod *can_cast_to;
  1603. MonoMethodDesc *desc;
  1604. MonoMethodBuilder *mb;
  1605. cache = get_cache (&m_class_get_image (klass)->proxy_isinst_cache, mono_aligned_addr_hash, NULL);
  1606. if ((res = mono_marshal_find_in_cache (cache, klass)))
  1607. return res;
  1608. if (!isint_sig) {
  1609. isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
  1610. isint_sig->params [0] = mono_get_object_type ();
  1611. isint_sig->ret = mono_get_object_type ();
  1612. isint_sig->pinvoke = 0;
  1613. }
  1614. klass_name = mono_type_full_name (m_class_get_byval_arg (klass));
  1615. name = g_strdup_printf ("__proxy_isinst_wrapper_%s", klass_name);
  1616. mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_PROXY_ISINST);
  1617. g_free (klass_name);
  1618. g_free (name);
  1619. mb->method->save_lmf = 1;
  1620. #ifndef DISABLE_JIT
  1621. mono_remoting_marshal_init (); // register icalls
  1622. /* get the real proxy from the transparent proxy*/
  1623. mono_mb_emit_ldarg (mb, 0);
  1624. mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
  1625. mono_mb_emit_byte (mb, CEE_LDIND_REF);
  1626. /* get the reflection type from the type handle */
  1627. mono_mb_emit_ptr (mb, m_class_get_byval_arg (klass));
  1628. mono_mb_emit_icall (mb, type_from_handle);
  1629. mono_mb_emit_ldarg (mb, 0);
  1630. /* make the call to CanCastTo (type, ob) */
  1631. desc = mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE);
  1632. can_cast_to = mono_method_desc_search_in_class (desc, mono_defaults.iremotingtypeinfo_class);
  1633. g_assert (can_cast_to);
  1634. mono_method_desc_free (desc);
  1635. mono_mb_emit_op (mb, CEE_CALLVIRT, can_cast_to);
  1636. pos_failed = mono_mb_emit_branch (mb, CEE_BRFALSE);
  1637. /* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
  1638. mono_mb_emit_ptr (mb, m_class_get_byval_arg (klass));
  1639. mono_mb_emit_icall (mb, type_from_handle);
  1640. mono_mb_emit_ldarg (mb, 0);
  1641. mono_mb_emit_icall (mb, mono_upgrade_remote_class_wrapper);
  1642. mono_marshal_emit_thread_interrupt_checkpoint (mb);
  1643. mono_mb_emit_ldarg (mb, 0);
  1644. pos_end = mono_mb_emit_branch (mb, CEE_BR);
  1645. /* fail */
  1646. mono_mb_patch_branch (mb, pos_failed);
  1647. mono_mb_emit_byte (mb, CEE_LDNULL);
  1648. /* the end */
  1649. mono_mb_patch_branch (mb, pos_end);
  1650. mono_mb_emit_byte (mb, CEE_RET);
  1651. #endif
  1652. info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
  1653. info->d.proxy.klass = klass;
  1654. res = mono_mb_create_and_cache_full (cache, klass, mb, isint_sig, isint_sig->param_count + 16, info, NULL);
  1655. mono_mb_free (mb);
  1656. return res;
  1657. }
  1658. void
  1659. mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype_raw, MonoTransparentProxy *tproxy_raw)
  1660. {
  1661. ICALL_ENTRY ();
  1662. MONO_HANDLE_DCL (MonoReflectionType, rtype);
  1663. MONO_HANDLE_DCL (MonoTransparentProxy, tproxy);
  1664. MonoDomain *domain = MONO_HANDLE_DOMAIN (tproxy);
  1665. MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (rtype, type));
  1666. mono_upgrade_remote_class (domain, MONO_HANDLE_CAST (MonoObject, tproxy), klass, error);
  1667. ICALL_RETURN ();
  1668. }
  1669. #else /* DISABLE_REMOTING */
  1670. void
  1671. mono_remoting_init (void)
  1672. {
  1673. }
  1674. #endif /* DISABLE_REMOTING */
  1675. /* mono_get_xdomain_marshal_type()
  1676. * Returns the kind of marshalling that a type needs for cross domain calls.
  1677. */
  1678. static MonoXDomainMarshalType
  1679. mono_get_xdomain_marshal_type (MonoType *t)
  1680. {
  1681. switch (t->type) {
  1682. case MONO_TYPE_VOID:
  1683. g_assert_not_reached ();
  1684. break;
  1685. case MONO_TYPE_U1:
  1686. case MONO_TYPE_I1:
  1687. case MONO_TYPE_BOOLEAN:
  1688. case MONO_TYPE_U2:
  1689. case MONO_TYPE_I2:
  1690. case MONO_TYPE_CHAR:
  1691. case MONO_TYPE_U4:
  1692. case MONO_TYPE_I4:
  1693. case MONO_TYPE_I8:
  1694. case MONO_TYPE_U8:
  1695. case MONO_TYPE_R4:
  1696. case MONO_TYPE_R8:
  1697. return MONO_MARSHAL_NONE;
  1698. case MONO_TYPE_STRING:
  1699. return MONO_MARSHAL_COPY;
  1700. case MONO_TYPE_ARRAY:
  1701. case MONO_TYPE_SZARRAY: {
  1702. MonoClass *elem_class = m_class_get_element_class (mono_class_from_mono_type_internal (t));
  1703. if (mono_get_xdomain_marshal_type (m_class_get_byval_arg (elem_class)) != MONO_MARSHAL_SERIALIZE)
  1704. return MONO_MARSHAL_COPY;
  1705. break;
  1706. }
  1707. default:
  1708. break;
  1709. }
  1710. return MONO_MARSHAL_SERIALIZE;
  1711. }
  1712. /* Replace the given array element by a copy in the current domain */
  1713. static gboolean
  1714. xdomain_copy_array_element_inplace (MonoArrayHandle arr, int i, MonoError *error)
  1715. {
  1716. HANDLE_FUNCTION_ENTER ();
  1717. error_init (error);
  1718. MonoObjectHandle item = MONO_HANDLE_NEW (MonoObject, NULL);
  1719. MONO_HANDLE_ARRAY_GETREF (item, arr, i);
  1720. MonoObjectHandle item_copy = mono_marshal_xdomain_copy_value_handle (item, error);
  1721. goto_if_nok (error, leave);
  1722. MONO_HANDLE_ARRAY_SETREF (arr, i, item_copy);
  1723. leave:
  1724. HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
  1725. }
  1726. /**
  1727. * mono_marshal_xdomain_copy_value_handle:
  1728. * \param val The value to copy.
  1729. * \param error set on failure.
  1730. * Makes a copy of \p val suitable for the current domain.
  1731. * On failure returns NULL and sets \p error.
  1732. */
  1733. MonoObjectHandle
  1734. mono_marshal_xdomain_copy_value_handle (MonoObjectHandle val, MonoError *error)
  1735. {
  1736. error_init (error);
  1737. MonoObjectHandle result = MONO_HANDLE_NEW (MonoObject, NULL);
  1738. if (MONO_HANDLE_IS_NULL (val))
  1739. goto leave;
  1740. MonoDomain *domain;
  1741. domain = mono_domain_get ();
  1742. MonoClass *klass;
  1743. klass = mono_handle_class (val);
  1744. switch (m_class_get_byval_arg (klass)->type) {
  1745. case MONO_TYPE_VOID:
  1746. g_assert_not_reached ();
  1747. break;
  1748. case MONO_TYPE_U1:
  1749. case MONO_TYPE_I1:
  1750. case MONO_TYPE_BOOLEAN:
  1751. case MONO_TYPE_U2:
  1752. case MONO_TYPE_I2:
  1753. case MONO_TYPE_CHAR:
  1754. case MONO_TYPE_U4:
  1755. case MONO_TYPE_I4:
  1756. case MONO_TYPE_I8:
  1757. case MONO_TYPE_U8:
  1758. case MONO_TYPE_R4:
  1759. case MONO_TYPE_R8: {
  1760. MonoGCHandle gchandle = mono_gchandle_from_handle (val, TRUE);
  1761. 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 */
  1762. mono_gchandle_free_internal (gchandle);
  1763. goto_if_nok (error, leave);
  1764. MONO_HANDLE_ASSIGN (result, res);
  1765. break;
  1766. }
  1767. case MONO_TYPE_STRING: {
  1768. MonoStringHandle str = MONO_HANDLE_CAST (MonoString, val);
  1769. MonoGCHandle gchandle = mono_gchandle_from_handle (val, TRUE);
  1770. MonoStringHandle res = mono_string_new_utf16_handle (domain, mono_string_chars_internal (MONO_HANDLE_RAW (str)), mono_string_handle_length (str), error);
  1771. mono_gchandle_free_internal (gchandle);
  1772. goto_if_nok (error, leave);
  1773. MONO_HANDLE_ASSIGN (result, res);
  1774. break;
  1775. }
  1776. case MONO_TYPE_ARRAY:
  1777. case MONO_TYPE_SZARRAY: {
  1778. MonoArrayHandle arr = MONO_HANDLE_CAST (MonoArray, val);
  1779. MonoXDomainMarshalType mt = mono_get_xdomain_marshal_type (m_class_get_byval_arg (m_class_get_element_class (klass)));
  1780. if (mt == MONO_MARSHAL_SERIALIZE)
  1781. goto leave;
  1782. MonoArrayHandle acopy = mono_array_clone_in_domain (domain, arr, error);
  1783. goto_if_nok (error, leave);
  1784. if (mt == MONO_MARSHAL_COPY) {
  1785. int i, len = mono_array_handle_length (acopy);
  1786. for (i = 0; i < len; i++) {
  1787. if (!xdomain_copy_array_element_inplace (acopy, i, error))
  1788. goto leave;
  1789. }
  1790. }
  1791. MONO_HANDLE_ASSIGN (result, acopy);
  1792. break;
  1793. }
  1794. default:
  1795. break;
  1796. }
  1797. leave:
  1798. return result;
  1799. }
  1800. #ifndef DISABLE_REMOTING
  1801. /* mono_marshal_xdomain_copy_value
  1802. * Makes a copy of "val" suitable for the current domain.
  1803. */
  1804. static MonoObject*
  1805. mono_marshal_xdomain_copy_value (MonoObject* val_raw, MonoError *error)
  1806. {
  1807. HANDLE_FUNCTION_ENTER ();
  1808. /* FIXME callers of mono_marshal_xdomain_copy_value should use handles */
  1809. MONO_HANDLE_DCL (MonoObject, val);
  1810. MonoObjectHandle result = mono_marshal_xdomain_copy_value_handle (val, error);
  1811. HANDLE_FUNCTION_RETURN_OBJ (result);
  1812. }
  1813. #endif
  1814. /* mono_marshal_xdomain_copy_value
  1815. * Makes a copy of "val" suitable for the current domain.
  1816. */
  1817. MonoObjectHandle
  1818. ves_icall_mono_marshal_xdomain_copy_value_impl (MonoObjectHandle val, MonoError *error)
  1819. {
  1820. return mono_marshal_xdomain_copy_value_handle (val, error);
  1821. }
  1822. static void
  1823. mono_context_set_icall (MonoAppContext *new_context_raw)
  1824. {
  1825. HANDLE_FUNCTION_ENTER ();
  1826. MONO_HANDLE_DCL (MonoAppContext, new_context);
  1827. mono_context_set_handle (new_context);
  1828. HANDLE_FUNCTION_RETURN ();
  1829. }
  1830. static MonoAppContext*
  1831. mono_context_get_icall (void)
  1832. {
  1833. HANDLE_FUNCTION_ENTER ();
  1834. MonoAppContextHandle context = mono_context_get_handle ();
  1835. HANDLE_FUNCTION_RETURN_OBJ (context);
  1836. }