[sdb] Avoid calling into the debuggee from VirtualMachine.GetObject () while holding...
[mono-project.git] / sdks / wasm / driver.c
blob5467b04f438c2409ebbff3724bdc359897ca9774
1 #include <emscripten.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
7 typedef enum {
8 /* Disables AOT mode */
9 MONO_AOT_MODE_NONE,
10 /* Enables normal AOT mode, equivalent to mono_jit_set_aot_only (false) */
11 MONO_AOT_MODE_NORMAL,
12 /* Enables hybrid AOT mode, JIT can still be used for wrappers */
13 MONO_AOT_MODE_HYBRID,
14 /* Enables full AOT mode, JIT is disabled and not allowed,
15 * equivalent to mono_jit_set_aot_only (true) */
16 MONO_AOT_MODE_FULL,
17 /* Same as full, but use only llvm compiled code */
18 MONO_AOT_MODE_LLVMONLY,
19 /* Uses Interpreter, JIT is disabled and not allowed,
20 * equivalent to "--full-aot --interpreter" */
21 MONO_AOT_MODE_INTERP,
22 /* Same as INTERP, but use only llvm compiled code */
23 MONO_AOT_MODE_INTERP_LLVMONLY,
24 } MonoAotMode;
26 typedef enum {
27 MONO_TYPE_END = 0x00, /* End of List */
28 MONO_TYPE_VOID = 0x01,
29 MONO_TYPE_BOOLEAN = 0x02,
30 MONO_TYPE_CHAR = 0x03,
31 MONO_TYPE_I1 = 0x04,
32 MONO_TYPE_U1 = 0x05,
33 MONO_TYPE_I2 = 0x06,
34 MONO_TYPE_U2 = 0x07,
35 MONO_TYPE_I4 = 0x08,
36 MONO_TYPE_U4 = 0x09,
37 MONO_TYPE_I8 = 0x0a,
38 MONO_TYPE_U8 = 0x0b,
39 MONO_TYPE_R4 = 0x0c,
40 MONO_TYPE_R8 = 0x0d,
41 MONO_TYPE_STRING = 0x0e,
42 MONO_TYPE_PTR = 0x0f, /* arg: <type> token */
43 MONO_TYPE_BYREF = 0x10, /* arg: <type> token */
44 MONO_TYPE_VALUETYPE = 0x11, /* arg: <type> token */
45 MONO_TYPE_CLASS = 0x12, /* arg: <type> token */
46 MONO_TYPE_VAR = 0x13, /* number */
47 MONO_TYPE_ARRAY = 0x14, /* type, rank, boundsCount, bound1, loCount, lo1 */
48 MONO_TYPE_GENERICINST= 0x15, /* <type> <type-arg-count> <type-1> \x{2026} <type-n> */
49 MONO_TYPE_TYPEDBYREF = 0x16,
50 MONO_TYPE_I = 0x18,
51 MONO_TYPE_U = 0x19,
52 MONO_TYPE_FNPTR = 0x1b, /* arg: full method signature */
53 MONO_TYPE_OBJECT = 0x1c,
54 MONO_TYPE_SZARRAY = 0x1d, /* 0-based one-dim-array */
55 MONO_TYPE_MVAR = 0x1e, /* number */
56 MONO_TYPE_CMOD_REQD = 0x1f, /* arg: typedef or typeref token */
57 MONO_TYPE_CMOD_OPT = 0x20, /* optional arg: typedef or typref token */
58 MONO_TYPE_INTERNAL = 0x21, /* CLR internal type */
60 MONO_TYPE_MODIFIER = 0x40, /* Or with the following types */
61 MONO_TYPE_SENTINEL = 0x41, /* Sentinel for varargs method signature */
62 MONO_TYPE_PINNED = 0x45, /* Local var that points to pinned object */
64 MONO_TYPE_ENUM = 0x55 /* an enumeration */
65 } MonoTypeEnum;
67 typedef enum {
68 MONO_IMAGE_OK,
69 MONO_IMAGE_ERROR_ERRNO,
70 MONO_IMAGE_MISSING_ASSEMBLYREF,
71 MONO_IMAGE_IMAGE_INVALID
72 } MonoImageOpenStatus;
74 typedef struct MonoType_ MonoType;
75 typedef struct MonoDomain_ MonoDomain;
76 typedef struct MonoAssembly_ MonoAssembly;
77 typedef struct MonoMethod_ MonoMethod;
78 typedef struct MonoException_ MonoException;
79 typedef struct MonoString_ MonoString;
80 typedef struct MonoClass_ MonoClass;
81 typedef struct MonoImage_ MonoImage;
82 typedef struct MonoObject_ MonoObject;
83 typedef struct MonoArray_ MonoArray;
84 typedef struct MonoThread_ MonoThread;
85 typedef struct _MonoAssemblyName MonoAssemblyName;
88 //JS funcs
89 extern MonoObject* mono_wasm_invoke_js_with_args (int js_handle, MonoString *method, MonoArray *args, int *is_exception);
90 extern MonoObject* mono_wasm_get_object_property (int js_handle, MonoString *method, int *is_exception);
91 extern MonoObject* mono_wasm_set_object_property (int js_handle, MonoString *method, MonoObject *value, int createIfNotExist, int hasOwnProperty, int *is_exception);
92 extern MonoObject* mono_wasm_get_global_object (MonoString *globalName, int *is_exception);
94 // Blazor specific custom routines - see dotnet_support.js for backing code
95 extern void* mono_wasm_invoke_js_marshalled (MonoString **exceptionMessage, void *asyncHandleLongPtr, MonoString *funcName, MonoString *argsJson);
96 extern void* mono_wasm_invoke_js_unmarshalled (MonoString **exceptionMessage, MonoString *funcName, void* arg0, void* arg1, void* arg2);
97 void mono_aot_register_module (void **aot_info);
98 void mono_jit_set_aot_mode (MonoAotMode mode);
99 MonoDomain* mono_jit_init_version (const char *root_domain_name, const char *runtime_version);
100 void mono_ee_interp_init (const char *opts);
101 void mono_marshal_ilgen_init (void);
102 void mono_method_builder_ilgen_init (void);
103 void mono_sgen_mono_ilgen_init (void);
104 void mono_icall_table_init (void);
105 MonoAssembly* mono_assembly_open (const char *filename, MonoImageOpenStatus *status);
106 int mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
107 void mono_set_assemblies_path (const char* path);
108 int monoeg_g_setenv(const char *variable, const char *value, int overwrite);
109 void mono_free (void*);
110 MonoString* mono_string_new (MonoDomain *domain, const char *text);
111 MonoDomain* mono_domain_get (void);
112 MonoClass* mono_class_from_name (MonoImage *image, const char* name_space, const char *name);
113 MonoMethod* mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count);
114 MonoType* mono_class_get_type (MonoClass *klass);
115 MonoClass* mono_object_get_class (MonoObject *obj);
116 int mono_type_get_type (MonoType *type);
117 int mono_type_is_reference (MonoType *type);
119 MonoString* mono_object_to_string (MonoObject *obj, MonoObject **exc);//FIXME Use MonoError variant
120 char* mono_string_to_utf8 (MonoString *string_obj);
121 MonoObject* mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc);
122 void* mono_object_unbox (MonoObject *obj);
124 MonoImage* mono_assembly_get_image (MonoAssembly *assembly);
125 MonoAssembly* mono_assembly_load (MonoAssemblyName *aname, const char *basedir, MonoImageOpenStatus *status);
127 MonoAssemblyName* mono_assembly_name_new (const char *name);
128 void mono_assembly_name_free (MonoAssemblyName *aname);
129 const char* mono_image_get_name (MonoImage *image);
130 MonoString* mono_string_new (MonoDomain *domain, const char *text);
131 void mono_add_internal_call (const char *name, const void* method);
132 MonoString * mono_string_from_utf16 (char *data);
133 MonoString* mono_string_new (MonoDomain *domain, const char *text);
134 void mono_wasm_enable_debugging (void);
135 MonoArray* mono_array_new (MonoDomain *domain, MonoClass *eclass, int n);
136 MonoClass* mono_get_object_class (void);
137 int mono_class_is_delegate (MonoClass* klass);
138 const char* mono_class_get_name (MonoClass *klass);
139 const char* mono_class_get_namespace (MonoClass *klass);
140 MonoClass* mono_get_byte_class (void);
141 MonoClass* mono_get_sbyte_class (void);
142 MonoClass* mono_get_int16_class (void);
143 MonoClass* mono_get_uint16_class (void);
144 MonoClass* mono_get_int32_class (void);
145 MonoClass* mono_get_uint32_class (void);
146 MonoClass* mono_get_single_class (void);
147 MonoClass* mono_get_double_class (void);
148 MonoClass* mono_class_get_element_class(MonoClass *klass);
150 #define mono_array_get(array,type,index) ( *(type*)mono_array_addr ((array), type, (index)) )
151 #define mono_array_addr(array,type,index) ((type*)(void*) mono_array_addr_with_size (array, sizeof (type), index))
152 #define mono_array_setref(array,index,value) \
153 do { \
154 void **__p = (void **) mono_array_addr ((array), void*, (index)); \
155 mono_gc_wbarrier_set_arrayref ((array), __p, (MonoObject*)(value)); \
156 /* *__p = (value);*/ \
157 } while (0)
160 char* mono_array_addr_with_size (MonoArray *array, int size, int idx);
161 int mono_array_length (MonoArray *array);
162 int mono_array_element_size(MonoClass *klass);
163 void mono_gc_wbarrier_set_arrayref (MonoArray *arr, void* slot_ptr, MonoObject* value);
165 typedef struct {
166 const char *name;
167 const unsigned char *data;
168 unsigned int size;
169 } MonoBundledAssembly;
171 void mono_register_bundled_assemblies (const MonoBundledAssembly **assemblies);
173 static char*
174 m_strdup (const char *str)
176 if (!str)
177 return NULL;
179 int len = strlen (str) + 1;
180 char *res = malloc (len);
181 memcpy (res, str, len);
182 return res;
185 static MonoDomain *root_domain;
187 static MonoString*
188 mono_wasm_invoke_js (MonoString *str, int *is_exception)
190 if (str == NULL)
191 return NULL;
193 char *native_val = mono_string_to_utf8 (str);
194 char *native_res = (char*)EM_ASM_INT ({
195 var str = UTF8ToString ($0);
196 try {
197 var res = eval (str);
198 if (res === null || res == undefined)
199 return 0;
200 res = res.toString ();
201 setValue ($1, 0, "i32");
202 } catch (e) {
203 res = e.toString ();
204 setValue ($1, 1, "i32");
205 if (res === null || res === undefined)
206 res = "unknown exception";
208 var buff = Module._malloc((res.length + 1) * 2);
209 stringToUTF16 (res, buff, (res.length + 1) * 2);
210 return buff;
211 }, (int)native_val, is_exception);
213 mono_free (native_val);
215 if (native_res == NULL)
216 return NULL;
218 MonoString *res = mono_string_from_utf16 (native_res);
219 free (native_res);
220 return res;
223 #ifdef ENABLE_AOT
224 #include "driver-gen.c"
225 #endif
227 typedef struct WasmAssembly_ WasmAssembly;
229 struct WasmAssembly_ {
230 MonoBundledAssembly assembly;
231 WasmAssembly *next;
234 static WasmAssembly *assemblies;
235 static int assembly_count;
237 EMSCRIPTEN_KEEPALIVE void
238 mono_wasm_add_assembly (const char *name, const unsigned char *data, unsigned int size)
240 WasmAssembly *entry = (WasmAssembly *)malloc(sizeof (MonoBundledAssembly));
241 entry->assembly.name = m_strdup (name);
242 entry->assembly.data = data;
243 entry->assembly.size = size;
244 entry->next = assemblies;
245 assemblies = entry;
246 ++assembly_count;
249 EMSCRIPTEN_KEEPALIVE void
250 mono_wasm_load_runtime (const char *managed_path, int enable_debugging)
252 monoeg_g_setenv ("MONO_LOG_LEVEL", "debug", 1);
253 monoeg_g_setenv ("MONO_LOG_MASK", "gc", 1);
255 #ifdef ENABLE_AOT
256 // Defined in driver-gen.c
257 register_aot_modules ();
258 mono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY);
259 #else
260 mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP_LLVMONLY);
261 if (enable_debugging)
262 mono_wasm_enable_debugging ();
263 #endif
265 #ifndef ENABLE_AOT
266 mono_ee_interp_init ("");
267 mono_marshal_ilgen_init ();
268 mono_method_builder_ilgen_init ();
269 mono_sgen_mono_ilgen_init ();
270 #endif
271 mono_icall_table_init ();
273 if (assembly_count) {
274 MonoBundledAssembly **bundle_array = (MonoBundledAssembly **)calloc (1, sizeof (MonoBundledAssembly*) * (assembly_count + 1));
275 WasmAssembly *cur = assemblies;
276 bundle_array [assembly_count] = NULL;
277 int i = 0;
278 while (cur) {
279 bundle_array [i] = &cur->assembly;
280 cur = cur->next;
281 ++i;
283 mono_register_bundled_assemblies ((const MonoBundledAssembly**)bundle_array);
286 mono_set_assemblies_path (m_strdup (managed_path));
287 root_domain = mono_jit_init_version ("mono", "v4.0.30319");
289 mono_add_internal_call ("WebAssembly.Runtime::InvokeJS", mono_wasm_invoke_js);
290 mono_add_internal_call ("WebAssembly.Runtime::InvokeJSWithArgs", mono_wasm_invoke_js_with_args);
291 mono_add_internal_call ("WebAssembly.Runtime::GetObjectProperty", mono_wasm_get_object_property);
292 mono_add_internal_call ("WebAssembly.Runtime::SetObjectProperty", mono_wasm_set_object_property);
293 mono_add_internal_call ("WebAssembly.Runtime::GetGlobalObject", mono_wasm_get_global_object);
295 // Blazor specific custom routines - see dotnet_support.js for backing code
296 mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSMarshalled", mono_wasm_invoke_js_marshalled);
297 mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSUnmarshalled", mono_wasm_invoke_js_unmarshalled);
301 EMSCRIPTEN_KEEPALIVE MonoAssembly*
302 mono_wasm_assembly_load (const char *name)
304 MonoImageOpenStatus status;
305 MonoAssemblyName* aname = mono_assembly_name_new (name);
306 if (!name)
307 return NULL;
309 MonoAssembly *res = mono_assembly_load (aname, NULL, &status);
310 mono_assembly_name_free (aname);
312 return res;
315 EMSCRIPTEN_KEEPALIVE MonoClass*
316 mono_wasm_assembly_find_class (MonoAssembly *assembly, const char *namespace, const char *name)
318 return mono_class_from_name (mono_assembly_get_image (assembly), namespace, name);
321 EMSCRIPTEN_KEEPALIVE MonoMethod*
322 mono_wasm_assembly_find_method (MonoClass *klass, const char *name, int arguments)
324 return mono_class_get_method_from_name (klass, name, arguments);
327 EMSCRIPTEN_KEEPALIVE MonoObject*
328 mono_wasm_invoke_method (MonoMethod *method, MonoObject *this_arg, void *params[], int* got_exception)
330 MonoObject *exc = NULL;
331 MonoObject *res = mono_runtime_invoke (method, this_arg, params, &exc);
332 *got_exception = 0;
334 if (exc) {
335 *got_exception = 1;
337 MonoObject *exc2 = NULL;
338 res = (MonoObject*)mono_object_to_string (exc, &exc2);
339 if (exc2)
340 res = (MonoObject*) mono_string_new (root_domain, "Exception Double Fault");
341 return res;
344 return res;
347 EMSCRIPTEN_KEEPALIVE char *
348 mono_wasm_string_get_utf8 (MonoString *str)
350 return mono_string_to_utf8 (str); //XXX JS is responsible for freeing this
353 EMSCRIPTEN_KEEPALIVE MonoString *
354 mono_wasm_string_from_js (const char *str)
356 return mono_string_new (root_domain, str);
360 static int
361 class_is_task (MonoClass *klass)
363 if (!strcmp ("System.Threading.Tasks", mono_class_get_namespace (klass)) &&
364 (!strcmp ("Task", mono_class_get_name (klass)) || !strcmp ("Task`1", mono_class_get_name (klass))))
365 return 1;
367 return 0;
370 #define MARSHAL_TYPE_INT 1
371 #define MARSHAL_TYPE_FP 2
372 #define MARSHAL_TYPE_STRING 3
373 #define MARSHAL_TYPE_VT 4
374 #define MARSHAL_TYPE_DELEGATE 5
375 #define MARSHAL_TYPE_TASK 6
376 #define MARSHAL_TYPE_OBJECT 7
377 #define MARSHAL_TYPE_BOOL 8
379 // typed array marshalling
380 #define MARSHAL_ARRAY_BYTE 11
381 #define MARSHAL_ARRAY_UBYTE 12
382 #define MARSHAL_ARRAY_SHORT 13
383 #define MARSHAL_ARRAY_USHORT 14
384 #define MARSHAL_ARRAY_INT 15
385 #define MARSHAL_ARRAY_UINT 16
386 #define MARSHAL_ARRAY_FLOAT 17
387 #define MARSHAL_ARRAY_DOUBLE 18
389 EMSCRIPTEN_KEEPALIVE int
390 mono_wasm_get_obj_type (MonoObject *obj)
392 if (!obj)
393 return 0;
394 MonoClass *klass = mono_object_get_class (obj);
395 MonoType *type = mono_class_get_type (klass);
397 switch (mono_type_get_type (type)) {
398 // case MONO_TYPE_CHAR: prob should be done not as a number?
399 case MONO_TYPE_BOOLEAN:
400 return MARSHAL_TYPE_BOOL;
401 case MONO_TYPE_I1:
402 case MONO_TYPE_U1:
403 case MONO_TYPE_I2:
404 case MONO_TYPE_U2:
405 case MONO_TYPE_I4:
406 case MONO_TYPE_U4:
407 case MONO_TYPE_I8:
408 case MONO_TYPE_U8:
409 return MARSHAL_TYPE_INT;
410 case MONO_TYPE_R4:
411 case MONO_TYPE_R8:
412 return MARSHAL_TYPE_FP;
413 case MONO_TYPE_STRING:
414 return MARSHAL_TYPE_STRING;
415 case MONO_TYPE_SZARRAY: { // simple zero based one-dim-array
416 MonoClass *eklass = mono_class_get_element_class(klass);
417 MonoType *etype = mono_class_get_type (eklass);
419 switch (mono_type_get_type (etype)) {
420 case MONO_TYPE_U1:
421 return MARSHAL_ARRAY_UBYTE;
422 case MONO_TYPE_I1:
423 return MARSHAL_ARRAY_BYTE;
424 case MONO_TYPE_U2:
425 return MARSHAL_ARRAY_USHORT;
426 case MONO_TYPE_I2:
427 return MARSHAL_ARRAY_SHORT;
428 case MONO_TYPE_U4:
429 return MARSHAL_ARRAY_UINT;
430 case MONO_TYPE_I4:
431 return MARSHAL_ARRAY_INT;
432 case MONO_TYPE_R4:
433 return MARSHAL_ARRAY_FLOAT;
434 case MONO_TYPE_R8:
435 return MARSHAL_ARRAY_DOUBLE;
436 default:
437 return MARSHAL_TYPE_OBJECT;
440 default:
441 if (!mono_type_is_reference (type)) //vt
442 return MARSHAL_TYPE_VT;
443 if (mono_class_is_delegate (klass))
444 return MARSHAL_TYPE_DELEGATE;
445 if (class_is_task(klass))
446 return MARSHAL_TYPE_TASK;
448 return MARSHAL_TYPE_OBJECT;
453 EMSCRIPTEN_KEEPALIVE int
454 mono_unbox_int (MonoObject *obj)
456 if (!obj)
457 return 0;
458 MonoType *type = mono_class_get_type (mono_object_get_class(obj));
460 void *ptr = mono_object_unbox (obj);
461 switch (mono_type_get_type (type)) {
462 case MONO_TYPE_I1:
463 case MONO_TYPE_BOOLEAN:
464 return *(signed char*)ptr;
465 case MONO_TYPE_U1:
466 return *(unsigned char*)ptr;
467 case MONO_TYPE_I2:
468 return *(short*)ptr;
469 case MONO_TYPE_U2:
470 return *(unsigned short*)ptr;
471 case MONO_TYPE_I4:
472 return *(int*)ptr;
473 case MONO_TYPE_U4:
474 return *(unsigned int*)ptr;
475 // WASM doesn't support returning longs to JS
476 // case MONO_TYPE_I8:
477 // case MONO_TYPE_U8:
478 default:
479 printf ("Invalid type %d to mono_unbox_int\n", mono_type_get_type (type));
480 return 0;
484 EMSCRIPTEN_KEEPALIVE double
485 mono_wasm_unbox_float (MonoObject *obj)
487 if (!obj)
488 return 0;
489 MonoType *type = mono_class_get_type (mono_object_get_class(obj));
491 void *ptr = mono_object_unbox (obj);
492 switch (mono_type_get_type (type)) {
493 case MONO_TYPE_R4:
494 return *(float*)ptr;
495 case MONO_TYPE_R8:
496 return *(double*)ptr;
497 default:
498 printf ("Invalid type %d to mono_wasm_unbox_float\n", mono_type_get_type (type));
499 return 0;
503 EMSCRIPTEN_KEEPALIVE int
504 mono_wasm_array_length (MonoArray *array)
506 return mono_array_length (array);
509 EMSCRIPTEN_KEEPALIVE MonoObject*
510 mono_wasm_array_get (MonoArray *array, int idx)
512 return mono_array_get (array, MonoObject*, idx);
515 EMSCRIPTEN_KEEPALIVE MonoArray*
516 mono_wasm_obj_array_new (int size)
518 return mono_array_new (root_domain, mono_get_object_class (), size);
521 EMSCRIPTEN_KEEPALIVE void
522 mono_wasm_obj_array_set (MonoArray *array, int idx, MonoObject *obj)
524 mono_array_setref (array, idx, obj);
527 // Int8Array | int8_t | byte or SByte (signed byte)
528 // Uint8Array | uint8_t | byte or Byte (unsigned byte)
529 // Uint8ClampedArray| uint8_t | byte or Byte (unsigned byte)
530 // Int16Array | int16_t | short (signed short)
531 // Uint16Array | uint16_t | ushort (unsigned short)
532 // Int32Array | int32_t | int (signed integer)
533 // Uint32Array | uint32_t | uint (unsigned integer)
534 // Float32Array | float | float
535 // Float64Array | double | double
537 EMSCRIPTEN_KEEPALIVE MonoArray*
538 mono_wasm_typed_array_new (char *arr, int length, int size, int type)
540 MonoClass *typeClass = mono_get_byte_class(); // default is Byte
541 switch (type) {
542 case MARSHAL_ARRAY_BYTE:
543 typeClass = mono_get_sbyte_class();
544 break;
545 case MARSHAL_ARRAY_SHORT:
546 typeClass = mono_get_int16_class();
547 break;
548 case MARSHAL_ARRAY_USHORT:
549 typeClass = mono_get_uint16_class();
550 break;
551 case MARSHAL_ARRAY_INT:
552 typeClass = mono_get_int32_class();
553 break;
554 case MARSHAL_ARRAY_UINT:
555 typeClass = mono_get_uint32_class();
556 break;
557 case MARSHAL_ARRAY_FLOAT:
558 typeClass = mono_get_single_class();
559 break;
560 case MARSHAL_ARRAY_DOUBLE:
561 typeClass = mono_get_double_class();
562 break;
565 MonoArray *buffer;
567 buffer = mono_array_new (root_domain, typeClass, length);
568 memcpy(mono_array_addr_with_size(buffer, sizeof(char), 0), arr, length * size);
570 return buffer;
574 EMSCRIPTEN_KEEPALIVE void
575 mono_wasm_array_to_heap (MonoArray *src, char *dest)
577 int element_size;
578 void *source_addr;
579 int arr_length;
581 element_size = mono_array_element_size ( mono_object_get_class((MonoObject*)src));
582 //DBG("mono_wasm_to_heap element size %i / length %i\n",element_size, mono_array_length(src));
584 // get our src address
585 source_addr = mono_array_addr_with_size (src, element_size, 0);
586 // copy the array memory to heap via ptr dest
587 memcpy (dest, source_addr, mono_array_length(src) * element_size);