2008-07-12 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / jit-icalls.c
1 /*
2  * jit-icalls.c: internal calls used by the JIT
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2002 Ximian, Inc.
9  */
10
11 #include <math.h>
12
13 #include "jit-icalls.h"
14
15 void*
16 mono_ldftn (MonoMethod *method)
17 {
18         gpointer addr;
19
20         MONO_ARCH_SAVE_REGS;
21
22         addr = mono_create_jump_trampoline (mono_domain_get (), method, TRUE);
23
24         return mono_create_ftnptr (mono_domain_get (), addr);
25 }
26
27 /*
28  * Same as mono_ldftn, but do not add a synchronized wrapper. Used in the
29  * synchronized wrappers to avoid infinite recursion.
30  */
31 void*
32 mono_ldftn_nosync (MonoMethod *method)
33 {
34         gpointer addr;
35
36         MONO_ARCH_SAVE_REGS;
37
38         addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE);
39
40         return mono_create_ftnptr (mono_domain_get (), addr);
41 }
42
43 static void*
44 ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared)
45 {
46         MonoMethod *res;
47
48         MONO_ARCH_SAVE_REGS;
49
50         if (obj == NULL)
51                 mono_raise_exception (mono_get_exception_null_reference ());
52
53         res = mono_object_get_virtual_method (obj, method);
54
55         if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
56                 MonoGenericContext context = { NULL, NULL };
57
58                 if (res->klass->generic_class)
59                         context.class_inst = res->klass->generic_class->context.class_inst;
60                 else if (res->klass->generic_container)
61                         context.class_inst = res->klass->generic_container->context.class_inst;
62                 context.method_inst = mono_method_get_context (method)->method_inst;
63
64                 res = mono_class_inflate_generic_method (res, &context);
65         }
66
67         /* FIXME: only do this for methods which can be shared! */
68         if (res->is_inflated && mono_method_get_context (res)->method_inst &&
69                         mono_class_generic_sharing_enabled (res->klass)) {
70                 res = mono_marshal_get_static_rgctx_invoke (res);
71         }
72
73         return mono_ldftn (res);
74 }
75
76 void*
77 mono_ldvirtfn (MonoObject *obj, MonoMethod *method) 
78 {
79         return ldvirtfn_internal (obj, method, FALSE);
80 }
81
82 void*
83 mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method) 
84 {
85         return ldvirtfn_internal (obj, method, TRUE);
86 }
87
88 void
89 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
90 {
91         MONO_ARCH_SAVE_REGS;
92
93         if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
94                 mono_raise_exception (mono_get_exception_array_type_mismatch ());
95 }
96
97 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
98
99 gint64 
100 mono_llmult (gint64 a, gint64 b)
101 {
102         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
103         return a * b;
104 }
105
106 guint64  
107 mono_llmult_ovf_un (guint64 a, guint64 b)
108 {
109         guint32 al = a;
110         guint32 ah = a >> 32;
111         guint32 bl = b;
112         guint32 bh = b >> 32; 
113         guint64 res, t1;
114
115         MONO_ARCH_SAVE_REGS;
116
117         // fixme: this is incredible slow
118
119         if (ah && bh)
120                 goto raise_exception;
121
122         res = (guint64)al * (guint64)bl;
123
124         t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
125
126         if (t1 > 0xffffffff)
127                 goto raise_exception;
128
129         res += ((guint64)t1) << 32; 
130
131         return res;
132
133  raise_exception:
134         mono_raise_exception (mono_get_exception_overflow ());
135         return 0;
136 }
137
138 guint64  
139 mono_llmult_ovf (gint64 a, gint64 b) 
140 {
141         guint32 al = a;
142         gint32 ah = a >> 32;
143         guint32 bl = b;
144         gint32 bh = b >> 32; 
145         /*
146         Use Karatsuba algorithm where:
147                 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
148                 where Ah is the "high half" (most significant 32 bits) of a and
149                 where Al is the "low half" (least significant 32 bits) of a and
150                 where  Bh is the "high half" of b and Bl is the "low half" and
151                 where R is the Radix or "size of the half" (in our case 32 bits)
152
153         Note, for the product of two 64 bit numbers to fit into a 64
154         result, ah and/or bh must be 0.  This will save us from doing
155         the AhBh term at all.
156
157         Also note that we refactor so that we don't overflow 64 bits with 
158         intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
159         */
160
161         gint64 res, t1;
162         gint32 sign;
163
164         MONO_ARCH_SAVE_REGS;
165
166         /* need to work with absoulte values, so find out what the
167            resulting sign will be and convert any negative numbers
168            from two's complement
169         */
170         sign = ah ^ bh;
171         if (ah < 0) {
172                 if (((guint32)ah == 0x80000000) && (al == 0)) {
173                         /* This has no two's complement */
174                         if (b == 0)
175                                 return 0;
176                         else if (b == 1)
177                                 return a;
178                         else
179                                 goto raise_exception;
180                 }
181
182                 /* flip the bits and add 1 */
183                 ah ^= ~0;
184                 if (al ==  0)
185                         ah += 1;
186                 else {
187                         al ^= ~0;
188                         al +=1;
189                 }
190         }
191
192         if (bh < 0) {
193                 if (((guint32)bh == 0x80000000) && (bl == 0)) {
194                         /* This has no two's complement */
195                         if (a == 0)
196                                 return 0;
197                         else if (a == 1)
198                                 return b;
199                         else
200                                 goto raise_exception;
201                 }
202
203                 /* flip the bits and add 1 */
204                 bh ^= ~0;
205                 if (bl ==  0)
206                         bh += 1;
207                 else {
208                         bl ^= ~0;
209                         bl +=1;
210                 }
211         }
212                 
213         /* we overflow for sure if both upper halves are greater 
214            than zero because we would need to shift their 
215            product 64 bits to the left and that will not fit
216            in a 64 bit result */
217         if (ah && bh)
218                 goto raise_exception;
219         if ((gint64)((gint64)ah * (gint64)bl) > (gint64)0x80000000 || (gint64)((gint64)al * (gint64)bh) > (gint64)0x80000000)
220                 goto raise_exception;
221
222         /* do the AlBl term first */
223         t1 = (gint64)al * (gint64)bl;
224
225         res = t1;
226
227         /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
228         t1 += (gint64)(ah - al) * (gint64)(bl - bh);
229         /* check for overflow */
230         t1 <<= 32;
231         if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
232                 goto raise_exception;
233
234         res += t1;
235
236         if (res < 0)
237                 goto raise_exception;
238
239         if (sign < 0)
240                 return -res;
241         else
242                 return res;
243
244  raise_exception:
245         mono_raise_exception (mono_get_exception_overflow ());
246         return 0;
247 }
248
249 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
250
251 gint32
252 mono_idiv (gint32 a, gint32 b)
253 {
254         MONO_ARCH_SAVE_REGS;
255
256 #ifdef MONO_ARCH_NEED_DIV_CHECK
257         if (!b)
258                 mono_raise_exception (mono_get_exception_divide_by_zero ());
259         else if (b == -1 && a == (0x80000000))
260                 mono_raise_exception (mono_get_exception_arithmetic ());
261 #endif
262         return a / b;
263 }
264
265 guint32
266 mono_idiv_un (guint32 a, guint32 b)
267 {
268         MONO_ARCH_SAVE_REGS;
269
270 #ifdef MONO_ARCH_NEED_DIV_CHECK
271         if (!b)
272                 mono_raise_exception (mono_get_exception_divide_by_zero ());
273 #endif
274         return a / b;
275 }
276
277 gint32
278 mono_irem (gint32 a, gint32 b)
279 {
280         MONO_ARCH_SAVE_REGS;
281
282 #ifdef MONO_ARCH_NEED_DIV_CHECK
283         if (!b)
284                 mono_raise_exception (mono_get_exception_divide_by_zero ());
285         else if (b == -1 && a == (0x80000000))
286                 mono_raise_exception (mono_get_exception_arithmetic ());
287 #endif
288
289         return a % b;
290 }
291
292 guint32
293 mono_irem_un (guint32 a, guint32 b)
294 {
295         MONO_ARCH_SAVE_REGS;
296
297 #ifdef MONO_ARCH_NEED_DIV_CHECK
298         if (!b)
299                 mono_raise_exception (mono_get_exception_divide_by_zero ());
300 #endif
301         return a % b;
302 }
303
304 #endif
305
306 #ifdef MONO_ARCH_EMULATE_MUL_DIV
307
308 gint32
309 mono_imul (gint32 a, gint32 b)
310 {
311         MONO_ARCH_SAVE_REGS;
312
313         return a * b;
314 }
315
316 gint32
317 mono_imul_ovf (gint32 a, gint32 b)
318 {
319         gint64 res;
320
321         MONO_ARCH_SAVE_REGS;
322
323         res = (gint64)a * (gint64)b;
324
325         if ((res > 0x7fffffffL) || (res < -2147483648))
326                 mono_raise_exception (mono_get_exception_overflow ());
327
328         return res;
329 }
330
331 gint32
332 mono_imul_ovf_un (guint32 a, guint32 b)
333 {
334         guint64 res;
335
336         MONO_ARCH_SAVE_REGS;
337
338         res = (guint64)a * (guint64)b;
339
340         if ((res >> 32))
341                 mono_raise_exception (mono_get_exception_overflow ());
342
343         return res;
344 }
345 #endif
346
347 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT)
348 double
349 mono_fdiv (double a, double b)
350 {
351         MONO_ARCH_SAVE_REGS;
352
353         return a / b;
354 }
355 #endif
356
357 gint64 
358 mono_lldiv (gint64 a, gint64 b)
359 {
360         MONO_ARCH_SAVE_REGS;
361
362 #ifdef MONO_ARCH_NEED_DIV_CHECK
363         if (!b)
364                 mono_raise_exception (mono_get_exception_divide_by_zero ());
365         else if (b == -1 && a == (-9223372036854775807LL - 1LL))
366                 mono_raise_exception (mono_get_exception_arithmetic ());
367 #endif
368         return a / b;
369 }
370
371 gint64 
372 mono_llrem (gint64 a, gint64 b)
373 {
374         MONO_ARCH_SAVE_REGS;
375
376 #ifdef MONO_ARCH_NEED_DIV_CHECK
377         if (!b)
378                 mono_raise_exception (mono_get_exception_divide_by_zero ());
379         else if (b == -1 && a == (-9223372036854775807LL - 1LL))
380                 mono_raise_exception (mono_get_exception_arithmetic ());
381 #endif
382         return a % b;
383 }
384
385 guint64 
386 mono_lldiv_un (guint64 a, guint64 b)
387 {
388         MONO_ARCH_SAVE_REGS;
389
390 #ifdef MONO_ARCH_NEED_DIV_CHECK
391         if (!b)
392                 mono_raise_exception (mono_get_exception_divide_by_zero ());
393 #endif
394         return a / b;
395 }
396
397 guint64 
398 mono_llrem_un (guint64 a, guint64 b)
399 {
400         MONO_ARCH_SAVE_REGS;
401
402 #ifdef MONO_ARCH_NEED_DIV_CHECK
403         if (!b)
404                 mono_raise_exception (mono_get_exception_divide_by_zero ());
405 #endif
406         return a % b;
407 }
408
409 #endif
410
411 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
412
413 guint64 
414 mono_lshl (guint64 a, gint32 shamt)
415 {
416         guint64 res;
417
418         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
419         res = a << shamt;
420
421         /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
422
423         return res;
424 }
425
426 guint64 
427 mono_lshr_un (guint64 a, gint32 shamt)
428 {
429         guint64 res;
430
431         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
432         res = a >> shamt;
433
434         /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
435
436         return res;
437 }
438
439 gint64 
440 mono_lshr (gint64 a, gint32 shamt)
441 {
442         gint64 res;
443
444         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
445         res = a >> shamt;
446
447         /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
448
449         return res;
450 }
451
452 #endif
453
454 #ifdef MONO_ARCH_SOFT_FLOAT
455
456 double
457 mono_fsub (double a, double b)
458 {
459         return a - b;
460 }
461
462 double
463 mono_fadd (double a, double b)
464 {
465         return a + b;
466 }
467
468 double
469 mono_fmul (double a, double b)
470 {
471         return a * b;
472 }
473
474 double
475 mono_fneg (double a)
476 {
477         return -a;
478 }
479
480 double
481 mono_fconv_r4 (double a)
482 {
483         return (float)a;
484 }
485
486 double
487 mono_conv_to_r8 (int a)
488 {
489         return (double)a;
490 }
491
492 double
493 mono_conv_to_r4 (int a)
494 {
495         return (double)(float)a;
496 }
497
498 gint8
499 mono_fconv_i1 (double a)
500 {
501         return (gint8)a;
502 }
503
504 gint16
505 mono_fconv_i2 (double a)
506 {
507         return (gint16)a;
508 }
509
510 gint32
511 mono_fconv_i4 (double a)
512 {
513         return (gint32)a;
514 }
515
516 guint8
517 mono_fconv_u1 (double a)
518 {
519         return (guint8)a;
520 }
521
522 guint16
523 mono_fconv_u2 (double a)
524 {
525         return (guint16)a;
526 }
527
528 gboolean
529 mono_fcmp_eq (double a, double b)
530 {
531         return a == b;
532 }
533
534 gboolean
535 mono_fcmp_ge (double a, double b)
536 {
537         return a >= b;
538 }
539
540 gboolean
541 mono_fcmp_gt (double a, double b)
542 {
543         return a > b;
544 }
545
546 gboolean
547 mono_fcmp_le (double a, double b)
548 {
549         return a <= b;
550 }
551
552 gboolean
553 mono_fcmp_lt (double a, double b)
554 {
555         return a < b;
556 }
557
558 gboolean
559 mono_fcmp_ne_un (double a, double b)
560 {
561         return isunordered (a, b) || a != b;
562 }
563
564 gboolean
565 mono_fcmp_ge_un (double a, double b)
566 {
567         return isunordered (a, b) || a >= b;
568 }
569
570 gboolean
571 mono_fcmp_gt_un (double a, double b)
572 {
573         return isunordered (a, b) || a > b;
574 }
575
576 gboolean
577 mono_fcmp_le_un (double a, double b)
578 {
579         return isunordered (a, b) || a <= b;
580 }
581
582 gboolean
583 mono_fcmp_lt_un (double a, double b)
584 {
585         return isunordered (a, b) || a < b;
586 }
587
588 gboolean
589 mono_fceq (double a, double b)
590 {
591         return a == b;
592 }
593
594 gboolean
595 mono_fcgt (double a, double b)
596 {
597         return a > b;
598 }
599
600 gboolean
601 mono_fcgt_un (double a, double b)
602 {
603         return a > b;
604 }
605
606 gboolean
607 mono_fclt (double a, double b)
608 {
609         return a < b;
610 }
611
612 gboolean
613 mono_fclt_un (double a, double b)
614 {
615         return a < b;
616 }
617
618 double
619 mono_fload_r4 (float *ptr)
620 {
621         return *ptr;
622 }
623
624 void
625 mono_fstore_r4 (double val, float *ptr)
626 {
627         *ptr = (float)val;
628 }
629
630 /* returns the integer bitpattern that is passed in the regs or stack */
631 guint32
632 mono_fload_r4_arg (double val)
633 {
634         float v = (float)val;
635         return *(guint32*)&v;
636 }
637
638 #endif
639
640 MonoArray *
641 mono_array_new_va (MonoMethod *cm, ...)
642 {
643         MonoDomain *domain = mono_domain_get ();
644         va_list ap;
645         guint32 *lengths;
646         guint32 *lower_bounds;
647         int pcount;
648         int rank;
649         int i, d;
650
651         MONO_ARCH_SAVE_REGS;
652
653         pcount = mono_method_signature (cm)->param_count;
654         rank = cm->klass->rank;
655
656         va_start (ap, cm);
657         
658         lengths = alloca (sizeof (guint32) * pcount);
659         for (i = 0; i < pcount; ++i)
660                 lengths [i] = d = va_arg(ap, int);
661
662         if (rank == pcount) {
663                 /* Only lengths provided. */
664                 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
665                         lower_bounds = alloca (sizeof (guint32) * rank);
666                         memset (lower_bounds, 0, sizeof (guint32) * rank);
667                 } else {
668                         lower_bounds = NULL;
669                 }
670         } else {
671                 g_assert (pcount == (rank * 2));
672                 /* lower bounds are first. */
673                 lower_bounds = lengths;
674                 lengths += rank;
675         }
676         va_end(ap);
677
678         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
679 }
680
681 /* Specialized version of mono_array_new_va () which avoids varargs */
682 MonoArray *
683 mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
684 {
685         MonoDomain *domain = mono_domain_get ();
686         guint32 lengths [2];
687         guint32 *lower_bounds;
688         int pcount;
689         int rank;
690
691         MONO_ARCH_SAVE_REGS;
692
693         pcount = mono_method_signature (cm)->param_count;
694         rank = cm->klass->rank;
695
696         lengths [0] = length1;
697         lengths [1] = length2;
698
699         g_assert (rank == pcount);
700
701         if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
702                 lower_bounds = alloca (sizeof (guint32) * rank);
703                 memset (lower_bounds, 0, sizeof (guint32) * rank);
704         } else {
705                 lower_bounds = NULL;
706         }
707
708         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
709 }
710
711 gpointer
712 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
713 {
714         MonoVTable *vtable;
715         gpointer addr;
716         
717         MONO_ARCH_SAVE_REGS;
718
719         //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
720
721         mono_class_init (field->parent);
722
723         vtable = mono_class_vtable (domain, field->parent);
724         if (!vtable->initialized)
725                 mono_runtime_class_init (vtable);
726
727         //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
728
729         if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
730                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
731         else
732                 addr = (char*)vtable->data + field->offset;
733         
734         return addr;
735 }
736
737 gpointer
738 mono_ldtoken_wrapper (MonoImage *image, int token, MonoGenericContext *context)
739 {
740         MonoClass *handle_class;
741         gpointer res;
742
743         MONO_ARCH_SAVE_REGS;
744         res = mono_ldtoken (image, token, &handle_class, context);      
745         mono_class_init (handle_class);
746
747         return res;
748 }
749
750 gpointer
751 mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *method)
752 {
753         MonoMethodSignature *sig = mono_method_signature (method);
754         MonoGenericContext *generic_context;
755
756         if (sig->is_inflated) {
757                 generic_context = mono_method_get_context (method);
758         } else {
759                 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
760                 g_assert (generic_container);
761                 generic_context = &generic_container->context;
762         }
763
764         return mono_ldtoken_wrapper (image, token, generic_context);
765 }
766
767 guint64
768 mono_fconv_u8 (double v)
769 {
770         return (guint64)v;
771 }
772
773 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
774 gint64
775 mono_fconv_i8 (double v)
776 {
777         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
778         return (gint64)v;
779 }
780 #endif
781
782 guint32
783 mono_fconv_u4 (double v)
784 {
785         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
786         return (guint32)v;
787 }
788
789 #ifndef HAVE_TRUNC
790 /* Solaris doesn't have trunc */
791 #ifdef HAVE_AINTL
792 extern long double aintl (long double);
793 #define trunc aintl
794 #else
795 /* FIXME: This means we will never throw overflow exceptions */
796 #define trunc(v) res
797 #endif
798 #endif /* HAVE_TRUNC */
799
800 gint64
801 mono_fconv_ovf_i8 (double v)
802 {
803         gint64 res;
804
805         MONO_ARCH_SAVE_REGS;
806
807         res = (gint64)v;
808
809         if (isnan(v) || trunc (v) != res) {
810                 mono_raise_exception (mono_get_exception_overflow ());
811         }
812         return res;
813 }
814
815 guint64
816 mono_fconv_ovf_u8 (double v)
817 {
818         guint64 res;
819
820         MONO_ARCH_SAVE_REGS;
821     
822         res = (guint64)v;
823
824         if (isnan(v) || trunc (v) != res) {
825                 mono_raise_exception (mono_get_exception_overflow ());
826         }
827         return res;
828 }
829
830 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
831 double
832 mono_lconv_to_r8 (gint64 a)
833 {
834         return (double)a;
835 }
836 #endif
837
838 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
839 float
840 mono_lconv_to_r4 (gint64 a)
841 {
842         return (float)a;
843 }
844 #endif
845
846 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
847 double
848 mono_conv_to_r8_un (guint32 a)
849 {
850         return (double)a;
851 }
852 #endif
853
854 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
855 double
856 mono_lconv_to_r8_un (guint64 a)
857 {
858         return (double)a;
859 }
860 #endif
861
862 gpointer
863 mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, MonoGenericContext *context, gpointer *this_arg)
864 {
865         MonoMethod *vmethod, *inflated;
866         gpointer addr;
867
868         mono_jit_stats.generic_virtual_invocations++;
869
870         if (obj == NULL)
871                 mono_raise_exception (mono_get_exception_null_reference ());
872         vmethod = mono_object_get_virtual_method (obj, method);
873
874         /* 'vmethod' is partially inflated.  All the blanks corresponding to the type parameters of the
875            declaring class have been inflated.  We still need to fully inflate the method parameters.
876
877            FIXME: This code depends on the declaring class being fully inflated, since we inflate it twice with 
878            the same context.
879         */
880         g_assert (!vmethod->klass->generic_container);
881         g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
882         g_assert (!context->method_inst || !context->method_inst->is_open);
883         inflated = mono_class_inflate_generic_method (vmethod, context);
884         if (mono_class_generic_sharing_enabled (inflated->klass) &&
885                         mono_method_is_generic_sharable_impl (method, FALSE)) {
886                 /* The method is shared generic code, so it needs a
887                    MRGCTX. */
888                 inflated = mono_marshal_get_static_rgctx_invoke (inflated);
889         }
890         addr = mono_compile_method (inflated);
891
892         /* Since this is a virtual call, have to unbox vtypes */
893         if (obj->vtable->klass->valuetype)
894                 *this_arg = mono_object_unbox (obj);
895         else
896                 *this_arg = obj;
897
898         return addr;
899 }
900
901 gpointer
902 mono_helper_compile_generic_method_wo_context (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
903 {
904         MonoGenericContext *context = mono_method_get_context (method);
905
906         return mono_helper_compile_generic_method (obj, method, context, this_arg);
907 }
908
909 MonoString*
910 mono_helper_ldstr (MonoImage *image, guint32 idx)
911 {
912         return mono_ldstr (mono_domain_get (), image, idx);
913 }
914
915 MonoString*
916 mono_helper_ldstr_mscorlib (guint32 idx)
917 {
918         return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
919 }
920
921 MonoObject*
922 mono_helper_newobj_mscorlib (guint32 idx)
923 {
924         MonoClass *klass = mono_class_get (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx);
925         
926         g_assert (klass);
927
928         return mono_object_new (mono_domain_get (), klass);
929 }
930
931 /*
932  * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
933  * in generated code. So instead we emit a call to this function and place a gdb
934  * breakpoint here.
935  */
936 void
937 mono_break (void)
938 {
939 }
940
941 MonoException *
942 mono_create_corlib_exception_0 (guint32 token)
943 {
944         return mono_exception_from_token (mono_defaults.corlib, token);
945 }
946
947 MonoException *
948 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
949 {
950         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
951 }
952
953 MonoException *
954 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
955 {
956         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
957 }