Merge pull request #4840 from kumpera/unaligned-access
[mono.git] / mono / mini / interp / interp.c
1 /**
2  * \file
3  * PLEASE NOTE: This is a research prototype.
4  *
5  *
6  * interp.c: Interpreter for CIL byte codes
7  *
8  * Authors:
9  *   Paolo Molaro (lupus@ximian.com)
10  *   Miguel de Icaza (miguel@ximian.com)
11  *   Dietmar Maurer (dietmar@ximian.com)
12  *
13  * (C) 2001, 2002 Ximian, Inc.
14  */
15 #ifndef __USE_ISOC99
16 #define __USE_ISOC99
17 #endif
18 #include "config.h"
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <glib.h>
23 #include <setjmp.h>
24 #include <signal.h>
25 #include <math.h>
26 #include <locale.h>
27
28 #include <mono/utils/gc_wrapper.h>
29
30 #ifdef HAVE_ALLOCA_H
31 #   include <alloca.h>
32 #else
33 #   ifdef __CYGWIN__
34 #      define alloca __builtin_alloca
35 #   endif
36 #endif
37
38 /* trim excessive headers */
39 #include <mono/metadata/image.h>
40 #include <mono/metadata/assembly-internals.h>
41 #include <mono/metadata/cil-coff.h>
42 #include <mono/metadata/mono-endian.h>
43 #include <mono/metadata/tabledefs.h>
44 #include <mono/metadata/tokentype.h>
45 #include <mono/metadata/loader.h>
46 #include <mono/metadata/threads.h>
47 #include <mono/metadata/threadpool.h>
48 #include <mono/metadata/profiler-private.h>
49 #include <mono/metadata/appdomain.h>
50 #include <mono/metadata/reflection.h>
51 #include <mono/metadata/reflection-internals.h>
52 #include <mono/metadata/exception.h>
53 #include <mono/metadata/verify.h>
54 #include <mono/metadata/opcodes.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/mono-config.h>
57 #include <mono/metadata/marshal.h>
58 #include <mono/metadata/environment.h>
59 #include <mono/metadata/mono-debug.h>
60 #include <mono/utils/atomic.h>
61
62 #include "interp.h"
63 #include "interp-internals.h"
64 #include "mintops.h"
65 #include "hacks.h"
66
67 #include <mono/mini/mini.h>
68 #include <mono/mini/jit-icalls.h>
69
70 #ifdef TARGET_ARM
71 #include <mono/mini/mini-arm.h>
72 #endif
73
74 /* Mingw 2.1 doesnt need this any more, but leave it in for now for older versions */
75 #ifdef _WIN32
76 #define isnan _isnan
77 #define finite _finite
78 #endif
79 #ifndef HAVE_FINITE
80 #ifdef HAVE_ISFINITE
81 #define finite isfinite
82 #endif
83 #endif
84
85 static inline void
86 init_frame (MonoInvocation *frame, MonoInvocation *parent_frame, RuntimeMethod *rmethod, stackval *method_args, stackval *method_retval)
87 {
88         frame->parent = parent_frame;
89         frame->stack_args = method_args;
90         frame->retval = method_retval;
91         frame->runtime_method = rmethod;
92         frame->ex = NULL;
93         frame->ip = NULL;
94         frame->invoke_trap = 0;
95 }
96
97 #define INIT_FRAME(frame,parent_frame,method_args,method_retval,domain,mono_method,error) do { \
98         RuntimeMethod *_rmethod = mono_interp_get_runtime_method ((domain), (mono_method), (error));    \
99         init_frame ((frame), (parent_frame), _rmethod, (method_args), (method_retval)); \
100         } while (0)
101
102 /*
103  * List of classes whose methods will be executed by transitioning to JITted code.
104  * Used for testing.
105  */
106 GSList *jit_classes;
107
108 void ves_exec_method (MonoInvocation *frame);
109
110 static char* dump_frame (MonoInvocation *inv);
111 static MonoArray *get_trace_ips (MonoDomain *domain, MonoInvocation *top);
112 static void ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, unsigned short *start_with_ip, MonoException *filter_exception, int exit_at_finally);
113
114 typedef void (*ICallMethod) (MonoInvocation *frame);
115
116 static guint32 die_on_exception = 0;
117 static MonoNativeTlsKey thread_context_id;
118
119 static char* dump_args (MonoInvocation *inv);
120
121 #define DEBUG_INTERP 0
122 #define COUNT_OPS 0
123 #if DEBUG_INTERP
124 int mono_interp_traceopt = 2;
125 /* If true, then we output the opcodes as we interpret them */
126 static int global_tracing = 2;
127
128 static int debug_indent_level = 0;
129
130 static int break_on_method = 0;
131 static int nested_trace = 0;
132 static GList *db_methods = NULL;
133
134 static void
135 output_indent (void)
136 {
137         int h;
138
139         for (h = 0; h < debug_indent_level; h++)
140                 g_print ("  ");
141 }
142
143 static void
144 db_match_method (gpointer data, gpointer user_data)
145 {
146         MonoMethod *m = (MonoMethod*)user_data;
147         MonoMethodDesc *desc = data;
148
149         if (mono_method_desc_full_match (desc, m))
150                 break_on_method = 1;
151 }
152
153 static void
154 debug_enter (MonoInvocation *frame, int *tracing)
155 {
156         if (db_methods) {
157                 g_list_foreach (db_methods, db_match_method, (gpointer)frame->runtime_method->method);
158                 if (break_on_method)
159                         *tracing = nested_trace ? (global_tracing = 2, 3) : 2;
160                 break_on_method = 0;
161         }
162         if (*tracing) {
163                 MonoMethod *method = frame->runtime_method->method;
164                 char *mn, *args = dump_args (frame);
165                 debug_indent_level++;
166                 output_indent ();
167                 mn = mono_method_full_name (method, FALSE);
168                 g_print ("(%p) Entering %s (", mono_thread_internal_current (), mn);
169                 g_free (mn);
170                 g_print  ("%s)\n", args);
171                 g_free (args);
172         }
173         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)
174                 mono_profiler_method_enter (frame->runtime_method->method);
175 }
176
177
178 #define DEBUG_LEAVE()   \
179         if (tracing) {  \
180                 char *mn, *args;        \
181                 args = dump_retval (frame);     \
182                 output_indent ();       \
183                 mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
184                 g_print  ("(%p) Leaving %s", mono_thread_internal_current (),  mn);     \
185                 g_free (mn); \
186                 g_print  (" => %s\n", args);    \
187                 g_free (args);  \
188                 debug_indent_level--;   \
189                 if (tracing == 3) global_tracing = 0; \
190         }       \
191         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)    \
192                 mono_profiler_method_leave (frame->runtime_method->method);
193
194 #else
195
196 int mono_interp_traceopt = 0;
197 static void debug_enter (MonoInvocation *frame, int *tracing)
198 {
199 }
200 #define DEBUG_LEAVE()
201
202 #endif
203
204 /* Set the current execution state to the resume state in context */
205 #define SET_RESUME_STATE(context) do { \
206                 ip = (context)->handler_ip;                                             \
207                 sp->data.p = frame->ex;                                                                                 \
208                 ++sp;                                                                                                                   \
209                 frame->ex = NULL;                                                                                               \
210                 (context)->has_resume_state = 0;                                                                \
211                 (context)->handler_frame = NULL;                                                                \
212                 goto main_loop;                                                                                                 \
213         } while (0)
214
215 static void
216 ves_real_abort (int line, MonoMethod *mh,
217                 const unsigned short *ip, stackval *stack, stackval *sp)
218 {
219         MonoError error;
220         fprintf (stderr, "Execution aborted in method: %s::%s\n", mh->klass->name, mh->name);
221         fprintf (stderr, "Line=%d IP=0x%04lx, Aborted execution\n", line,
222                  ip-(const unsigned short *)mono_method_get_header_checked (mh, &error)->code);
223                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
224         g_print ("0x%04x %02x\n",
225                  ip-(const unsigned short *)mono_method_get_header_checked (mh, &error)->code, *ip);
226         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
227         if (sp > stack)
228                 printf ("\t[%ld] 0x%08x %0.5f\n", sp-stack, sp[-1].data.i, sp[-1].data.f);
229 }
230
231 #define ves_abort() \
232         do {\
233                 ves_real_abort(__LINE__, frame->runtime_method->method, ip, frame->stack, sp); \
234                 THROW_EX (mono_get_exception_execution_engine (NULL), ip); \
235         } while (0);
236
237 RuntimeMethod*
238 mono_interp_get_runtime_method (MonoDomain *domain, MonoMethod *method, MonoError *error)
239 {
240         RuntimeMethod *rtm;
241         MonoJitDomainInfo *info;
242         MonoMethodSignature *sig;
243         int i;
244
245         error_init (error);
246
247         info = domain_jit_info (domain);
248         mono_domain_jit_code_hash_lock (domain);
249         rtm = mono_internal_hash_table_lookup (&info->interp_code_hash, method);
250         mono_domain_jit_code_hash_unlock (domain);
251         if (rtm)
252                 return rtm;
253
254         sig = mono_method_signature (method);
255
256         rtm = mono_domain_alloc0 (domain, sizeof (RuntimeMethod));
257         rtm->method = method;
258         rtm->param_count = sig->param_count;
259         rtm->hasthis = sig->hasthis;
260         rtm->rtype = mini_get_underlying_type (sig->ret);
261         rtm->param_types = mono_domain_alloc0 (domain, sizeof (MonoType*) * sig->param_count);
262         for (i = 0; i < sig->param_count; ++i)
263                 rtm->param_types [i] = mini_get_underlying_type (sig->params [i]);
264
265         mono_domain_jit_code_hash_lock (domain);
266         if (!mono_internal_hash_table_lookup (&info->interp_code_hash, method))
267                 mono_internal_hash_table_insert (&info->interp_code_hash, method, rtm);
268         mono_domain_jit_code_hash_unlock (domain);
269
270         return rtm;
271 }
272
273 gpointer
274 mono_interp_create_trampoline (MonoDomain *domain, MonoMethod *method, MonoError *error)
275 {
276         if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
277                 method = mono_marshal_get_synchronized_wrapper (method);
278         return mono_interp_get_runtime_method (domain, method, error);
279 }
280
281 static inline RuntimeMethod*
282 get_virtual_method (MonoDomain *domain, RuntimeMethod *runtime_method, MonoObject *obj)
283 {
284         MonoMethod *m = runtime_method->method;
285         MonoError error;
286
287         if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
288                 RuntimeMethod *ret = NULL;
289                 if (mono_object_is_transparent_proxy (obj)) {
290                         ret = mono_interp_get_runtime_method (domain, mono_marshal_get_remoting_invoke (m), &error);
291                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
292                 } else if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
293                         ret = mono_interp_get_runtime_method (domain, mono_marshal_get_synchronized_wrapper (m), &error);
294                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
295                 } else {
296                         ret = runtime_method;
297                 }
298                 return ret;
299         }
300
301         mono_class_setup_vtable (obj->vtable->klass);
302
303         int slot = mono_method_get_vtable_slot (m);
304         if (mono_class_is_interface (m->klass)) {
305                 g_assert (obj->vtable->klass != m->klass);
306                 /* TODO: interface offset lookup is slow, go through IMT instead */
307                 gboolean non_exact_match;
308                 slot += mono_class_interface_offset_with_variance (obj->vtable->klass, m->klass, &non_exact_match);
309         }
310
311         MonoMethod *virtual_method = obj->vtable->klass->vtable [slot];
312         if (m->is_inflated && mono_method_get_context (m)->method_inst) {
313                 MonoGenericContext context = { NULL, NULL };
314
315                 if (mono_class_is_ginst (virtual_method->klass))
316                         context.class_inst = mono_class_get_generic_class (virtual_method->klass)->context.class_inst;
317                 else if (mono_class_is_gtd (virtual_method->klass))
318                         context.class_inst = mono_class_get_generic_container (virtual_method->klass)->context.class_inst;
319                 context.method_inst = mono_method_get_context (m)->method_inst;
320
321                 virtual_method = mono_class_inflate_generic_method_checked (virtual_method, &context, &error);
322                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
323         }
324
325         if (virtual_method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
326                 virtual_method = mono_marshal_get_synchronized_wrapper (virtual_method);
327         }
328
329         RuntimeMethod *virtual_runtime_method = mono_interp_get_runtime_method (domain, virtual_method, &error);
330         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
331         return virtual_runtime_method;
332 }
333
334 static void inline
335 stackval_from_data (MonoType *type, stackval *result, char *data, gboolean pinvoke)
336 {
337         if (type->byref) {
338                 switch (type->type) {
339                 case MONO_TYPE_OBJECT:
340                 case MONO_TYPE_CLASS:
341                 case MONO_TYPE_STRING:
342                 case MONO_TYPE_ARRAY:
343                 case MONO_TYPE_SZARRAY:
344                         break;
345                 default:
346                         break;
347                 }
348                 result->data.p = *(gpointer*)data;
349                 return;
350         }
351         switch (type->type) {
352         case MONO_TYPE_VOID:
353                 return;
354         case MONO_TYPE_I1:
355                 result->data.i = *(gint8*)data;
356                 return;
357         case MONO_TYPE_U1:
358         case MONO_TYPE_BOOLEAN:
359                 result->data.i = *(guint8*)data;
360                 return;
361         case MONO_TYPE_I2:
362                 result->data.i = *(gint16*)data;
363                 return;
364         case MONO_TYPE_U2:
365         case MONO_TYPE_CHAR:
366                 result->data.i = *(guint16*)data;
367                 return;
368         case MONO_TYPE_I4:
369                 result->data.i = *(gint32*)data;
370                 return;
371         case MONO_TYPE_U:
372         case MONO_TYPE_I:
373                 result->data.nati = *(mono_i*)data;
374                 return;
375         case MONO_TYPE_PTR:
376                 result->data.p = *(gpointer*)data;
377                 return;
378         case MONO_TYPE_U4:
379                 result->data.i = *(guint32*)data;
380                 return;
381         case MONO_TYPE_R4:
382                 result->data.f = *(float*)data;
383                 return;
384         case MONO_TYPE_I8:
385         case MONO_TYPE_U8:
386                 result->data.l = *(gint64*)data;
387                 return;
388         case MONO_TYPE_R8:
389                 result->data.f = *(double*)data;
390                 return;
391         case MONO_TYPE_STRING:
392         case MONO_TYPE_SZARRAY:
393         case MONO_TYPE_CLASS:
394         case MONO_TYPE_OBJECT:
395         case MONO_TYPE_ARRAY:
396                 result->data.p = *(gpointer*)data;
397                 return;
398         case MONO_TYPE_VALUETYPE:
399                 if (type->data.klass->enumtype) {
400                         stackval_from_data (mono_class_enum_basetype (type->data.klass), result, data, pinvoke);
401                         return;
402                 } else
403                         mono_value_copy (result->data.vt, data, type->data.klass);
404                 return;
405         case MONO_TYPE_GENERICINST: {
406                 if (mono_type_generic_inst_is_valuetype (type)) {
407                         mono_value_copy (result->data.vt, data, mono_class_from_mono_type (type));
408                         return;
409                 }
410                 stackval_from_data (&type->data.generic_class->container_class->byval_arg, result, data, pinvoke);
411                 return;
412         }
413         default:
414                 g_warning ("got type 0x%02x", type->type);
415                 g_assert_not_reached ();
416         }
417 }
418
419 static void inline
420 stackval_to_data (MonoType *type, stackval *val, char *data, gboolean pinvoke)
421 {
422         if (type->byref) {
423                 gpointer *p = (gpointer*)data;
424                 *p = val->data.p;
425                 return;
426         }
427         /* printf ("TODAT0 %p\n", data); */
428         switch (type->type) {
429         case MONO_TYPE_I1:
430         case MONO_TYPE_U1: {
431                 guint8 *p = (guint8*)data;
432                 *p = val->data.i;
433                 return;
434         }
435         case MONO_TYPE_BOOLEAN: {
436                 guint8 *p = (guint8*)data;
437                 *p = (val->data.i != 0);
438                 return;
439         }
440         case MONO_TYPE_I2:
441         case MONO_TYPE_U2:
442         case MONO_TYPE_CHAR: {
443                 guint16 *p = (guint16*)data;
444                 *p = val->data.i;
445                 return;
446         }
447         case MONO_TYPE_I: {
448                 mono_i *p = (mono_i*)data;
449                 /* In theory the value used by stloc should match the local var type
450                    but in practice it sometimes doesn't (a int32 gets dup'd and stloc'd into
451                    a native int - both by csc and mcs). Not sure what to do about sign extension
452                    as it is outside the spec... doing the obvious */
453                 *p = (mono_i)val->data.nati;
454                 return;
455         }
456         case MONO_TYPE_U: {
457                 mono_u *p = (mono_u*)data;
458                 /* see above. */
459                 *p = (mono_u)val->data.nati;
460                 return;
461         }
462         case MONO_TYPE_I4:
463         case MONO_TYPE_U4: {
464                 gint32 *p = (gint32*)data;
465                 *p = val->data.i;
466                 return;
467         }
468         case MONO_TYPE_I8:
469         case MONO_TYPE_U8: {
470                 gint64 *p = (gint64*)data;
471                 *p = val->data.l;
472                 return;
473         }
474         case MONO_TYPE_R4: {
475                 float *p = (float*)data;
476                 *p = val->data.f;
477                 return;
478         }
479         case MONO_TYPE_R8: {
480                 double *p = (double*)data;
481                 *p = val->data.f;
482                 return;
483         }
484         case MONO_TYPE_STRING:
485         case MONO_TYPE_SZARRAY:
486         case MONO_TYPE_CLASS:
487         case MONO_TYPE_OBJECT:
488         case MONO_TYPE_ARRAY: {
489                 gpointer *p = (gpointer *) data;
490                 mono_gc_wbarrier_generic_store (p, val->data.p);
491                 return;
492         }
493         case MONO_TYPE_PTR: {
494                 gpointer *p = (gpointer *) data;
495                 *p = val->data.p;
496                 return;
497         }
498         case MONO_TYPE_VALUETYPE:
499                 if (type->data.klass->enumtype) {
500                         stackval_to_data (mono_class_enum_basetype (type->data.klass), val, data, pinvoke);
501                         return;
502                 } else
503                         mono_value_copy (data, val->data.vt, type->data.klass);
504                 return;
505         case MONO_TYPE_GENERICINST: {
506                 MonoClass *container_class = type->data.generic_class->container_class;
507
508                 if (container_class->valuetype && !container_class->enumtype) {
509                         mono_value_copy (data, val->data.vt, mono_class_from_mono_type (type));
510                         return;
511                 }
512                 stackval_to_data (&type->data.generic_class->container_class->byval_arg, val, data, pinvoke);
513                 return;
514         }
515         default:
516                 g_warning ("got type %x", type->type);
517                 g_assert_not_reached ();
518         }
519 }
520
521 static void
522 fill_in_trace (MonoException *exception, MonoInvocation *frame)
523 {
524         MonoError error;
525         char *stack_trace = dump_frame (frame);
526         MonoDomain *domain = mono_domain_get();
527         (exception)->stack_trace = mono_string_new_checked (domain, stack_trace, &error);
528         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
529         (exception)->trace_ips = get_trace_ips (domain, frame);
530         g_free (stack_trace);
531 }
532
533 #define FILL_IN_TRACE(exception, frame) fill_in_trace(exception, frame)
534
535 #define THROW_EX(exception,ex_ip)       \
536         do {\
537                 frame->ip = (ex_ip);            \
538                 frame->ex = (MonoException*)(exception);        \
539                 FILL_IN_TRACE(frame->ex, frame); \
540                 goto handle_exception;  \
541         } while (0)
542
543 static MonoObject*
544 ves_array_create (MonoInvocation *frame, MonoDomain *domain, MonoClass *klass, MonoMethodSignature *sig, stackval *values)
545 {
546         uintptr_t *lengths;
547         intptr_t *lower_bounds;
548         MonoObject *obj;
549         MonoError error;
550         int i;
551
552         lengths = alloca (sizeof (uintptr_t) * klass->rank * 2);
553         for (i = 0; i < sig->param_count; ++i) {
554                 lengths [i] = values->data.i;
555                 values ++;
556         }
557         if (klass->rank == sig->param_count) {
558                 /* Only lengths provided. */
559                 lower_bounds = NULL;
560         } else {
561                 /* lower bounds are first. */
562                 lower_bounds = (intptr_t *) lengths;
563                 lengths += klass->rank;
564         }
565         obj = (MonoObject*) mono_array_new_full_checked (domain, klass, lengths, lower_bounds, &error);
566         if (!mono_error_ok (&error)) {
567                 frame->ex = mono_error_convert_to_exception (&error);
568                 FILL_IN_TRACE (frame->ex, frame);
569         }
570         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
571         return obj;
572 }
573
574 static gint32
575 ves_array_calculate_index (MonoArray *ao, stackval *sp, MonoInvocation *frame, gboolean safe)
576 {
577         g_assert (!frame->ex);
578         MonoClass *ac = ((MonoObject *) ao)->vtable->klass;
579
580         guint32 pos = 0;
581         if (ao->bounds) {
582                 for (gint32 i = 0; i < ac->rank; i++) {
583                         guint32 idx = sp [i].data.i;
584                         guint32 lower = ao->bounds [i].lower_bound;
585                         guint32 len = ao->bounds [i].length;
586                         if (safe && (idx < lower || (idx - lower) >= len)) {
587                                 frame->ex = mono_get_exception_index_out_of_range ();
588                                 FILL_IN_TRACE (frame->ex, frame);
589                                 return -1;
590                         }
591                         pos = (pos * len) + idx - lower;
592                 }
593         } else {
594                 pos = sp [0].data.i;
595                 if (safe && pos >= ao->max_length) {
596                         frame->ex = mono_get_exception_index_out_of_range ();
597                         FILL_IN_TRACE (frame->ex, frame);
598                         return -1;
599                 }
600         }
601         return pos;
602 }
603
604 static void
605 ves_array_set (MonoInvocation *frame)
606 {
607         stackval *sp = frame->stack_args + 1;
608
609         MonoObject *o = frame->stack_args->data.p;
610         MonoArray *ao = (MonoArray *) o;
611         MonoClass *ac = o->vtable->klass;
612
613         g_assert (ac->rank >= 1);
614
615         gint32 pos = ves_array_calculate_index (ao, sp, frame, TRUE);
616         if (frame->ex)
617                 return;
618
619         if (sp [ac->rank].data.p && !mono_object_class (o)->element_class->valuetype) {
620                 MonoError error;
621                 MonoObject *isinst = mono_object_isinst_checked (sp [ac->rank].data.p, mono_object_class (o)->element_class, &error);
622                 mono_error_cleanup (&error);
623                 if (!isinst) {
624                         frame->ex = mono_get_exception_array_type_mismatch ();
625                         FILL_IN_TRACE (frame->ex, frame);
626                         return;
627                 }
628         }
629
630         gint32 esize = mono_array_element_size (ac);
631         gpointer ea = mono_array_addr_with_size (ao, esize, pos);
632
633         MonoType *mt = mono_method_signature (frame->runtime_method->method)->params [ac->rank];
634         stackval_to_data (mt, &sp [ac->rank], ea, FALSE);
635 }
636
637 static void
638 ves_array_get (MonoInvocation *frame, gboolean safe)
639 {
640         stackval *sp = frame->stack_args + 1;
641
642         MonoObject *o = frame->stack_args->data.p;
643         MonoArray *ao = (MonoArray *) o;
644         MonoClass *ac = o->vtable->klass;
645
646         g_assert (ac->rank >= 1);
647
648         gint32 pos = ves_array_calculate_index (ao, sp, frame, safe);
649         if (frame->ex)
650                 return;
651
652         gint32 esize = mono_array_element_size (ac);
653         gpointer ea = mono_array_addr_with_size (ao, esize, pos);
654
655         MonoType *mt = mono_method_signature (frame->runtime_method->method)->ret;
656         stackval_from_data (mt, frame->retval, ea, FALSE);
657 }
658
659 static gpointer
660 ves_array_element_address (MonoInvocation *frame, MonoClass *required_type, MonoArray *ao, stackval *sp, gboolean needs_typecheck)
661 {
662         MonoClass *ac = ((MonoObject *) ao)->vtable->klass;
663
664         g_assert (ac->rank >= 1);
665
666         gint32 pos = ves_array_calculate_index (ao, sp, frame, TRUE);
667         if (frame->ex)
668                 return NULL;
669
670         if (needs_typecheck && !mono_class_is_assignable_from (mono_object_class ((MonoObject *) ao)->element_class, required_type->element_class)) {
671                 frame->ex = mono_get_exception_array_type_mismatch ();
672                 FILL_IN_TRACE (frame->ex, frame);
673                 return NULL;
674         }
675         gint32 esize = mono_array_element_size (ac);
676         return mono_array_addr_with_size (ao, esize, pos);
677 }
678
679 void
680 interp_walk_stack_with_ctx (MonoInternalStackWalk func, MonoContext *ctx, MonoUnwindOptions options, void *user_data)
681 {
682         MonoError error;
683         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
684
685         if (!context)
686                 return;
687
688         MonoInvocation *frame = context->current_frame;
689
690         while (frame) {
691                 MonoStackFrameInfo fi;
692                 memset (&fi, 0, sizeof (MonoStackFrameInfo));
693
694                 /* TODO: hack to make some asserts happy. */
695                 fi.ji = (MonoJitInfo *) frame->runtime_method;
696
697                 if (frame->runtime_method)
698                         fi.method = fi.actual_method = frame->runtime_method->method;
699
700                 if (!fi.method || (fi.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (fi.method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
701                         fi.il_offset = -1;
702                         fi.type = FRAME_TYPE_MANAGED_TO_NATIVE;
703                 } else {
704                         MonoMethodHeader *hd = mono_method_get_header_checked (fi.method, &error);
705                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
706                         fi.type = FRAME_TYPE_MANAGED;
707                         fi.il_offset = frame->ip - (const unsigned short *) hd->code;
708                         if (!fi.method->wrapper_type)
709                                 fi.managed = TRUE;
710                 }
711
712                 if (func (&fi, ctx, user_data))
713                         return;
714                 frame = frame->parent;
715         }
716 }
717
718 static MonoPIFunc mono_interp_enter_icall_trampoline = NULL;
719
720 static InterpMethodArguments* build_args_from_sig (MonoMethodSignature *sig, MonoInvocation *frame)
721 {
722         InterpMethodArguments *margs = g_malloc0 (sizeof (InterpMethodArguments));
723
724 #ifdef TARGET_ARM
725         g_assert (mono_arm_eabi_supported ());
726         int i8_align = mono_arm_i8_align ();
727 #endif
728
729         if (sig->hasthis)
730                 margs->ilen++;
731
732         for (int i = 0; i < sig->param_count; i++) {
733                 guint32 ptype = sig->params [i]->byref ? MONO_TYPE_PTR : sig->params [i]->type;
734                 switch (ptype) {
735                 case MONO_TYPE_BOOLEAN:
736                 case MONO_TYPE_CHAR:
737                 case MONO_TYPE_I1:
738                 case MONO_TYPE_U1:
739                 case MONO_TYPE_I2:
740                 case MONO_TYPE_U2:
741                 case MONO_TYPE_I4:
742                 case MONO_TYPE_U4:
743                 case MONO_TYPE_I:
744                 case MONO_TYPE_U:
745                 case MONO_TYPE_PTR:
746                 case MONO_TYPE_SZARRAY:
747                 case MONO_TYPE_CLASS:
748                 case MONO_TYPE_OBJECT:
749                 case MONO_TYPE_STRING:
750                 case MONO_TYPE_VALUETYPE:
751                 case MONO_TYPE_GENERICINST:
752 #if SIZEOF_VOID_P == 8
753                 case MONO_TYPE_I8:
754 #endif
755                         margs->ilen++;
756                         break;
757 #if SIZEOF_VOID_P == 4
758                 case MONO_TYPE_I8:
759 #ifdef TARGET_ARM
760                         /* pairs begin at even registers */
761                         if (i8_align == 8 && margs->ilen & 1)
762                                 margs->ilen++;
763 #endif
764                         margs->ilen += 2;
765                         break;
766 #endif
767                 case MONO_TYPE_R4:
768 #if SIZEOF_VOID_P == 8
769                 case MONO_TYPE_R8:
770 #endif
771                         margs->flen++;
772                         break;
773 #if SIZEOF_VOID_P == 4
774                 case MONO_TYPE_R8:
775                         margs->flen += 2;
776                         break;
777 #endif
778                 default:
779                         g_error ("build_args_from_sig: not implemented yet (1): 0x%x\n", ptype);
780                 }
781         }
782
783         if (margs->ilen > 0)
784                 margs->iargs = g_malloc0 (sizeof (gpointer) * margs->ilen);
785
786         if (margs->flen > 0)
787                 margs->fargs = g_malloc0 (sizeof (double) * margs->flen);
788
789         if (margs->ilen > INTERP_ICALL_TRAMP_IARGS)
790                 g_error ("build_args_from_sig: TODO, allocate gregs: %d\n", margs->ilen);
791
792         if (margs->flen > INTERP_ICALL_TRAMP_FARGS)
793                 g_error ("build_args_from_sig: TODO, allocate fregs: %d\n", margs->flen);
794
795
796         size_t int_i = 0;
797         size_t int_f = 0;
798
799         if (sig->hasthis) {
800                 margs->iargs [0] = frame->stack_args->data.p;
801                 int_i++;
802         }
803
804         for (int i = 0; i < sig->param_count; i++) {
805                 guint32 ptype = sig->params [i]->byref ? MONO_TYPE_PTR : sig->params [i]->type;
806                 switch (ptype) {
807                 case MONO_TYPE_BOOLEAN:
808                 case MONO_TYPE_CHAR:
809                 case MONO_TYPE_I1:
810                 case MONO_TYPE_U1:
811                 case MONO_TYPE_I2:
812                 case MONO_TYPE_U2:
813                 case MONO_TYPE_I4:
814                 case MONO_TYPE_U4:
815                 case MONO_TYPE_I:
816                 case MONO_TYPE_U:
817                 case MONO_TYPE_PTR:
818                 case MONO_TYPE_SZARRAY:
819                 case MONO_TYPE_CLASS:
820                 case MONO_TYPE_OBJECT:
821                 case MONO_TYPE_STRING:
822                 case MONO_TYPE_VALUETYPE:
823                 case MONO_TYPE_GENERICINST:
824 #if SIZEOF_VOID_P == 8
825                 case MONO_TYPE_I8:
826 #endif
827                         margs->iargs [int_i] = frame->stack_args [i].data.p;
828 #if DEBUG_INTERP
829                         g_print ("build_args_from_sig: margs->iargs [%d]: %p (frame @ %d)\n", int_i, margs->iargs [int_i], i);
830 #endif
831                         int_i++;
832                         break;
833 #if SIZEOF_VOID_P == 4
834                 case MONO_TYPE_I8: {
835                         stackval *sarg = &frame->stack_args [i];
836 #ifdef TARGET_ARM
837                         /* pairs begin at even registers */
838                         if (i8_align == 8 && int_i & 1)
839                                 int_i++;
840 #endif
841                         margs->iargs [int_i] = (gpointer) sarg->data.pair.lo;
842                         int_i++;
843                         margs->iargs [int_i] = (gpointer) sarg->data.pair.hi;
844 #if DEBUG_INTERP
845                         g_print ("build_args_from_sig: margs->iargs [%d/%d]: 0x%016llx, hi=0x%08x lo=0x%08x (frame @ %d)\n", int_i - 1, int_i, *((guint64 *) &margs->iargs [int_i - 1]), sarg->data.pair.hi, sarg->data.pair.lo, i);
846 #endif
847                         int_i++;
848                         break;
849                 }
850 #endif
851                 case MONO_TYPE_R4:
852                 case MONO_TYPE_R8:
853                         if (ptype == MONO_TYPE_R4)
854                                 * (float *) &(margs->fargs [int_f]) = (float) frame->stack_args [i].data.f;
855                         else
856                                 margs->fargs [int_f] = frame->stack_args [i].data.f;
857 #if DEBUG_INTERP
858                         g_print ("build_args_from_sig: margs->fargs [%d]: %p (%f) (frame @ %d)\n", int_f, margs->fargs [int_f], margs->fargs [int_f], i);
859 #endif
860 #if SIZEOF_VOID_P == 4
861                         int_f += 2;
862 #else
863                         int_f++;
864 #endif
865                         break;
866                 default:
867                         g_error ("build_args_from_sig: not implemented yet (2): 0x%x\n", ptype);
868                 }
869         }
870
871         switch (sig->ret->type) {
872                 case MONO_TYPE_BOOLEAN:
873                 case MONO_TYPE_CHAR:
874                 case MONO_TYPE_I1:
875                 case MONO_TYPE_U1:
876                 case MONO_TYPE_I2:
877                 case MONO_TYPE_U2:
878                 case MONO_TYPE_I4:
879                 case MONO_TYPE_U4:
880                 case MONO_TYPE_I:
881                 case MONO_TYPE_U:
882                 case MONO_TYPE_PTR:
883                 case MONO_TYPE_SZARRAY:
884                 case MONO_TYPE_CLASS:
885                 case MONO_TYPE_OBJECT:
886                 case MONO_TYPE_STRING:
887                 case MONO_TYPE_I8:
888                 case MONO_TYPE_VALUETYPE:
889                 case MONO_TYPE_GENERICINST:
890                         margs->retval = &(frame->retval->data.p);
891                         margs->is_float_ret = 0;
892                         break;
893                 case MONO_TYPE_R4:
894                 case MONO_TYPE_R8:
895                         margs->retval = &(frame->retval->data.p);
896                         margs->is_float_ret = 1;
897                         break;
898                 case MONO_TYPE_VOID:
899                         margs->retval = NULL;
900                         break;
901                 default:
902                         g_error ("build_args_from_sig: ret type not implemented yet: 0x%x\n", sig->ret->type);
903         }
904
905         return margs;
906 }
907
908 static void 
909 ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFuncV addr, gboolean string_ctor, ThreadContext *context)
910 {
911         jmp_buf env;
912         MonoInvocation *old_frame = context->current_frame;
913         MonoInvocation *old_env_frame = context->env_frame;
914         jmp_buf *old_env = context->current_env;
915         MonoLMFExt ext;
916
917         if (setjmp (env)) {
918                 context->current_frame = old_frame;
919                 context->env_frame = old_env_frame;
920                 context->current_env = old_env;
921                 context->managed_code = 1;
922                 return;
923         }
924
925         frame->ex = NULL;
926         context->env_frame = frame;
927         context->current_env = &env;
928
929         g_assert (!frame->runtime_method);
930         if (!mono_interp_enter_icall_trampoline) {
931                 MonoTrampInfo *info;
932                 mono_interp_enter_icall_trampoline = mono_arch_get_enter_icall_trampoline (&info);
933                 // TODO:
934                 // mono_tramp_info_register (info, NULL);
935         }
936
937         InterpMethodArguments *margs = build_args_from_sig (sig, frame);
938 #if DEBUG_INTERP
939         g_print ("ICALL: mono_interp_enter_icall_trampoline = %p, addr = %p\n", mono_interp_enter_icall_trampoline, addr);
940         g_print ("margs(out): ilen=%d, flen=%d\n", margs->ilen, margs->flen);
941 #endif
942
943         context->current_frame = frame;
944         context->managed_code = 0;
945
946         /*
947          * Push an LMF frame on the LMF stack
948          * to mark the transition to native code.
949          */
950         memset (&ext, 0, sizeof (ext));
951         ext.interp_exit = TRUE;
952         ext.interp_exit_data = frame;
953
954         mono_push_lmf (&ext);
955
956         mono_interp_enter_icall_trampoline (addr, margs);
957
958         mono_pop_lmf (&ext.lmf);
959
960         context->managed_code = 1;
961         /* domain can only be changed by native code */
962         context->domain = mono_domain_get ();
963
964         if (*mono_thread_interruption_request_flag ()) {
965                 MonoException *exc = mono_thread_interruption_checkpoint ();
966                 if (exc) {
967                         frame->ex = exc;
968                         context->search_for_handler = 1;
969                 }
970         }
971         
972         if (!frame->ex && !MONO_TYPE_ISSTRUCT (sig->ret))
973                 stackval_from_data (sig->ret, frame->retval, (char*)&frame->retval->data.p, sig->pinvoke);
974
975         context->current_frame = old_frame;
976         context->env_frame = old_env_frame;
977         context->current_env = old_env;
978
979         g_free (margs->iargs);
980         g_free (margs->fargs);
981         g_free (margs);
982 }
983
984 void
985 mono_interp_init_delegate (MonoDelegate *del)
986 {
987         if (del->method)
988                 return;
989         /* shouldn't need a write barrier because we don't write a MonoObject into the field */
990         del->method = ((RuntimeMethod *) del->method_ptr)->method;
991 }
992
993 /*
994  * From the spec:
995  * runtime specifies that the implementation of the method is automatically
996  * provided by the runtime and is primarily used for the methods of delegates.
997  */
998 static void
999 ves_runtime_method (MonoInvocation *frame, ThreadContext *context)
1000 {
1001         MonoMethod *method = frame->runtime_method->method;
1002         const char *name = method->name;
1003         MonoObject *obj = (MonoObject*) frame->stack_args->data.p;
1004         MonoObject *isinst_obj;
1005         MonoError error;
1006
1007         mono_class_init (method->klass);
1008
1009         if (method->klass == mono_defaults.array_class) {
1010                 if (!strcmp (method->name, "UnsafeMov")) {
1011                         /* TODO: layout checks */
1012                         MonoType *mt = mono_method_signature (method)->ret;
1013                         stackval_from_data (mt, frame->retval, (char *) frame->stack_args, FALSE);
1014                         return;
1015                 }
1016                 if (!strcmp (method->name, "UnsafeLoad")) {
1017                         ves_array_get (frame, FALSE);
1018                         return;
1019                 }
1020         }
1021
1022         isinst_obj = mono_object_isinst_checked (obj, mono_defaults.array_class, &error);
1023         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1024         if (obj && isinst_obj) {
1025                 if (*name == 'S' && (strcmp (name, "Set") == 0)) {
1026                         ves_array_set (frame);
1027                         return;
1028                 }
1029                 if (*name == 'G' && (strcmp (name, "Get") == 0)) {
1030                         ves_array_get (frame, TRUE);
1031                         return;
1032                 }
1033         }
1034         
1035         g_error ("Don't know how to exec runtime method %s.%s::%s", 
1036                         method->klass->name_space, method->klass->name,
1037                         method->name);
1038 }
1039
1040 #if DEBUG_INTERP
1041 static char*
1042 dump_stack (stackval *stack, stackval *sp)
1043 {
1044         stackval *s = stack;
1045         GString *str = g_string_new ("");
1046         
1047         if (sp == stack)
1048                 return g_string_free (str, FALSE);
1049         
1050         while (s < sp) {
1051                 g_string_append_printf (str, "[%p (%lld)] ", s->data.l, s->data.l);
1052                 ++s;
1053         }
1054         return g_string_free (str, FALSE);
1055 }
1056 #endif
1057
1058 static void
1059 dump_stackval (GString *str, stackval *s, MonoType *type)
1060 {
1061         switch (type->type) {
1062         case MONO_TYPE_I1:
1063         case MONO_TYPE_U1:
1064         case MONO_TYPE_I2:
1065         case MONO_TYPE_U2:
1066         case MONO_TYPE_I4:
1067         case MONO_TYPE_U4:
1068         case MONO_TYPE_CHAR:
1069         case MONO_TYPE_BOOLEAN:
1070                 g_string_append_printf (str, "[%d] ", s->data.i);
1071                 break;
1072         case MONO_TYPE_STRING:
1073         case MONO_TYPE_SZARRAY:
1074         case MONO_TYPE_CLASS:
1075         case MONO_TYPE_OBJECT:
1076         case MONO_TYPE_ARRAY:
1077         case MONO_TYPE_PTR:
1078         case MONO_TYPE_I:
1079         case MONO_TYPE_U:
1080                 g_string_append_printf (str, "[%p] ", s->data.p);
1081                 break;
1082         case MONO_TYPE_VALUETYPE:
1083                 if (type->data.klass->enumtype)
1084                         g_string_append_printf (str, "[%d] ", s->data.i);
1085                 else
1086                         g_string_append_printf (str, "[vt:%p] ", s->data.p);
1087                 break;
1088         case MONO_TYPE_R4:
1089         case MONO_TYPE_R8:
1090                 g_string_append_printf (str, "[%g] ", s->data.f);
1091                 break;
1092         case MONO_TYPE_I8:
1093         case MONO_TYPE_U8:
1094         default: {
1095                 GString *res = g_string_new ("");
1096                 mono_type_get_desc (res, type, TRUE);
1097                 g_string_append_printf (str, "[{%s} %lld/0x%0llx] ", res->str, s->data.l, s->data.l);
1098                 g_string_free (res, TRUE);
1099                 break;
1100         }
1101         }
1102 }
1103
1104 #if DEBUG_INTERP
1105 static char*
1106 dump_retval (MonoInvocation *inv)
1107 {
1108         GString *str = g_string_new ("");
1109         MonoType *ret = mono_method_signature (inv->runtime_method->method)->ret;
1110
1111         if (ret->type != MONO_TYPE_VOID)
1112                 dump_stackval (str, inv->retval, ret);
1113
1114         return g_string_free (str, FALSE);
1115 }
1116 #endif
1117
1118 static char*
1119 dump_args (MonoInvocation *inv)
1120 {
1121         GString *str = g_string_new ("");
1122         int i;
1123         MonoMethodSignature *signature = mono_method_signature (inv->runtime_method->method);
1124         
1125         if (signature->param_count == 0 && !signature->hasthis)
1126                 return g_string_free (str, FALSE);
1127
1128         if (signature->hasthis) {
1129                 MonoMethod *method = inv->runtime_method->method;
1130                 dump_stackval (str, inv->stack_args, &method->klass->byval_arg);
1131         }
1132
1133         for (i = 0; i < signature->param_count; ++i)
1134                 dump_stackval (str, inv->stack_args + (!!signature->hasthis) + i, signature->params [i]);
1135
1136         return g_string_free (str, FALSE);
1137 }
1138  
1139 static char*
1140 dump_frame (MonoInvocation *inv)
1141 {
1142         GString *str = g_string_new ("");
1143         int i;
1144         char *args;
1145         MonoError error;
1146
1147         for (i = 0; inv; inv = inv->parent) {
1148                 if (inv->runtime_method != NULL) {
1149                         MonoMethod *method = inv->runtime_method->method;
1150                         MonoClass *k;
1151
1152                         int codep = 0;
1153                         const char * opname = "";
1154                         char *name;
1155                         gchar *source = NULL;
1156
1157                         k = method->klass;
1158
1159                         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 &&
1160                                 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) == 0) {
1161                                 MonoMethodHeader *hd = mono_method_get_header_checked (method, &error);
1162                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1163
1164                                 if (hd != NULL) {
1165                                         if (inv->ip) {
1166                                                 opname = mono_interp_opname [*inv->ip];
1167                                                 codep = inv->ip - inv->runtime_method->code;
1168                                                 source = g_strdup_printf ("%s:%d // (TODO: proper stacktrace)", method->name, codep);
1169                                         } else 
1170                                                 opname = "";
1171
1172 #if 0
1173                                         MonoDebugSourceLocation *minfo = mono_debug_lookup_method (method);
1174                                         source = mono_debug_method_lookup_location (minfo, codep);
1175 #endif
1176                                 }
1177                         }
1178                         args = dump_args (inv);
1179                         name = mono_method_full_name (method, TRUE);
1180                         if (source)
1181                                 g_string_append_printf (str, "#%d: 0x%05x %-10s in %s (%s) at %s\n", i, codep, opname, name, args, source);
1182                         else
1183                                 g_string_append_printf (str, "#%d: 0x%05x %-10s in %s (%s)\n", i, codep, opname, name, args);
1184                         g_free (name);
1185                         g_free (args);
1186                         g_free (source);
1187                         ++i;
1188                 }
1189         }
1190         return g_string_free (str, FALSE);
1191 }
1192
1193 static MonoArray *
1194 get_trace_ips (MonoDomain *domain, MonoInvocation *top)
1195 {
1196         int i;
1197         MonoArray *res;
1198         MonoInvocation *inv;
1199         MonoError error;
1200
1201         for (i = 0, inv = top; inv; inv = inv->parent)
1202                 if (inv->runtime_method != NULL)
1203                         ++i;
1204
1205         res = mono_array_new_checked (domain, mono_defaults.int_class, 2 * i, &error);
1206         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1207
1208         for (i = 0, inv = top; inv; inv = inv->parent)
1209                 if (inv->runtime_method != NULL) {
1210                         mono_array_set (res, gpointer, i, inv->runtime_method);
1211                         ++i;
1212                         mono_array_set (res, gpointer, i, (gpointer)inv->ip);
1213                         ++i;
1214                 }
1215
1216         return res;
1217 }
1218
1219
1220 #define MYGUINT64_MAX 18446744073709551615ULL
1221 #define MYGINT64_MAX 9223372036854775807LL
1222 #define MYGINT64_MIN (-MYGINT64_MAX -1LL)
1223
1224 #define MYGUINT32_MAX 4294967295U
1225 #define MYGINT32_MAX 2147483647
1226 #define MYGINT32_MIN (-MYGINT32_MAX -1)
1227         
1228 #define CHECK_ADD_OVERFLOW(a,b) \
1229         (gint32)(b) >= 0 ? (gint32)(MYGINT32_MAX) - (gint32)(b) < (gint32)(a) ? -1 : 0  \
1230         : (gint32)(MYGINT32_MIN) - (gint32)(b) > (gint32)(a) ? +1 : 0
1231
1232 #define CHECK_SUB_OVERFLOW(a,b) \
1233         (gint32)(b) < 0 ? (gint32)(MYGINT32_MAX) + (gint32)(b) < (gint32)(a) ? -1 : 0   \
1234         : (gint32)(MYGINT32_MIN) + (gint32)(b) > (gint32)(a) ? +1 : 0
1235
1236 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1237         (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1238
1239 #define CHECK_SUB_OVERFLOW_UN(a,b) \
1240         (guint32)(a) < (guint32)(b) ? -1 : 0
1241
1242 #define CHECK_ADD_OVERFLOW64(a,b) \
1243         (gint64)(b) >= 0 ? (gint64)(MYGINT64_MAX) - (gint64)(b) < (gint64)(a) ? -1 : 0  \
1244         : (gint64)(MYGINT64_MIN) - (gint64)(b) > (gint64)(a) ? +1 : 0
1245
1246 #define CHECK_SUB_OVERFLOW64(a,b) \
1247         (gint64)(b) < 0 ? (gint64)(MYGINT64_MAX) + (gint64)(b) < (gint64)(a) ? -1 : 0   \
1248         : (gint64)(MYGINT64_MIN) + (gint64)(b) > (gint64)(a) ? +1 : 0
1249
1250 #define CHECK_ADD_OVERFLOW64_UN(a,b) \
1251         (guint64)(MYGUINT64_MAX) - (guint64)(b) < (guint64)(a) ? -1 : 0
1252
1253 #define CHECK_SUB_OVERFLOW64_UN(a,b) \
1254         (guint64)(a) < (guint64)(b) ? -1 : 0
1255
1256 #if SIZEOF_VOID_P == 4
1257 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW(a,b)
1258 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW_UN(a,b)
1259 #else
1260 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW64(a,b)
1261 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW64_UN(a,b)
1262 #endif
1263
1264 /* Resolves to TRUE if the operands would overflow */
1265 #define CHECK_MUL_OVERFLOW(a,b) \
1266         ((gint32)(a) == 0) || ((gint32)(b) == 0) ? 0 : \
1267         (((gint32)(a) > 0) && ((gint32)(b) == -1)) ? FALSE : \
1268         (((gint32)(a) < 0) && ((gint32)(b) == -1)) ? (a == - MYGINT32_MAX) : \
1269         (((gint32)(a) > 0) && ((gint32)(b) > 0)) ? (gint32)(a) > ((MYGINT32_MAX) / (gint32)(b)) : \
1270         (((gint32)(a) > 0) && ((gint32)(b) < 0)) ? (gint32)(a) > ((MYGINT32_MIN) / (gint32)(b)) : \
1271         (((gint32)(a) < 0) && ((gint32)(b) > 0)) ? (gint32)(a) < ((MYGINT32_MIN) / (gint32)(b)) : \
1272         (gint32)(a) < ((MYGINT32_MAX) / (gint32)(b))
1273
1274 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1275         ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1276         (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1277
1278 #define CHECK_MUL_OVERFLOW64(a,b) \
1279         ((gint64)(a) == 0) || ((gint64)(b) == 0) ? 0 : \
1280         (((gint64)(a) > 0) && ((gint64)(b) == -1)) ? FALSE : \
1281         (((gint64)(a) < 0) && ((gint64)(b) == -1)) ? (a == - MYGINT64_MAX) : \
1282         (((gint64)(a) > 0) && ((gint64)(b) > 0)) ? (gint64)(a) > ((MYGINT64_MAX) / (gint64)(b)) : \
1283         (((gint64)(a) > 0) && ((gint64)(b) < 0)) ? (gint64)(a) > ((MYGINT64_MIN) / (gint64)(b)) : \
1284         (((gint64)(a) < 0) && ((gint64)(b) > 0)) ? (gint64)(a) < ((MYGINT64_MIN) / (gint64)(b)) : \
1285         (gint64)(a) < ((MYGINT64_MAX) / (gint64)(b))
1286
1287 #define CHECK_MUL_OVERFLOW64_UN(a,b) \
1288         ((guint64)(a) == 0) || ((guint64)(b) == 0) ? 0 : \
1289         (guint64)(b) > ((MYGUINT64_MAX) / (guint64)(a))
1290
1291 #if SIZEOF_VOID_P == 4
1292 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW(a,b)
1293 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW_UN(a,b)
1294 #else
1295 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW64(a,b)
1296 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW64_UN(a,b)
1297 #endif
1298
1299 MonoObject*
1300 mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
1301 {
1302         MonoInvocation frame;
1303         ThreadContext * volatile context = mono_native_tls_get_value (thread_context_id);
1304         MonoObject *retval = NULL;
1305         MonoMethodSignature *sig = mono_method_signature (method);
1306         MonoClass *klass = mono_class_from_mono_type (sig->ret);
1307         int i, type, isobject = 0;
1308         void *ret = NULL;
1309         stackval result;
1310         stackval *args = alloca (sizeof (stackval) * (sig->param_count + !!sig->hasthis));
1311         ThreadContext context_struct;
1312         MonoInvocation *old_frame = NULL;
1313         jmp_buf env;
1314
1315         error_init (error);
1316         if (exc)
1317                 *exc = NULL;
1318
1319         frame.ex = NULL;
1320
1321         if (setjmp(env)) {
1322                 if (context != &context_struct) {
1323                         context->domain = mono_domain_get ();
1324                         context->current_frame = old_frame;
1325                         context->managed_code = 0;
1326                 } else 
1327                         mono_native_tls_set_value (thread_context_id, NULL);
1328                 if (exc != NULL)
1329                         *exc = (MonoObject *)frame.ex;
1330                 return retval;
1331         }
1332
1333         if (context == NULL) {
1334                 context = &context_struct;
1335                 memset (context, 0, sizeof (ThreadContext));
1336                 context_struct.base_frame = &frame;
1337                 context_struct.env_frame = &frame;
1338                 context_struct.current_env = &env;
1339                 mono_native_tls_set_value (thread_context_id, context);
1340         }
1341         else
1342                 old_frame = context->current_frame;
1343
1344         context->domain = mono_domain_get ();
1345
1346         switch (sig->ret->type) {
1347         case MONO_TYPE_VOID:
1348                 break;
1349         case MONO_TYPE_STRING:
1350         case MONO_TYPE_OBJECT:
1351         case MONO_TYPE_CLASS:
1352         case MONO_TYPE_ARRAY:
1353         case MONO_TYPE_SZARRAY:
1354                 isobject = 1;
1355                 break;
1356         case MONO_TYPE_VALUETYPE:
1357                 retval = mono_object_new_checked (context->domain, klass, error);
1358                 ret = mono_object_unbox (retval);
1359                 if (!sig->ret->data.klass->enumtype)
1360                         result.data.vt = ret;
1361                 else
1362                         result.data.vt = alloca (mono_class_instance_size (klass));
1363                 break;
1364         case MONO_TYPE_GENERICINST:
1365                 if (!MONO_TYPE_IS_REFERENCE (sig->ret)) {
1366                         retval = mono_object_new_checked (context->domain, klass, error);
1367                         ret = mono_object_unbox (retval);
1368                         if (!sig->ret->data.klass->enumtype)
1369                                 result.data.vt = ret;
1370                         else
1371                                 result.data.vt = alloca (mono_class_instance_size (klass));
1372                 } else {
1373                         isobject = 1;
1374                 }
1375                 break;
1376
1377         case MONO_TYPE_PTR:
1378                 retval = mono_object_new_checked (context->domain, mono_defaults.int_class, error);
1379                 ret = mono_object_unbox (retval);
1380                 break;
1381         default:
1382                 retval = mono_object_new_checked (context->domain, klass, error);
1383                 ret = mono_object_unbox (retval);
1384                 break;
1385         }
1386
1387         if (sig->hasthis)
1388                 args [0].data.p = obj;
1389
1390         for (i = 0; i < sig->param_count; ++i) {
1391                 int a_index = i + !!sig->hasthis;
1392                 if (sig->params [i]->byref) {
1393                         args [a_index].data.p = params [i];
1394                         continue;
1395                 }
1396                 type = sig->params [i]->type;
1397 handle_enum:
1398                 switch (type) {
1399                 case MONO_TYPE_U1:
1400                 case MONO_TYPE_I1:
1401                 case MONO_TYPE_BOOLEAN:
1402                         args [a_index].data.i = *(MonoBoolean*)params [i];
1403                         break;
1404                 case MONO_TYPE_U2:
1405                 case MONO_TYPE_I2:
1406                 case MONO_TYPE_CHAR:
1407                         args [a_index].data.i = *(gint16*)params [i];
1408                         break;
1409 #if SIZEOF_VOID_P == 4
1410                 case MONO_TYPE_U: /* use VAL_POINTER? */
1411                 case MONO_TYPE_I:
1412 #endif
1413                 case MONO_TYPE_U4:
1414                 case MONO_TYPE_I4:
1415                         args [a_index].data.i = *(gint32*)params [i];
1416                         break;
1417 #if SIZEOF_VOID_P == 8
1418                 case MONO_TYPE_U:
1419                 case MONO_TYPE_I:
1420 #endif
1421                 case MONO_TYPE_U8:
1422                 case MONO_TYPE_I8:
1423                         args [a_index].data.l = *(gint64*)params [i];
1424                         break;
1425                 case MONO_TYPE_R4:
1426                         args [a_index].data.f = *(gfloat *) params [i];
1427                         break;
1428                 case MONO_TYPE_R8:
1429                         args [a_index].data.f = *(gdouble *) params [i];
1430                         break;
1431                 case MONO_TYPE_VALUETYPE:
1432                         if (sig->params [i]->data.klass->enumtype) {
1433                                 type = mono_class_enum_basetype (sig->params [i]->data.klass)->type;
1434                                 goto handle_enum;
1435                         } else {
1436                                 args [a_index].data.p = params [i];
1437                         }
1438                         break;
1439                 case MONO_TYPE_STRING:
1440                 case MONO_TYPE_PTR:
1441                 case MONO_TYPE_CLASS:
1442                 case MONO_TYPE_ARRAY:
1443                 case MONO_TYPE_SZARRAY:
1444                 case MONO_TYPE_OBJECT:
1445                 case MONO_TYPE_GENERICINST:
1446                         args [a_index].data.p = params [i];
1447                         break;
1448                 default:
1449                         g_error ("type 0x%x not handled in  runtime invoke", sig->params [i]->type);
1450                 }
1451         }
1452
1453         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
1454                 method = mono_marshal_get_native_wrapper (method, FALSE, FALSE);
1455         INIT_FRAME (&frame,context->current_frame,args,&result,mono_get_root_domain (),method,error);
1456         if (exc)
1457                 frame.invoke_trap = 1;
1458         context->managed_code = 1;
1459         ves_exec_method_with_context (&frame, context, NULL, NULL, -1);
1460         context->managed_code = 0;
1461         if (context == &context_struct)
1462                 mono_native_tls_set_value (thread_context_id, NULL);
1463         else
1464                 context->current_frame = old_frame;
1465         if (frame.ex != NULL) {
1466                 if (exc != NULL) {
1467                         *exc = (MonoObject*) frame.ex;
1468                         return NULL;
1469                 }
1470                 if (context->current_env != NULL) {
1471                         context->env_frame->ex = frame.ex;
1472                         longjmp(*context->current_env, 1);
1473                 }
1474                 else
1475                         printf("dropped exception...\n");
1476         }
1477         if (sig->ret->type == MONO_TYPE_VOID && !method->string_ctor)
1478                 return NULL;
1479         if (isobject || method->string_ctor)
1480                 return result.data.p;
1481         stackval_to_data (sig->ret, &result, ret, sig->pinvoke);
1482         return retval;
1483 }
1484
1485 typedef struct {
1486         RuntimeMethod *rmethod;
1487         gpointer this_arg;
1488         gpointer res;
1489         gpointer args [16];
1490         gpointer *many_args;
1491 } InterpEntryData;
1492
1493 /* Main function for entering the interpreter from compiled code */
1494 static void
1495 interp_entry (InterpEntryData *data)
1496 {
1497         MonoInvocation frame;
1498         RuntimeMethod *rmethod = data->rmethod;
1499         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
1500         ThreadContext context_struct;
1501         MonoInvocation *old_frame;
1502         stackval result;
1503         stackval *args;
1504         MonoMethod *method;
1505         MonoMethodSignature *sig;
1506         MonoType *type;
1507         int i;
1508
1509         method = rmethod->method;
1510         sig = mono_method_signature (method);
1511
1512         // FIXME: Optimize this
1513
1514         //printf ("%s\n", mono_method_full_name (method, 1));
1515
1516         frame.ex = NULL;
1517         if (context == NULL) {
1518                 context = &context_struct;
1519                 memset (context, 0, sizeof (ThreadContext));
1520                 context_struct.base_frame = &frame;
1521                 context_struct.env_frame = &frame;
1522                 mono_native_tls_set_value (thread_context_id, context);
1523         }
1524         else
1525                 old_frame = context->current_frame;
1526         context->domain = mono_domain_get ();
1527
1528         args = alloca (sizeof (stackval) * (sig->param_count + (sig->hasthis ? 1 : 0)));
1529         if (sig->hasthis)
1530                 args [0].data.p = data->this_arg;
1531
1532         gpointer *params;
1533         if (data->many_args)
1534                 params = data->many_args;
1535         else
1536                 params = data->args;
1537         for (i = 0; i < sig->param_count; ++i) {
1538                 int a_index = i + (sig->hasthis ? 1 : 0);
1539                 if (sig->params [i]->byref) {
1540                         args [a_index].data.p = params [i];
1541                         continue;
1542                 }
1543                 type = rmethod->param_types [i];
1544                 switch (type->type) {
1545                 case MONO_TYPE_U1:
1546                 case MONO_TYPE_I1:
1547                         args [a_index].data.i = *(MonoBoolean*)params [i];
1548                         break;
1549                 case MONO_TYPE_U2:
1550                 case MONO_TYPE_I2:
1551                         args [a_index].data.i = *(gint16*)params [i];
1552                         break;
1553                 case MONO_TYPE_U:
1554 #if SIZEOF_VOID_P == 4
1555                         args [a_index].data.p = GINT_TO_POINTER (*(guint32*)params [i]);
1556 #else
1557                         args [a_index].data.p = GINT_TO_POINTER (*(guint64*)params [i]);
1558 #endif
1559                         break;
1560                 case MONO_TYPE_I:
1561 #if SIZEOF_VOID_P == 4
1562                         args [a_index].data.p = GINT_TO_POINTER (*(gint32*)params [i]);
1563 #else
1564                         args [a_index].data.p = GINT_TO_POINTER (*(gint64*)params [i]);
1565 #endif
1566                         break;
1567                 case MONO_TYPE_U4:
1568                         args [a_index].data.i = *(guint32*)params [i];
1569                         break;
1570                 case MONO_TYPE_I4:
1571                         args [a_index].data.i = *(gint32*)params [i];
1572                         break;
1573                 case MONO_TYPE_U8:
1574                         args [a_index].data.l = *(guint64*)params [i];
1575                         break;
1576                 case MONO_TYPE_I8:
1577                         args [a_index].data.l = *(gint64*)params [i];
1578                         break;
1579                 case MONO_TYPE_PTR:
1580                 case MONO_TYPE_OBJECT:
1581                         args [a_index].data.p = *(MonoObject**)params [i];
1582                         break;
1583                 case MONO_TYPE_VALUETYPE:
1584                         args [a_index].data.p = params [i];
1585                         break;
1586                 case MONO_TYPE_GENERICINST:
1587                         if (MONO_TYPE_IS_REFERENCE (type))
1588                                 args [a_index].data.p = params [i];
1589                         else
1590                                 args [a_index].data.vt = params [i];
1591                         break;
1592                 default:
1593                         printf ("%s\n", mono_type_full_name (sig->params [i]));
1594                         NOT_IMPLEMENTED;
1595                         break;
1596                 }
1597         }
1598
1599         init_frame (&frame, NULL, data->rmethod, args, &result);
1600         context->managed_code = 1;
1601
1602         type = rmethod->rtype;
1603         switch (type->type) {
1604         case MONO_TYPE_GENERICINST:
1605                 if (!MONO_TYPE_IS_REFERENCE (type))
1606                         frame.retval->data.vt = data->res;
1607                 break;
1608         case MONO_TYPE_VALUETYPE:
1609                 frame.retval->data.vt = data->res;
1610                 break;
1611         default:
1612                 break;
1613         }
1614
1615         ves_exec_method_with_context (&frame, context, NULL, NULL, -1);
1616         context->managed_code = 0;
1617         if (context == &context_struct)
1618                 mono_native_tls_set_value (thread_context_id, NULL);
1619         else
1620                 context->current_frame = old_frame;
1621
1622         // FIXME:
1623         g_assert (frame.ex == NULL);
1624
1625         type = rmethod->rtype;
1626         switch (type->type) {
1627         case MONO_TYPE_VOID:
1628                 break;
1629         case MONO_TYPE_I1:
1630                 *(gint8*)data->res = frame.retval->data.i;
1631                 break;
1632         case MONO_TYPE_U1:
1633                 *(guint8*)data->res = frame.retval->data.i;
1634                 break;
1635         case MONO_TYPE_I2:
1636                 *(gint16*)data->res = frame.retval->data.i;
1637                 break;
1638         case MONO_TYPE_U2:
1639                 *(guint16*)data->res = frame.retval->data.i;
1640                 break;
1641         case MONO_TYPE_I4:
1642                 *(gint32*)data->res = frame.retval->data.i;
1643                 break;
1644         case MONO_TYPE_U4:
1645                 *(guint64*)data->res = frame.retval->data.i;
1646                 break;
1647         case MONO_TYPE_I8:
1648                 *(gint64*)data->res = frame.retval->data.i;
1649                 break;
1650         case MONO_TYPE_U8:
1651                 *(guint64*)data->res = frame.retval->data.i;
1652                 break;
1653         case MONO_TYPE_I:
1654 #if SIZEOF_VOID_P == 8
1655                 *(gint64*)data->res = (gint64)frame.retval->data.p;
1656 #else
1657                 *(gint32*)data->res = (gint32)frame.retval->data.p;
1658 #endif
1659                 break;
1660         case MONO_TYPE_U:
1661 #if SIZEOF_VOID_P == 8
1662                 *(guint64*)data->res = (guint64)frame.retval->data.p;
1663 #else
1664                 *(guint32*)data->res = (guint32)frame.retval->data.p;
1665 #endif
1666                 break;
1667         case MONO_TYPE_OBJECT:
1668                 /* No need for a write barrier */
1669                 *(MonoObject**)data->res = (MonoObject*)frame.retval->data.p;
1670                 break;
1671         case MONO_TYPE_GENERICINST:
1672                 if (MONO_TYPE_IS_REFERENCE (type)) {
1673                         *(MonoObject**)data->res = *(MonoObject**)frame.retval->data.p;
1674                 } else {
1675                         /* Already set before the call */
1676                 }
1677                 break;
1678         case MONO_TYPE_VALUETYPE:
1679                 /* Already set before the call */
1680                 break;
1681         default:
1682                 printf ("%s\n", mono_type_full_name (sig->ret));
1683                 NOT_IMPLEMENTED;
1684                 break;
1685         }
1686 }
1687
1688 static stackval * 
1689 do_icall (ThreadContext *context, int op, stackval *sp, gpointer ptr)
1690 {
1691         MonoInvocation *old_frame = context->current_frame;
1692         MonoInvocation *old_env_frame = context->env_frame;
1693         jmp_buf *old_env = context->current_env;
1694         jmp_buf env;
1695
1696         if (setjmp (env)) {
1697                 context->current_frame = old_frame;
1698                 context->env_frame = old_env_frame;
1699                 context->current_env = old_env;
1700                 context->managed_code = 1;
1701                 return sp;
1702         }
1703
1704         context->env_frame = context->current_frame;
1705         context->current_env = &env;
1706         context->managed_code = 0;
1707
1708         switch (op) {
1709         case MINT_ICALL_V_V: {
1710                 void (*func)(void) = ptr;
1711                 func ();
1712                 break;
1713         }
1714         case MINT_ICALL_V_P: {
1715                 gpointer (*func)(void) = ptr;
1716                 sp++;
1717                 sp [-1].data.p = func ();
1718                 break;
1719         }
1720         case MINT_ICALL_P_V: {
1721                 void (*func)(gpointer) = ptr;
1722                 func (sp [-1].data.p);
1723                 sp --;
1724                 break;
1725         }
1726         case MINT_ICALL_P_P: {
1727                 gpointer (*func)(gpointer) = ptr;
1728                 sp [-1].data.p = func (sp [-1].data.p);
1729                 break;
1730         }
1731         case MINT_ICALL_PP_V: {
1732                 void (*func)(gpointer,gpointer) = ptr;
1733                 sp -= 2;
1734                 func (sp [0].data.p, sp [1].data.p);
1735                 break;
1736         }
1737         case MINT_ICALL_PI_V: {
1738                 void (*func)(gpointer,int) = ptr;
1739                 sp -= 2;
1740                 func (sp [0].data.p, sp [1].data.i);
1741                 break;
1742         }
1743         case MINT_ICALL_PP_P: {
1744                 gpointer (*func)(gpointer,gpointer) = ptr;
1745                 --sp;
1746                 sp [-1].data.p = func (sp [-1].data.p, sp [0].data.p);
1747                 break;
1748         }
1749         case MINT_ICALL_PI_P: {
1750                 gpointer (*func)(gpointer,int) = ptr;
1751                 --sp;
1752                 sp [-1].data.p = func (sp [-1].data.p, sp [0].data.i);
1753                 break;
1754         }
1755         case MINT_ICALL_PPP_V: {
1756                 void (*func)(gpointer,gpointer,gpointer) = ptr;
1757                 sp -= 3;
1758                 func (sp [0].data.p, sp [1].data.p, sp [2].data.p);
1759                 break;
1760         }
1761         case MINT_ICALL_PPI_V: {
1762                 void (*func)(gpointer,gpointer,int) = ptr;
1763                 sp -= 3;
1764                 func (sp [0].data.p, sp [1].data.p, sp [2].data.i);
1765                 break;
1766         }
1767         default:
1768                 g_assert_not_reached ();
1769         }
1770
1771         context->env_frame = old_env_frame;
1772         context->current_env = old_env;
1773
1774         return sp;
1775 }
1776
1777 /*
1778  * These functions are the entry points into the interpreter from compiled code.
1779  * They are called by the interp_in wrappers. They have the following signature:
1780  * void (<optional this_arg>, <optional retval pointer>, <arg1>, ..., <argn>, <method ptr>)
1781  * They pack up their arguments into an InterpEntryData structure and call interp_entry ().
1782  * It would be possible for the wrappers to pack up the arguments etc, but that would make them bigger, and there are
1783  * more wrappers then these functions.
1784  * this/static * ret/void * 16 arguments -> 64 functions.
1785  */
1786
1787 #define MAX_INTERP_ENTRY_ARGS 8
1788
1789 #define INTERP_ENTRY_BASE(_method, _this_arg, _res) \
1790         InterpEntryData data; \
1791         (data).rmethod = (_method); \
1792         (data).res = (_res); \
1793         (data).this_arg = (_this_arg); \
1794         (data).many_args = NULL;
1795
1796 #define INTERP_ENTRY0(_this_arg, _res, _method) {       \
1797         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1798         interp_entry (&data); \
1799         }
1800 #define INTERP_ENTRY1(_this_arg, _res, _method) {         \
1801         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1802         (data).args [0] = arg1; \
1803         interp_entry (&data); \
1804         }
1805 #define INTERP_ENTRY2(_this_arg, _res, _method) {  \
1806         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1807         (data).args [0] = arg1; \
1808         (data).args [1] = arg2; \
1809         interp_entry (&data); \
1810         }
1811 #define INTERP_ENTRY3(_this_arg, _res, _method) { \
1812         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1813         (data).args [0] = arg1; \
1814         (data).args [1] = arg2; \
1815         (data).args [2] = arg3; \
1816         interp_entry (&data); \
1817         }
1818 #define INTERP_ENTRY4(_this_arg, _res, _method) {       \
1819         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1820         (data).args [0] = arg1; \
1821         (data).args [1] = arg2; \
1822         (data).args [2] = arg3; \
1823         (data).args [3] = arg4; \
1824         interp_entry (&data); \
1825         }
1826 #define INTERP_ENTRY5(_this_arg, _res, _method) {       \
1827         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1828         (data).args [0] = arg1; \
1829         (data).args [1] = arg2; \
1830         (data).args [2] = arg3; \
1831         (data).args [3] = arg4; \
1832         (data).args [4] = arg5; \
1833         interp_entry (&data); \
1834         }
1835 #define INTERP_ENTRY6(_this_arg, _res, _method) {       \
1836         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1837         (data).args [0] = arg1; \
1838         (data).args [1] = arg2; \
1839         (data).args [2] = arg3; \
1840         (data).args [3] = arg4; \
1841         (data).args [4] = arg5; \
1842         (data).args [5] = arg6; \
1843         interp_entry (&data); \
1844         }
1845 #define INTERP_ENTRY7(_this_arg, _res, _method) {       \
1846         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1847         (data).args [0] = arg1; \
1848         (data).args [1] = arg2; \
1849         (data).args [2] = arg3; \
1850         (data).args [3] = arg4; \
1851         (data).args [4] = arg5; \
1852         (data).args [5] = arg6; \
1853         (data).args [6] = arg7; \
1854         interp_entry (&data); \
1855         }
1856 #define INTERP_ENTRY8(_this_arg, _res, _method) {       \
1857         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1858         (data).args [0] = arg1; \
1859         (data).args [1] = arg2; \
1860         (data).args [2] = arg3; \
1861         (data).args [3] = arg4; \
1862         (data).args [4] = arg5; \
1863         (data).args [5] = arg6; \
1864         (data).args [6] = arg7; \
1865         (data).args [7] = arg8; \
1866         interp_entry (&data); \
1867         }
1868
1869 #define ARGLIST0 RuntimeMethod *rmethod
1870 #define ARGLIST1 gpointer arg1, RuntimeMethod *rmethod
1871 #define ARGLIST2 gpointer arg1, gpointer arg2, RuntimeMethod *rmethod
1872 #define ARGLIST3 gpointer arg1, gpointer arg2, gpointer arg3, RuntimeMethod *rmethod
1873 #define ARGLIST4 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, RuntimeMethod *rmethod
1874 #define ARGLIST5 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, RuntimeMethod *rmethod
1875 #define ARGLIST6 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, gpointer arg6, RuntimeMethod *rmethod
1876 #define ARGLIST7 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, gpointer arg6, gpointer arg7, RuntimeMethod *rmethod
1877 #define ARGLIST8 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, gpointer arg6, gpointer arg7, gpointer arg8, RuntimeMethod *rmethod
1878
1879 static void interp_entry_static_0 (ARGLIST0) INTERP_ENTRY0 (NULL, NULL, rmethod)
1880 static void interp_entry_static_1 (ARGLIST1) INTERP_ENTRY1 (NULL, NULL, rmethod)
1881 static void interp_entry_static_2 (ARGLIST2) INTERP_ENTRY2 (NULL, NULL, rmethod)
1882 static void interp_entry_static_3 (ARGLIST3) INTERP_ENTRY3 (NULL, NULL, rmethod)
1883 static void interp_entry_static_4 (ARGLIST4) INTERP_ENTRY4 (NULL, NULL, rmethod)
1884 static void interp_entry_static_5 (ARGLIST5) INTERP_ENTRY5 (NULL, NULL, rmethod)
1885 static void interp_entry_static_6 (ARGLIST6) INTERP_ENTRY6 (NULL, NULL, rmethod)
1886 static void interp_entry_static_7 (ARGLIST7) INTERP_ENTRY7 (NULL, NULL, rmethod)
1887 static void interp_entry_static_8 (ARGLIST8) INTERP_ENTRY8 (NULL, NULL, rmethod)
1888 static void interp_entry_static_ret_0 (gpointer res, ARGLIST0) INTERP_ENTRY0 (NULL, res, rmethod)
1889 static void interp_entry_static_ret_1 (gpointer res, ARGLIST1) INTERP_ENTRY1 (NULL, res, rmethod)
1890 static void interp_entry_static_ret_2 (gpointer res, ARGLIST2) INTERP_ENTRY2 (NULL, res, rmethod)
1891 static void interp_entry_static_ret_3 (gpointer res, ARGLIST3) INTERP_ENTRY3 (NULL, res, rmethod)
1892 static void interp_entry_static_ret_4 (gpointer res, ARGLIST4) INTERP_ENTRY4 (NULL, res, rmethod)
1893 static void interp_entry_static_ret_5 (gpointer res, ARGLIST5) INTERP_ENTRY5 (NULL, res, rmethod)
1894 static void interp_entry_static_ret_6 (gpointer res, ARGLIST6) INTERP_ENTRY6 (NULL, res, rmethod)
1895 static void interp_entry_static_ret_7 (gpointer res, ARGLIST7) INTERP_ENTRY7 (NULL, res, rmethod)
1896 static void interp_entry_static_ret_8 (gpointer res, ARGLIST8) INTERP_ENTRY8 (NULL, res, rmethod)
1897 static void interp_entry_instance_0 (gpointer this_arg, ARGLIST0) INTERP_ENTRY0 (this_arg, NULL, rmethod)
1898 static void interp_entry_instance_1 (gpointer this_arg, ARGLIST1) INTERP_ENTRY1 (this_arg, NULL, rmethod)
1899 static void interp_entry_instance_2 (gpointer this_arg, ARGLIST2) INTERP_ENTRY2 (this_arg, NULL, rmethod)
1900 static void interp_entry_instance_3 (gpointer this_arg, ARGLIST3) INTERP_ENTRY3 (this_arg, NULL, rmethod)
1901 static void interp_entry_instance_4 (gpointer this_arg, ARGLIST4) INTERP_ENTRY4 (this_arg, NULL, rmethod)
1902 static void interp_entry_instance_5 (gpointer this_arg, ARGLIST5) INTERP_ENTRY5 (this_arg, NULL, rmethod)
1903 static void interp_entry_instance_6 (gpointer this_arg, ARGLIST6) INTERP_ENTRY6 (this_arg, NULL, rmethod)
1904 static void interp_entry_instance_7 (gpointer this_arg, ARGLIST7) INTERP_ENTRY7 (this_arg, NULL, rmethod)
1905 static void interp_entry_instance_8 (gpointer this_arg, ARGLIST8) INTERP_ENTRY8 (this_arg, NULL, rmethod)
1906 static void interp_entry_instance_ret_0 (gpointer this_arg, gpointer res, ARGLIST0) INTERP_ENTRY0 (this_arg, res, rmethod)
1907 static void interp_entry_instance_ret_1 (gpointer this_arg, gpointer res, ARGLIST1) INTERP_ENTRY1 (this_arg, res, rmethod)
1908 static void interp_entry_instance_ret_2 (gpointer this_arg, gpointer res, ARGLIST2) INTERP_ENTRY2 (this_arg, res, rmethod)
1909 static void interp_entry_instance_ret_3 (gpointer this_arg, gpointer res, ARGLIST3) INTERP_ENTRY3 (this_arg, res, rmethod)
1910 static void interp_entry_instance_ret_4 (gpointer this_arg, gpointer res, ARGLIST4) INTERP_ENTRY4 (this_arg, res, rmethod)
1911 static void interp_entry_instance_ret_5 (gpointer this_arg, gpointer res, ARGLIST5) INTERP_ENTRY5 (this_arg, res, rmethod)
1912 static void interp_entry_instance_ret_6 (gpointer this_arg, gpointer res, ARGLIST6) INTERP_ENTRY6 (this_arg, res, rmethod)
1913 static void interp_entry_instance_ret_7 (gpointer this_arg, gpointer res, ARGLIST7) INTERP_ENTRY6 (this_arg, res, rmethod)
1914 static void interp_entry_instance_ret_8 (gpointer this_arg, gpointer res, ARGLIST8) INTERP_ENTRY6 (this_arg, res, rmethod)
1915
1916 #define INTERP_ENTRY_FUNCLIST(type) interp_entry_ ## type ## _0, interp_entry_ ## type ## _1, interp_entry_ ## type ## _2, interp_entry_ ## type ## _3, interp_entry_ ## type ## _4, interp_entry_ ## type ## _5, interp_entry_ ## type ## _6, interp_entry_ ## type ## _7, interp_entry_ ## type ## _8
1917
1918 gpointer entry_funcs_static [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (static) };
1919 gpointer entry_funcs_static_ret [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (static_ret) };
1920 gpointer entry_funcs_instance [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (instance) };
1921 gpointer entry_funcs_instance_ret [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (instance_ret) };
1922
1923 /* General version for methods with more than MAX_INTERP_ENTRY_ARGS arguments */
1924 static void
1925 interp_entry_general (gpointer this_arg, gpointer res, gpointer *args, gpointer rmethod)
1926 {
1927         INTERP_ENTRY_BASE (rmethod, this_arg, res);
1928         data.many_args = args;
1929         interp_entry (&data);
1930 }
1931
1932 /*
1933  * mono_interp_create_method_pointer:
1934  *
1935  * Return a function pointer which can be used to call METHOD using the
1936  * interpreter. Return NULL for methods which are not supported.
1937  */
1938 gpointer
1939 mono_interp_create_method_pointer (MonoMethod *method, MonoError *error)
1940 {
1941         gpointer addr;
1942         MonoMethodSignature *sig = mono_method_signature (method);
1943         MonoMethod *wrapper;
1944         RuntimeMethod *rmethod;
1945
1946         /* HACK: method_ptr of delegate should point to a runtime method*/
1947         if (method->wrapper_type && method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
1948                 return mono_interp_get_runtime_method (mono_domain_get (), method, error);
1949
1950         rmethod = mono_interp_get_runtime_method (mono_domain_get (), method, error);
1951         if (rmethod->jit_entry)
1952                 return rmethod->jit_entry;
1953         wrapper = mini_get_interp_in_wrapper (sig);
1954
1955         gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, error);
1956         mono_error_assert_ok (error);
1957
1958         //printf ("%s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
1959         gpointer entry_func;
1960         if (sig->param_count > MAX_INTERP_ENTRY_ARGS) {
1961                 entry_func = interp_entry_general;
1962         } else if (sig->hasthis) {
1963                 if (sig->ret->type == MONO_TYPE_VOID)
1964                         entry_func = entry_funcs_instance [sig->param_count];
1965                 else
1966                         entry_func = entry_funcs_instance_ret [sig->param_count];
1967         } else {
1968                 if (sig->ret->type == MONO_TYPE_VOID)
1969                         entry_func = entry_funcs_static [sig->param_count];
1970                 else
1971                         entry_func = entry_funcs_static_ret [sig->param_count];
1972         }
1973         g_assert (entry_func);
1974
1975         /* This is the argument passed to the interp_in wrapper by the static rgctx trampoline */
1976         MonoFtnDesc *ftndesc = g_new0 (MonoFtnDesc, 1);
1977         ftndesc->addr = entry_func;
1978         ftndesc->arg = rmethod;
1979         mono_error_assert_ok (error);
1980
1981         /*
1982          * The wrapper is called by compiled code, which doesn't pass the extra argument, so we pass it in the
1983          * rgctx register using a trampoline.
1984          */
1985
1986         // FIXME: AOT
1987         g_assert (!mono_aot_only);
1988         addr = mono_arch_get_static_rgctx_trampoline (ftndesc, jit_wrapper);
1989
1990         mono_memory_barrier ();
1991         rmethod->jit_entry = addr;
1992
1993         return addr;
1994 }
1995
1996 #if COUNT_OPS
1997 static int opcode_counts[512];
1998
1999 #define COUNT_OP(op) opcode_counts[op]++
2000 #else
2001 #define COUNT_OP(op) 
2002 #endif
2003
2004 #if DEBUG_INTERP
2005 #define DUMP_INSTR() \
2006         if (tracing > 1) { \
2007                 char *ins; \
2008                 if (sp > frame->stack) { \
2009                         ins = dump_stack (frame->stack, sp); \
2010                 } else { \
2011                         ins = g_strdup (""); \
2012                 } \
2013                 sp->data.l = 0; \
2014                 output_indent (); \
2015                 char *mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
2016                 g_print ("(%p) %s -> ", mono_thread_internal_current (), mn); \
2017                 g_free (mn); \
2018                 mono_interp_dis_mintop(rtm->code, ip); \
2019                 g_print ("\t%d:%s\n", vt_sp - vtalloc, ins); \
2020                 g_free (ins); \
2021         }
2022 #else
2023 #define DUMP_INSTR()
2024 #endif
2025
2026 #ifdef __GNUC__
2027 #define USE_COMPUTED_GOTO 1
2028 #endif
2029 #if USE_COMPUTED_GOTO
2030 #define MINT_IN_SWITCH(op) COUNT_OP(op); goto *in_labels[op];
2031 #define MINT_IN_CASE(x) LAB_ ## x:
2032 #if DEBUG_INTERP
2033 #define MINT_IN_BREAK if (tracing > 1) goto main_loop; else { COUNT_OP(*ip); goto *in_labels[*ip]; }
2034 #else
2035 #define MINT_IN_BREAK { COUNT_OP(*ip); goto *in_labels[*ip]; }
2036 #endif
2037 #define MINT_IN_DEFAULT mint_default: if (0) goto mint_default; /* make gcc shut up */
2038 #else
2039 #define MINT_IN_SWITCH(op) switch (op)
2040 #define MINT_IN_CASE(x) case x:
2041 #define MINT_IN_BREAK break
2042 #define MINT_IN_DEFAULT default:
2043 #endif
2044
2045 /*
2046  * If EXIT_AT_FINALLY is not -1, exit after exiting the finally clause with that index.
2047  */
2048 static void 
2049 ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, unsigned short *start_with_ip, MonoException *filter_exception, int exit_at_finally)
2050 {
2051         MonoInvocation child_frame;
2052         GSList *finally_ips = NULL;
2053         const unsigned short *endfinally_ip = NULL;
2054         const unsigned short *ip = NULL;
2055         register stackval *sp;
2056         RuntimeMethod *rtm;
2057 #if DEBUG_INTERP
2058         gint tracing = global_tracing;
2059         unsigned char *vtalloc;
2060 #else
2061         gint tracing = 0;
2062 #endif
2063         int i32;
2064         unsigned char *vt_sp;
2065         unsigned char *locals;
2066         MonoError error;
2067         MonoObject *o = NULL;
2068         MonoClass *c;
2069 #if USE_COMPUTED_GOTO
2070         static void *in_labels[] = {
2071 #define OPDEF(a,b,c,d) \
2072         &&LAB_ ## a,
2073 #include "mintops.def"
2074         0 };
2075 #endif
2076
2077         frame->ex = NULL;
2078         frame->ex_handler = NULL;
2079         frame->ip = NULL;
2080         context->current_frame = frame;
2081
2082         debug_enter (frame, &tracing);
2083
2084         if (!frame->runtime_method->transformed) {
2085                 context->managed_code = 0;
2086 #if DEBUG_INTERP
2087                 char *mn = mono_method_full_name (frame->runtime_method->method, TRUE);
2088                 g_print ("(%p) Transforming %s\n", mono_thread_internal_current (), mn);
2089                 g_free (mn);
2090 #endif
2091                 frame->ex = mono_interp_transform_method (frame->runtime_method, context);
2092                 context->managed_code = 1;
2093                 if (frame->ex) {
2094                         rtm = NULL;
2095                         ip = NULL;
2096                         goto exit_frame;
2097                 }
2098         }
2099
2100         rtm = frame->runtime_method;
2101         if (!start_with_ip ) {
2102                 frame->args = alloca (rtm->alloca_size);
2103                 memset (frame->args, 0, rtm->alloca_size);
2104
2105                 ip = rtm->code;
2106         } else {
2107                 ip = start_with_ip;
2108         }
2109         sp = frame->stack = (stackval *) ((char *) frame->args + rtm->args_size);
2110         vt_sp = (unsigned char *) sp + rtm->stack_size;
2111 #if DEBUG_INTERP
2112         vtalloc = vt_sp;
2113 #endif
2114         locals = (unsigned char *) vt_sp + rtm->vt_stack_size;
2115         child_frame.parent = frame;
2116
2117         if (filter_exception) {
2118                 sp->data.p = filter_exception;
2119                 sp++;
2120         }
2121
2122         /*
2123          * using while (ip < end) may result in a 15% performance drop, 
2124          * but it may be useful for debug
2125          */
2126         while (1) {
2127         main_loop:
2128                 /* g_assert (sp >= frame->stack); */
2129                 /* g_assert(vt_sp - vtalloc <= rtm->vt_stack_size); */
2130                 DUMP_INSTR();
2131                 MINT_IN_SWITCH (*ip) {
2132                 MINT_IN_CASE(MINT_INITLOCALS)
2133                         memset (locals, 0, rtm->locals_size);
2134                         ++ip;
2135                         MINT_IN_BREAK;
2136                 MINT_IN_CASE(MINT_NOP)
2137                         ++ip;
2138                         MINT_IN_BREAK;
2139                 MINT_IN_CASE(MINT_BREAK)
2140                         ++ip;
2141                         G_BREAKPOINT (); /* this is not portable... */
2142                         MINT_IN_BREAK;
2143                 MINT_IN_CASE(MINT_LDNULL) 
2144                         sp->data.p = NULL;
2145                         ++ip;
2146                         ++sp;
2147                         MINT_IN_BREAK;
2148                 MINT_IN_CASE(MINT_VTRESULT) {
2149                         int ret_size = * (guint16 *)(ip + 1);
2150                         unsigned char *ret_vt_sp = vt_sp;
2151                         vt_sp -= READ32(ip + 2);
2152                         if (ret_size > 0) {
2153                                 memmove (vt_sp, ret_vt_sp, ret_size);
2154                                 sp [-1].data.p = vt_sp;
2155                                 vt_sp += (ret_size + 7) & ~7;
2156                         }
2157                         ip += 4;
2158                         MINT_IN_BREAK;
2159                 }
2160 #define LDC(n) do { sp->data.i = (n); ++ip; ++sp; } while (0)
2161                 MINT_IN_CASE(MINT_LDC_I4_M1)
2162                         LDC(-1);
2163                         MINT_IN_BREAK;
2164                 MINT_IN_CASE(MINT_LDC_I4_0)
2165                         LDC(0);
2166                         MINT_IN_BREAK;
2167                 MINT_IN_CASE(MINT_LDC_I4_1)
2168                         LDC(1);
2169                         MINT_IN_BREAK;
2170                 MINT_IN_CASE(MINT_LDC_I4_2)
2171                         LDC(2);
2172                         MINT_IN_BREAK;
2173                 MINT_IN_CASE(MINT_LDC_I4_3)
2174                         LDC(3);
2175                         MINT_IN_BREAK;
2176                 MINT_IN_CASE(MINT_LDC_I4_4)
2177                         LDC(4);
2178                         MINT_IN_BREAK;
2179                 MINT_IN_CASE(MINT_LDC_I4_5)
2180                         LDC(5);
2181                         MINT_IN_BREAK;
2182                 MINT_IN_CASE(MINT_LDC_I4_6)
2183                         LDC(6);
2184                         MINT_IN_BREAK;
2185                 MINT_IN_CASE(MINT_LDC_I4_7)
2186                         LDC(7);
2187                         MINT_IN_BREAK;
2188                 MINT_IN_CASE(MINT_LDC_I4_8)
2189                         LDC(8);
2190                         MINT_IN_BREAK;
2191                 MINT_IN_CASE(MINT_LDC_I4_S) 
2192                         sp->data.i = *(const short *)(ip + 1);
2193                         ip += 2;
2194                         ++sp;
2195                         MINT_IN_BREAK;
2196                 MINT_IN_CASE(MINT_LDC_I4)
2197                         ++ip;
2198                         sp->data.i = READ32 (ip);
2199                         ip += 2;
2200                         ++sp;
2201                         MINT_IN_BREAK;
2202                 MINT_IN_CASE(MINT_LDC_I8)
2203                         ++ip;
2204                         sp->data.l = READ64 (ip);
2205                         ip += 4;
2206                         ++sp;
2207                         MINT_IN_BREAK;
2208                 MINT_IN_CASE(MINT_LDC_R4) {
2209                         guint32 val;
2210                         ++ip;
2211                         val = READ32(ip);
2212                         sp->data.f = * (float *)&val;
2213                         ip += 2;
2214                         ++sp;
2215                         MINT_IN_BREAK;
2216                 }
2217                 MINT_IN_CASE(MINT_LDC_R8) 
2218                         sp->data.l = READ64 (ip + 1); /* note union usage */
2219                         ip += 5;
2220                         ++sp;
2221                         MINT_IN_BREAK;
2222                 MINT_IN_CASE(MINT_DUP) 
2223                         sp [0] = sp[-1];
2224                         ++sp;
2225                         ++ip; 
2226                         MINT_IN_BREAK;
2227                 MINT_IN_CASE(MINT_DUP_VT)
2228                         i32 = READ32 (ip + 1);
2229                         sp->data.p = vt_sp;
2230                         memcpy(sp->data.p, sp [-1].data.p, i32);
2231                         vt_sp += (i32 + 7) & ~7;
2232                         ++sp;
2233                         ip += 3;
2234                         MINT_IN_BREAK;
2235                 MINT_IN_CASE(MINT_POP) {
2236                         guint16 u16 = (* (guint16 *)(ip + 1)) + 1;
2237                         if (u16 > 1)
2238                                 memmove (sp - u16, sp - 1, (u16 - 1) * sizeof (stackval));
2239                         sp--;
2240                         ip += 2;
2241                         MINT_IN_BREAK;
2242                 }
2243                 MINT_IN_CASE(MINT_JMP) {
2244                         RuntimeMethod *new_method = rtm->data_items [* (guint16 *)(ip + 1)];
2245                         if (!new_method->transformed) {
2246                                 frame->ip = ip;
2247                                 frame->ex = mono_interp_transform_method (new_method, context);
2248                                 if (frame->ex)
2249                                         goto exit_frame;
2250                         }
2251                         ip += 2;
2252                         if (new_method->alloca_size > rtm->alloca_size)
2253                                 g_error ("MINT_JMP to method which needs more stack space (%d > %d)", new_method->alloca_size, rtm->alloca_size); 
2254                         rtm = frame->runtime_method = new_method;
2255                         vt_sp = (unsigned char *) sp + rtm->stack_size;
2256 #if DEBUG_INTERP
2257                         vtalloc = vt_sp;
2258 #endif
2259                         locals = vt_sp + rtm->vt_stack_size;
2260                         ip = rtm->new_body_start; /* bypass storing input args from callers frame */
2261                         MINT_IN_BREAK;
2262                 }
2263                 MINT_IN_CASE(MINT_CALLI) {
2264                         MonoMethodSignature *csignature;
2265                         stackval *endsp = sp;
2266
2267                         frame->ip = ip;
2268                         
2269                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
2270                         ip += 2;
2271                         --sp;
2272                         --endsp;
2273                         child_frame.runtime_method = sp->data.p;
2274
2275                         sp->data.p = vt_sp;
2276                         child_frame.retval = sp;
2277                         /* decrement by the actual number of args */
2278                         sp -= csignature->param_count;
2279                         if (csignature->hasthis)
2280                                 --sp;
2281                         child_frame.stack_args = sp;
2282
2283                         /* `this' can be NULL for string:.ctor */
2284                         if (csignature->hasthis && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
2285                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
2286                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2287                         } else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2288                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_native_wrapper (child_frame.runtime_method->method, FALSE, FALSE), &error);
2289                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2290                         }
2291
2292                         if (csignature->hasthis) {
2293                                 MonoObject *this_arg = sp->data.p;
2294
2295                                 if (this_arg->vtable->klass->valuetype) {
2296                                         gpointer *unboxed = mono_object_unbox (this_arg);
2297                                         sp [0].data.p = unboxed;
2298                                 }
2299                         }
2300
2301                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2302
2303                         context->current_frame = frame;
2304
2305                         if (context->has_resume_state) {
2306                                 if (frame == context->handler_frame)
2307                                         SET_RESUME_STATE (context);
2308                                 else
2309                                         goto exit_frame;
2310                         }
2311
2312                         if (child_frame.ex) {
2313                                 /*
2314                                  * An exception occurred, need to run finally, fault and catch handlers..
2315                                  */
2316                                 frame->ex = child_frame.ex;
2317                                 goto handle_finally;
2318                         }
2319
2320                         /* need to handle typedbyref ... */
2321                         if (csignature->ret->type != MONO_TYPE_VOID) {
2322                                 *sp = *endsp;
2323                                 sp++;
2324                         }
2325                         MINT_IN_BREAK;
2326                 }
2327                 MINT_IN_CASE(MINT_CALLI_NAT) {
2328                         MonoMethodSignature *csignature;
2329                         stackval *endsp = sp;
2330                         unsigned char *code = NULL;
2331
2332                         frame->ip = ip;
2333                         
2334                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
2335                         ip += 2;
2336                         --sp;
2337                         --endsp;
2338                         code = sp->data.p;
2339                         child_frame.runtime_method = NULL;
2340
2341                         sp->data.p = vt_sp;
2342                         child_frame.retval = sp;
2343                         /* decrement by the actual number of args */
2344                         sp -= csignature->param_count;
2345                         if (csignature->hasthis)
2346                                 --sp;
2347                         child_frame.stack_args = sp;
2348                         ves_pinvoke_method (&child_frame, csignature, (MonoFuncV) code, FALSE, context);
2349
2350                         context->current_frame = frame;
2351
2352                         if (context->has_resume_state) {
2353                                 if (frame == context->handler_frame)
2354                                         SET_RESUME_STATE (context);
2355                                 else
2356                                         goto exit_frame;
2357                         }
2358
2359                         if (child_frame.ex) {
2360                                 /*
2361                                  * An exception occurred, need to run finally, fault and catch handlers..
2362                                  */
2363                                 frame->ex = child_frame.ex;
2364                                 if (context->search_for_handler) {
2365                                         context->search_for_handler = 0;
2366                                         goto handle_exception;
2367                                 }
2368                                 goto handle_finally;
2369                         }
2370
2371                         /* need to handle typedbyref ... */
2372                         if (csignature->ret->type != MONO_TYPE_VOID) {
2373                                 *sp = *endsp;
2374                                 sp++;
2375                         }
2376                         MINT_IN_BREAK;
2377                 }
2378                 MINT_IN_CASE(MINT_CALL) {
2379                         stackval *endsp = sp;
2380
2381                         frame->ip = ip;
2382                         
2383                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
2384                         ip += 2;
2385                         sp->data.p = vt_sp;
2386                         child_frame.retval = sp;
2387                         /* decrement by the actual number of args */
2388                         sp -= child_frame.runtime_method->param_count;
2389                         if (child_frame.runtime_method->hasthis)
2390                                 --sp;
2391                         child_frame.stack_args = sp;
2392
2393                         /* `this' can be NULL for string:.ctor */
2394                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
2395                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
2396                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2397                         }
2398
2399                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2400
2401                         context->current_frame = frame;
2402
2403                         if (context->has_resume_state) {
2404                                 if (frame == context->handler_frame)
2405                                         SET_RESUME_STATE (context);
2406                                 else
2407                                         goto exit_frame;
2408                         }
2409
2410                         if (child_frame.ex) {
2411                                 /*
2412                                  * An exception occurred, need to run finally, fault and catch handlers..
2413                                  */
2414                                 frame->ex = child_frame.ex;
2415                                 goto handle_exception;;
2416                         }
2417
2418                         /* need to handle typedbyref ... */
2419                         *sp = *endsp;
2420                         sp++;
2421                         MINT_IN_BREAK;
2422                 }
2423                 MINT_IN_CASE(MINT_VCALL) {
2424                         frame->ip = ip;
2425                         
2426                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
2427                         ip += 2;
2428
2429                         sp->data.p = vt_sp;
2430                         child_frame.retval = sp;
2431                         /* decrement by the actual number of args */
2432                         sp -= child_frame.runtime_method->param_count;
2433                         if (child_frame.runtime_method->hasthis) {
2434                                 --sp;
2435                                 MonoObject *this_arg = sp->data.p;
2436                                 if (!this_arg)
2437                                         THROW_EX (mono_get_exception_null_reference(), ip - 2);
2438                         }
2439                         child_frame.stack_args = sp;
2440
2441                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
2442                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
2443                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2444                         }
2445
2446                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2447
2448                         context->current_frame = frame;
2449
2450                         if (context->has_resume_state) {
2451                                 if (frame == context->handler_frame)
2452                                         SET_RESUME_STATE (context);
2453                                 else
2454                                         goto exit_frame;
2455                         }
2456
2457                         if (child_frame.ex) {
2458                                 /*
2459                                  * An exception occurred, need to run finally, fault and catch handlers..
2460                                  */
2461                                 frame->ex = child_frame.ex;
2462                                 goto handle_finally;
2463                         }
2464                         MINT_IN_BREAK;
2465                 }
2466
2467                 MINT_IN_CASE(MINT_JIT_CALL) {
2468                         MonoMethodSignature *sig;
2469                         RuntimeMethod *rmethod = rtm->data_items [* (guint16 *)(ip + 1)];
2470                         MonoFtnDesc ftndesc;
2471                         guint8 res_buf [256];
2472                         MonoType *type;
2473                         MonoLMFExt ext;
2474
2475                         //printf ("%s\n", mono_method_full_name (rmethod->method, 1));
2476
2477                         /*
2478                          * Call JITted code through a gsharedvt_out wrapper. These wrappers receive every argument
2479                          * by ref and return a return value using an explicit return value argument.
2480                          */
2481                         if (!rmethod->jit_wrapper) {
2482                                 MonoMethod *method = rmethod->method;
2483                                 MonoError error;
2484
2485                                 sig = mono_method_signature (method);
2486                                 g_assert (sig);
2487
2488                                 MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
2489                                 //printf ("J: %s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
2490
2491                                 gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, &error);
2492                                 mono_error_assert_ok (&error);
2493
2494                                 gpointer addr = mono_jit_compile_method_jit_only (method, &error);
2495                                 g_assert (addr);
2496                                 mono_error_assert_ok (&error);
2497
2498                                 rmethod->jit_addr = addr;
2499                                 rmethod->jit_sig = sig;
2500                                 mono_memory_barrier ();
2501                                 rmethod->jit_wrapper = jit_wrapper;
2502
2503                         } else {
2504                                 sig = rmethod->jit_sig;
2505                         }
2506
2507                         frame->ip = ip;
2508                         ip += 2;
2509                         sp -= sig->param_count;
2510                         if (sig->hasthis)
2511                                 --sp;
2512
2513                         ftndesc.addr = rmethod->jit_addr;
2514                         ftndesc.arg = NULL;
2515
2516                         // FIXME: Optimize this
2517
2518                         gpointer args [32];
2519                         int pindex = 0;
2520                         int stack_index = 0;
2521                         if (rmethod->hasthis) {
2522                                 args [pindex ++] = sp [0].data.p;
2523                                 stack_index ++;
2524                         }
2525                         type = rmethod->rtype;
2526                         if (type->type != MONO_TYPE_VOID) {
2527                                 if (MONO_TYPE_ISSTRUCT (type))
2528                                         args [pindex ++] = vt_sp;
2529                                 else
2530                                         args [pindex ++] = res_buf;
2531                         }
2532                         for (int i = 0; i < rmethod->param_count; ++i) {
2533                                 MonoType *t = rmethod->param_types [i];
2534                                 stackval *sval = &sp [stack_index + i];
2535                                 if (sig->params [i]->byref) {
2536                                         args [pindex ++] = sval->data.p;
2537                                 } else if (MONO_TYPE_ISSTRUCT (t)) {
2538                                         args [pindex ++] = sval->data.p;
2539                                 } else if (MONO_TYPE_IS_REFERENCE (t)) {
2540                                         args [pindex ++] = &sval->data.p;
2541                                 } else {
2542                                         switch (t->type) {
2543                                         case MONO_TYPE_I1:
2544                                         case MONO_TYPE_U1:
2545                                         case MONO_TYPE_I2:
2546                                         case MONO_TYPE_U2:
2547                                         case MONO_TYPE_I4:
2548                                         case MONO_TYPE_U4:
2549                                         case MONO_TYPE_VALUETYPE:
2550                                                 args [pindex ++] = &sval->data.i;
2551                                                 break;
2552                                         case MONO_TYPE_PTR:
2553                                         case MONO_TYPE_FNPTR:
2554                                         case MONO_TYPE_I:
2555                                         case MONO_TYPE_U:
2556                                         case MONO_TYPE_OBJECT:
2557                                                 args [pindex ++] = &sval->data.p;
2558                                                 break;
2559                                         case MONO_TYPE_I8:
2560                                         case MONO_TYPE_U8:
2561                                                 args [pindex ++] = &sval->data.l;
2562                                                 break;
2563                                         default:
2564                                                 printf ("%s\n", mono_type_full_name (t));
2565                                                 g_assert_not_reached ();
2566                                         }
2567                                 }
2568                         }
2569
2570                         /*
2571                          * Push an LMF frame on the LMF stack
2572                          * to mark the transition to compiled code.
2573                          */
2574                         memset (&ext, 0, sizeof (ext));
2575                         ext.interp_exit = TRUE;
2576                         ext.interp_exit_data = frame;
2577
2578                         mono_push_lmf (&ext);
2579
2580                         switch (pindex) {
2581                         case 0: {
2582                                 void (*func)(gpointer) = rmethod->jit_wrapper;
2583
2584                                 func (&ftndesc);
2585                                 break;
2586                         }
2587                         case 1: {
2588                                 void (*func)(gpointer, gpointer) = rmethod->jit_wrapper;
2589
2590                                 func (args [0], &ftndesc);
2591                                 break;
2592                         }
2593                         case 2: {
2594                                 void (*func)(gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2595
2596                                 func (args [0], args [1], &ftndesc);
2597                                 break;
2598                         }
2599                         case 3: {
2600                                 void (*func)(gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2601
2602                                 func (args [0], args [1], args [2], &ftndesc);
2603                                 break;
2604                         }
2605                         case 4: {
2606                                 void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2607
2608                                 func (args [0], args [1], args [2], args [3], &ftndesc);
2609                                 break;
2610                         }
2611                         case 5: {
2612                                 void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2613
2614                                 func (args [0], args [1], args [2], args [3], args [4], &ftndesc);
2615                                 break;
2616                         }
2617                         case 6: {
2618                                 void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2619
2620                                 func (args [0], args [1], args [2], args [3], args [4], args [5], &ftndesc);
2621                                 break;
2622                         }
2623                         case 7: {
2624                                 void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2625
2626                                 func (args [0], args [1], args [2], args [3], args [4], args [5], args [6], &ftndesc);
2627                                 break;
2628                         }
2629                         default:
2630                                 g_assert_not_reached ();
2631                                 break;
2632                         }
2633
2634                         mono_pop_lmf (&ext.lmf);
2635
2636                         if (context->has_resume_state) {
2637                                 /*
2638                                  * If this bit is set, it means the call has thrown the exception, and we
2639                                  * reached this point because the EH code in mono_handle_exception ()
2640                                  * unwound all the JITted frames below us. mono_interp_set_resume_state ()
2641                                  * has set the fields in context to indicate where we have to resume execution.
2642                                  */
2643                                 if (frame == context->handler_frame)
2644                                         SET_RESUME_STATE (context);
2645                                 else
2646                                         goto exit_frame;
2647                         }
2648
2649                         MonoType *rtype = rmethod->rtype;
2650                         switch (rtype->type) {
2651                         case MONO_TYPE_VOID:
2652                         case MONO_TYPE_OBJECT:
2653                         case MONO_TYPE_STRING:
2654                         case MONO_TYPE_CLASS:
2655                         case MONO_TYPE_ARRAY:
2656                         case MONO_TYPE_SZARRAY:
2657                         case MONO_TYPE_I:
2658                         case MONO_TYPE_U:
2659                                 sp->data.p = *(gpointer*)res_buf;
2660                                 break;
2661                         case MONO_TYPE_I1:
2662                                 sp->data.i = *(gint8*)res_buf;
2663                                 break;
2664                         case MONO_TYPE_U1:
2665                                 sp->data.i = *(guint8*)res_buf;
2666                                 break;
2667                         case MONO_TYPE_I2:
2668                                 sp->data.i = *(gint16*)res_buf;
2669                                 break;
2670                         case MONO_TYPE_U2:
2671                                 sp->data.i = *(guint16*)res_buf;
2672                                 break;
2673                         case MONO_TYPE_I4:
2674                                 sp->data.i = *(gint32*)res_buf;
2675                                 break;
2676                         case MONO_TYPE_U4:
2677                                 sp->data.i = *(guint32*)res_buf;
2678                                 break;
2679                         case MONO_TYPE_VALUETYPE:
2680                                 /* The result was written to vt_sp */
2681                                 sp->data.p = vt_sp;
2682                                 break;
2683                         case MONO_TYPE_GENERICINST:
2684                                 if (MONO_TYPE_IS_REFERENCE (rtype)) {
2685                                         sp->data.p = *(gpointer*)res_buf;
2686                                 } else {
2687                                         /* The result was written to vt_sp */
2688                                         sp->data.p = vt_sp;
2689                                 }
2690                                 break;
2691                         default:
2692                                 printf ("%s\n", mono_type_full_name (rtype));
2693                                 g_assert_not_reached ();
2694                                 break;
2695                         }
2696                         if (rtype->type != MONO_TYPE_VOID)
2697                                 sp++;
2698                         MINT_IN_BREAK;
2699                 }
2700
2701                 MINT_IN_CASE(MINT_CALLVIRT) {
2702                         stackval *endsp = sp;
2703                         MonoObject *this_arg;
2704                         guint32 token;
2705
2706                         frame->ip = ip;
2707                         
2708                         token = * (unsigned short *)(ip + 1);
2709                         ip += 2;
2710                         child_frame.runtime_method = rtm->data_items [token];
2711                         sp->data.p = vt_sp;
2712                         child_frame.retval = sp;
2713
2714                         /* decrement by the actual number of args */
2715                         sp -= child_frame.runtime_method->param_count + 1;
2716                         child_frame.stack_args = sp;
2717                         this_arg = sp->data.p;
2718                         if (!this_arg)
2719                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
2720                         child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
2721
2722                         MonoClass *this_class = this_arg->vtable->klass;
2723                         if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
2724                                 /* unbox */
2725                                 gpointer *unboxed = mono_object_unbox (this_arg);
2726                                 sp [0].data.p = unboxed;
2727                         }
2728
2729                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2730
2731                         context->current_frame = frame;
2732
2733                         if (context->has_resume_state) {
2734                                 if (frame == context->handler_frame)
2735                                         SET_RESUME_STATE (context);
2736                                 else
2737                                         goto exit_frame;
2738                         }
2739
2740                         if (child_frame.ex) {
2741                                 /*
2742                                  * An exception occurred, need to run finally, fault and catch handlers..
2743                                  */
2744                                 frame->ex = child_frame.ex;
2745                                 if (context->search_for_handler) {
2746                                         context->search_for_handler = 0;
2747                                         goto handle_exception;
2748                                 }
2749                                 goto handle_finally;
2750                         }
2751
2752                         /* need to handle typedbyref ... */
2753                         *sp = *endsp;
2754                         sp++;
2755                         MINT_IN_BREAK;
2756                 }
2757                 MINT_IN_CASE(MINT_VCALLVIRT) {
2758                         MonoObject *this_arg;
2759                         guint32 token;
2760
2761                         frame->ip = ip;
2762                         
2763                         token = * (unsigned short *)(ip + 1);
2764                         ip += 2;
2765                         child_frame.runtime_method = rtm->data_items [token];
2766                         sp->data.p = vt_sp;
2767                         child_frame.retval = sp;
2768
2769                         /* decrement by the actual number of args */
2770                         sp -= child_frame.runtime_method->param_count + 1;
2771                         child_frame.stack_args = sp;
2772                         this_arg = sp->data.p;
2773                         if (!this_arg)
2774                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
2775                         child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
2776
2777                         MonoClass *this_class = this_arg->vtable->klass;
2778                         if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
2779                                 gpointer *unboxed = mono_object_unbox (this_arg);
2780                                 sp [0].data.p = unboxed;
2781                         }
2782
2783                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2784
2785                         context->current_frame = frame;
2786
2787                         if (context->has_resume_state) {
2788                                 if (frame == context->handler_frame)
2789                                         SET_RESUME_STATE (context);
2790                                 else
2791                                         goto exit_frame;
2792                         }
2793
2794                         if (child_frame.ex) {
2795                                 /*
2796                                  * An exception occurred, need to run finally, fault and catch handlers..
2797                                  */
2798                                 frame->ex = child_frame.ex;
2799                                 if (context->search_for_handler) {
2800                                         context->search_for_handler = 0;
2801                                         goto handle_exception;
2802                                 }
2803                                 goto handle_finally;
2804                         }
2805                         MINT_IN_BREAK;
2806                 }
2807                 MINT_IN_CASE(MINT_CALLRUN)
2808                         ves_runtime_method (frame, context);
2809                         if (frame->ex) {
2810                                 rtm = NULL;
2811                                 goto handle_exception;
2812                         }
2813                         goto exit_frame;
2814                 MINT_IN_CASE(MINT_RET)
2815                         --sp;
2816                         *frame->retval = *sp;
2817                         if (sp > frame->stack)
2818                                 g_warning ("ret: more values on stack: %d", sp-frame->stack);
2819                         goto exit_frame;
2820                 MINT_IN_CASE(MINT_RET_VOID)
2821                         if (sp > frame->stack)
2822                                 g_warning ("ret.void: more values on stack: %d", sp-frame->stack);
2823                         goto exit_frame;
2824                 MINT_IN_CASE(MINT_RET_VT)
2825                         i32 = READ32(ip + 1);
2826                         --sp;
2827                         memcpy(frame->retval->data.p, sp->data.p, i32);
2828                         if (sp > frame->stack)
2829                                 g_warning ("ret.vt: more values on stack: %d", sp-frame->stack);
2830                         goto exit_frame;
2831                 MINT_IN_CASE(MINT_BR_S)
2832                         ip += (short) *(ip + 1);
2833                         MINT_IN_BREAK;
2834                 MINT_IN_CASE(MINT_BR)
2835                         ip += (gint32) READ32(ip + 1);
2836                         MINT_IN_BREAK;
2837 #define ZEROP_S(datamem, op) \
2838         --sp; \
2839         if (sp->data.datamem op 0) \
2840                 ip += * (gint16 *)(ip + 1); \
2841         else \
2842                 ip += 2;
2843
2844 #define ZEROP(datamem, op) \
2845         --sp; \
2846         if (sp->data.datamem op 0) \
2847                 ip += READ32(ip + 1); \
2848         else \
2849                 ip += 3;
2850
2851                 MINT_IN_CASE(MINT_BRFALSE_I4_S)
2852                         ZEROP_S(i, ==);
2853                         MINT_IN_BREAK;
2854                 MINT_IN_CASE(MINT_BRFALSE_I8_S)
2855                         ZEROP_S(l, ==);
2856                         MINT_IN_BREAK;
2857                 MINT_IN_CASE(MINT_BRFALSE_R8_S)
2858                         ZEROP_S(f, ==);
2859                         MINT_IN_BREAK;
2860                 MINT_IN_CASE(MINT_BRFALSE_I4)
2861                         ZEROP(i, ==);
2862                         MINT_IN_BREAK;
2863                 MINT_IN_CASE(MINT_BRFALSE_I8)
2864                         ZEROP(l, ==);
2865                         MINT_IN_BREAK;
2866                 MINT_IN_CASE(MINT_BRFALSE_R8)
2867                         ZEROP_S(f, ==);
2868                         MINT_IN_BREAK;
2869                 MINT_IN_CASE(MINT_BRTRUE_I4_S)
2870                         ZEROP_S(i, !=);
2871                         MINT_IN_BREAK;
2872                 MINT_IN_CASE(MINT_BRTRUE_I8_S)
2873                         ZEROP_S(l, !=);
2874                         MINT_IN_BREAK;
2875                 MINT_IN_CASE(MINT_BRTRUE_R8_S)
2876                         ZEROP_S(f, !=);
2877                         MINT_IN_BREAK;
2878                 MINT_IN_CASE(MINT_BRTRUE_I4)
2879                         ZEROP(i, !=);
2880                         MINT_IN_BREAK;
2881                 MINT_IN_CASE(MINT_BRTRUE_I8)
2882                         ZEROP(l, !=);
2883                         MINT_IN_BREAK;
2884                 MINT_IN_CASE(MINT_BRTRUE_R8)
2885                         ZEROP(f, !=);
2886                         MINT_IN_BREAK;
2887 #define CONDBR_S(cond) \
2888         sp -= 2; \
2889         if (cond) \
2890                 ip += * (gint16 *)(ip + 1); \
2891         else \
2892                 ip += 2;
2893 #define BRELOP_S(datamem, op) \
2894         CONDBR_S(sp[0].data.datamem op sp[1].data.datamem)
2895
2896 #define CONDBR(cond) \
2897         sp -= 2; \
2898         if (cond) \
2899                 ip += READ32(ip + 1); \
2900         else \
2901                 ip += 3;
2902
2903 #define BRELOP(datamem, op) \
2904         CONDBR(sp[0].data.datamem op sp[1].data.datamem)
2905
2906                 MINT_IN_CASE(MINT_BEQ_I4_S)
2907                         BRELOP_S(i, ==)
2908                         MINT_IN_BREAK;
2909                 MINT_IN_CASE(MINT_BEQ_I8_S)
2910                         BRELOP_S(l, ==)
2911                         MINT_IN_BREAK;
2912                 MINT_IN_CASE(MINT_BEQ_R8_S)
2913                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
2914                         MINT_IN_BREAK;
2915                 MINT_IN_CASE(MINT_BEQ_I4)
2916                         BRELOP(i, ==)
2917                         MINT_IN_BREAK;
2918                 MINT_IN_CASE(MINT_BEQ_I8)
2919                         BRELOP(l, ==)
2920                         MINT_IN_BREAK;
2921                 MINT_IN_CASE(MINT_BEQ_R8)
2922                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
2923                         MINT_IN_BREAK;
2924                 MINT_IN_CASE(MINT_BGE_I4_S)
2925                         BRELOP_S(i, >=)
2926                         MINT_IN_BREAK;
2927                 MINT_IN_CASE(MINT_BGE_I8_S)
2928                         BRELOP_S(l, >=)
2929                         MINT_IN_BREAK;
2930                 MINT_IN_CASE(MINT_BGE_R8_S)
2931                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
2932                         MINT_IN_BREAK;
2933                 MINT_IN_CASE(MINT_BGE_I4)
2934                         BRELOP(i, >=)
2935                         MINT_IN_BREAK;
2936                 MINT_IN_CASE(MINT_BGE_I8)
2937                         BRELOP(l, >=)
2938                         MINT_IN_BREAK;
2939                 MINT_IN_CASE(MINT_BGE_R8)
2940                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
2941                         MINT_IN_BREAK;
2942                 MINT_IN_CASE(MINT_BGT_I4_S)
2943                         BRELOP_S(i, >)
2944                         MINT_IN_BREAK;
2945                 MINT_IN_CASE(MINT_BGT_I8_S)
2946                         BRELOP_S(l, >)
2947                         MINT_IN_BREAK;
2948                 MINT_IN_CASE(MINT_BGT_R8_S)
2949                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
2950                         MINT_IN_BREAK;
2951                 MINT_IN_CASE(MINT_BGT_I4)
2952                         BRELOP(i, >)
2953                         MINT_IN_BREAK;
2954                 MINT_IN_CASE(MINT_BGT_I8)
2955                         BRELOP(l, >)
2956                         MINT_IN_BREAK;
2957                 MINT_IN_CASE(MINT_BGT_R8)
2958                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
2959                         MINT_IN_BREAK;
2960                 MINT_IN_CASE(MINT_BLT_I4_S)
2961                         BRELOP_S(i, <)
2962                         MINT_IN_BREAK;
2963                 MINT_IN_CASE(MINT_BLT_I8_S)
2964                         BRELOP_S(l, <)
2965                         MINT_IN_BREAK;
2966                 MINT_IN_CASE(MINT_BLT_R8_S)
2967                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
2968                         MINT_IN_BREAK;
2969                 MINT_IN_CASE(MINT_BLT_I4)
2970                         BRELOP(i, <)
2971                         MINT_IN_BREAK;
2972                 MINT_IN_CASE(MINT_BLT_I8)
2973                         BRELOP(l, <)
2974                         MINT_IN_BREAK;
2975                 MINT_IN_CASE(MINT_BLT_R8)
2976                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
2977                         MINT_IN_BREAK;
2978                 MINT_IN_CASE(MINT_BLE_I4_S)
2979                         BRELOP_S(i, <=)
2980                         MINT_IN_BREAK;
2981                 MINT_IN_CASE(MINT_BLE_I8_S)
2982                         BRELOP_S(l, <=)
2983                         MINT_IN_BREAK;
2984                 MINT_IN_CASE(MINT_BLE_R8_S)
2985                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
2986                         MINT_IN_BREAK;
2987                 MINT_IN_CASE(MINT_BLE_I4)
2988                         BRELOP(i, <=)
2989                         MINT_IN_BREAK;
2990                 MINT_IN_CASE(MINT_BLE_I8)
2991                         BRELOP(l, <=)
2992                         MINT_IN_BREAK;
2993                 MINT_IN_CASE(MINT_BLE_R8)
2994                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
2995                         MINT_IN_BREAK;
2996                 MINT_IN_CASE(MINT_BNE_UN_I4_S)
2997                         BRELOP_S(i, !=)
2998                         MINT_IN_BREAK;
2999                 MINT_IN_CASE(MINT_BNE_UN_I8_S)
3000                         BRELOP_S(l, !=)
3001                         MINT_IN_BREAK;
3002                 MINT_IN_CASE(MINT_BNE_UN_R8_S)
3003                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
3004                         MINT_IN_BREAK;
3005                 MINT_IN_CASE(MINT_BNE_UN_I4)
3006                         BRELOP(i, !=)
3007                         MINT_IN_BREAK;
3008                 MINT_IN_CASE(MINT_BNE_UN_I8)
3009                         BRELOP(l, !=)
3010                         MINT_IN_BREAK;
3011                 MINT_IN_CASE(MINT_BNE_UN_R8)
3012                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
3013                         MINT_IN_BREAK;
3014
3015 #define BRELOP_S_CAST(datamem, op, type) \
3016         sp -= 2; \
3017         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
3018                 ip += * (gint16 *)(ip + 1); \
3019         else \
3020                 ip += 2;
3021
3022 #define BRELOP_CAST(datamem, op, type) \
3023         sp -= 2; \
3024         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
3025                 ip += READ32(ip + 1); \
3026         else \
3027                 ip += 3;
3028
3029                 MINT_IN_CASE(MINT_BGE_UN_I4_S)
3030                         BRELOP_S_CAST(i, >=, guint32);
3031                         MINT_IN_BREAK;
3032                 MINT_IN_CASE(MINT_BGE_UN_I8_S)
3033                         BRELOP_S_CAST(l, >=, guint64);
3034                         MINT_IN_BREAK;
3035                 MINT_IN_CASE(MINT_BGE_UN_R8_S)
3036                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
3037                         MINT_IN_BREAK;
3038                 MINT_IN_CASE(MINT_BGE_UN_I4)
3039                         BRELOP_CAST(i, >=, guint32);
3040                         MINT_IN_BREAK;
3041                 MINT_IN_CASE(MINT_BGE_UN_I8)
3042                         BRELOP_CAST(l, >=, guint64);
3043                         MINT_IN_BREAK;
3044                 MINT_IN_CASE(MINT_BGE_UN_R8)
3045                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
3046                         MINT_IN_BREAK;
3047                 MINT_IN_CASE(MINT_BGT_UN_I4_S)
3048                         BRELOP_S_CAST(i, >, guint32);
3049                         MINT_IN_BREAK;
3050                 MINT_IN_CASE(MINT_BGT_UN_I8_S)
3051                         BRELOP_S_CAST(l, >, guint64);
3052                         MINT_IN_BREAK;
3053                 MINT_IN_CASE(MINT_BGT_UN_R8_S)
3054                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
3055                         MINT_IN_BREAK;
3056                 MINT_IN_CASE(MINT_BGT_UN_I4)
3057                         BRELOP_CAST(i, >, guint32);
3058                         MINT_IN_BREAK;
3059                 MINT_IN_CASE(MINT_BGT_UN_I8)
3060                         BRELOP_CAST(l, >, guint64);
3061                         MINT_IN_BREAK;
3062                 MINT_IN_CASE(MINT_BGT_UN_R8)
3063                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
3064                         MINT_IN_BREAK;
3065                 MINT_IN_CASE(MINT_BLE_UN_I4_S)
3066                         BRELOP_S_CAST(i, <=, guint32);
3067                         MINT_IN_BREAK;
3068                 MINT_IN_CASE(MINT_BLE_UN_I8_S)
3069                         BRELOP_S_CAST(l, <=, guint64);
3070                         MINT_IN_BREAK;
3071                 MINT_IN_CASE(MINT_BLE_UN_R8_S)
3072                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
3073                         MINT_IN_BREAK;
3074                 MINT_IN_CASE(MINT_BLE_UN_I4)
3075                         BRELOP_CAST(i, <=, guint32);
3076                         MINT_IN_BREAK;
3077                 MINT_IN_CASE(MINT_BLE_UN_I8)
3078                         BRELOP_CAST(l, <=, guint64);
3079                         MINT_IN_BREAK;
3080                 MINT_IN_CASE(MINT_BLE_UN_R8)
3081                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
3082                         MINT_IN_BREAK;
3083                 MINT_IN_CASE(MINT_BLT_UN_I4_S)
3084                         BRELOP_S_CAST(i, <, guint32);
3085                         MINT_IN_BREAK;
3086                 MINT_IN_CASE(MINT_BLT_UN_I8_S)
3087                         BRELOP_S_CAST(l, <, guint64);
3088                         MINT_IN_BREAK;
3089                 MINT_IN_CASE(MINT_BLT_UN_R8_S)
3090                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
3091                         MINT_IN_BREAK;
3092                 MINT_IN_CASE(MINT_BLT_UN_I4)
3093                         BRELOP_CAST(i, <, guint32);
3094                         MINT_IN_BREAK;
3095                 MINT_IN_CASE(MINT_BLT_UN_I8)
3096                         BRELOP_CAST(l, <, guint64);
3097                         MINT_IN_BREAK;
3098                 MINT_IN_CASE(MINT_BLT_UN_R8)
3099                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
3100                         MINT_IN_BREAK;
3101                 MINT_IN_CASE(MINT_SWITCH) {
3102                         guint32 n;
3103                         const unsigned short *st;
3104                         ++ip;
3105                         n = READ32 (ip);
3106                         ip += 2;
3107                         st = ip + 2 * n;
3108                         --sp;
3109                         if ((guint32)sp->data.i < n) {
3110                                 gint offset;
3111                                 ip += 2 * (guint32)sp->data.i;
3112                                 offset = READ32 (ip);
3113                                 ip = st + offset;
3114                         } else {
3115                                 ip = st;
3116                         }
3117                         MINT_IN_BREAK;
3118                 }
3119                 MINT_IN_CASE(MINT_LDIND_I1)
3120                         ++ip;
3121                         sp[-1].data.i = *(gint8*)sp[-1].data.p;
3122                         MINT_IN_BREAK;
3123                 MINT_IN_CASE(MINT_LDIND_U1)
3124                         ++ip;
3125                         sp[-1].data.i = *(guint8*)sp[-1].data.p;
3126                         MINT_IN_BREAK;
3127                 MINT_IN_CASE(MINT_LDIND_I2)
3128                         ++ip;
3129                         sp[-1].data.i = *(gint16*)sp[-1].data.p;
3130                         MINT_IN_BREAK;
3131                 MINT_IN_CASE(MINT_LDIND_U2)
3132                         ++ip;
3133                         sp[-1].data.i = *(guint16*)sp[-1].data.p;
3134                         MINT_IN_BREAK;
3135                 MINT_IN_CASE(MINT_LDIND_I4) /* Fall through */
3136                 MINT_IN_CASE(MINT_LDIND_U4)
3137                         ++ip;
3138                         sp[-1].data.i = *(gint32*)sp[-1].data.p;
3139                         MINT_IN_BREAK;
3140                 MINT_IN_CASE(MINT_LDIND_I8)
3141                         ++ip;
3142                         sp[-1].data.l = *(gint64*)sp[-1].data.p;
3143                         MINT_IN_BREAK;
3144                 MINT_IN_CASE(MINT_LDIND_I) {
3145                         guint16 offset = * (guint16 *)(ip + 1);
3146                         sp[-1 - offset].data.p = *(gpointer*)sp[-1 - offset].data.p;
3147                         ip += 2;
3148                         MINT_IN_BREAK;
3149                 }
3150                 MINT_IN_CASE(MINT_LDIND_R4)
3151                         ++ip;
3152                         sp[-1].data.f = *(gfloat*)sp[-1].data.p;
3153                         MINT_IN_BREAK;
3154                 MINT_IN_CASE(MINT_LDIND_R8)
3155                         ++ip;
3156                         sp[-1].data.f = *(gdouble*)sp[-1].data.p;
3157                         MINT_IN_BREAK;
3158                 MINT_IN_CASE(MINT_LDIND_REF)
3159                         ++ip;
3160                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
3161                         MINT_IN_BREAK;
3162                 MINT_IN_CASE(MINT_STIND_REF) 
3163                         ++ip;
3164                         sp -= 2;
3165                         mono_gc_wbarrier_generic_store (sp->data.p, sp [1].data.p);
3166                         MINT_IN_BREAK;
3167                 MINT_IN_CASE(MINT_STIND_I1)
3168                         ++ip;
3169                         sp -= 2;
3170                         * (gint8 *) sp->data.p = (gint8)sp[1].data.i;
3171                         MINT_IN_BREAK;
3172                 MINT_IN_CASE(MINT_STIND_I2)
3173                         ++ip;
3174                         sp -= 2;
3175                         * (gint16 *) sp->data.p = (gint16)sp[1].data.i;
3176                         MINT_IN_BREAK;
3177                 MINT_IN_CASE(MINT_STIND_I4)
3178                         ++ip;
3179                         sp -= 2;
3180                         * (gint32 *) sp->data.p = sp[1].data.i;
3181                         MINT_IN_BREAK;
3182                 MINT_IN_CASE(MINT_STIND_I)
3183                         ++ip;
3184                         sp -= 2;
3185                         * (mono_i *) sp->data.p = (mono_i)sp[1].data.p;
3186                         MINT_IN_BREAK;
3187                 MINT_IN_CASE(MINT_STIND_I8)
3188                         ++ip;
3189                         sp -= 2;
3190                         * (gint64 *) sp->data.p = sp[1].data.l;
3191                         MINT_IN_BREAK;
3192                 MINT_IN_CASE(MINT_STIND_R4)
3193                         ++ip;
3194                         sp -= 2;
3195                         * (float *) sp->data.p = (gfloat)sp[1].data.f;
3196                         MINT_IN_BREAK;
3197                 MINT_IN_CASE(MINT_STIND_R8)
3198                         ++ip;
3199                         sp -= 2;
3200                         * (double *) sp->data.p = sp[1].data.f;
3201                         MINT_IN_BREAK;
3202                 MINT_IN_CASE(MINT_MONO_ATOMIC_STORE_I4)
3203                         ++ip;
3204                         sp -= 2;
3205                         InterlockedWrite ((gint32 *) sp->data.p, sp [1].data.i);
3206                         MINT_IN_BREAK;
3207 #define BINOP(datamem, op) \
3208         --sp; \
3209         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.datamem; \
3210         ++ip;
3211                 MINT_IN_CASE(MINT_ADD_I4)
3212                         BINOP(i, +);
3213                         MINT_IN_BREAK;
3214                 MINT_IN_CASE(MINT_ADD_I8)
3215                         BINOP(l, +);
3216                         MINT_IN_BREAK;
3217                 MINT_IN_CASE(MINT_ADD_R8)
3218                         BINOP(f, +);
3219                         MINT_IN_BREAK;
3220                 MINT_IN_CASE(MINT_ADD1_I4)
3221                         ++sp [-1].data.i;
3222                         ++ip;
3223                         MINT_IN_BREAK;
3224                 MINT_IN_CASE(MINT_SUB_I4)
3225                         BINOP(i, -);
3226                         MINT_IN_BREAK;
3227                 MINT_IN_CASE(MINT_SUB_I8)
3228                         BINOP(l, -);
3229                         MINT_IN_BREAK;
3230                 MINT_IN_CASE(MINT_SUB_R8)
3231                         BINOP(f, -);
3232                         MINT_IN_BREAK;
3233                 MINT_IN_CASE(MINT_SUB1_I4)
3234                         --sp [-1].data.i;
3235                         ++ip;
3236                         MINT_IN_BREAK;
3237                 MINT_IN_CASE(MINT_MUL_I4)
3238                         BINOP(i, *);
3239                         MINT_IN_BREAK;
3240                 MINT_IN_CASE(MINT_MUL_I8)
3241                         BINOP(l, *);
3242                         MINT_IN_BREAK;
3243                 MINT_IN_CASE(MINT_MUL_R8)
3244                         BINOP(f, *);
3245                         MINT_IN_BREAK;
3246                 MINT_IN_CASE(MINT_DIV_I4)
3247                         if (sp [-1].data.i == 0)
3248                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3249                         if (sp [-1].data.i == (-1))
3250                                 THROW_EX (mono_get_exception_overflow (), ip);
3251                         BINOP(i, /);
3252                         MINT_IN_BREAK;
3253                 MINT_IN_CASE(MINT_DIV_I8)
3254                         if (sp [-1].data.l == 0)
3255                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3256                         if (sp [-1].data.l == (-1))
3257                                 THROW_EX (mono_get_exception_overflow (), ip);
3258                         BINOP(l, /);
3259                         MINT_IN_BREAK;
3260                 MINT_IN_CASE(MINT_DIV_R8)
3261                         BINOP(f, /);
3262                         MINT_IN_BREAK;
3263
3264 #define BINOP_CAST(datamem, op, type) \
3265         --sp; \
3266         sp [-1].data.datamem = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
3267         ++ip;
3268                 MINT_IN_CASE(MINT_DIV_UN_I4)
3269                         if (sp [-1].data.i == 0)
3270                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3271                         BINOP_CAST(i, /, guint32);
3272                         MINT_IN_BREAK;
3273                 MINT_IN_CASE(MINT_DIV_UN_I8)
3274                         if (sp [-1].data.l == 0)
3275                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3276                         BINOP_CAST(l, /, guint64);
3277                         MINT_IN_BREAK;
3278                 MINT_IN_CASE(MINT_REM_I4)
3279                         if (sp [-1].data.i == 0)
3280                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3281                         if (sp [-1].data.i == (-1))
3282                                 THROW_EX (mono_get_exception_overflow (), ip);
3283                         BINOP(i, %);
3284                         MINT_IN_BREAK;
3285                 MINT_IN_CASE(MINT_REM_I8)
3286                         if (sp [-1].data.l == 0)
3287                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3288                         if (sp [-1].data.l == (-1))
3289                                 THROW_EX (mono_get_exception_overflow (), ip);
3290                         BINOP(l, %);
3291                         MINT_IN_BREAK;
3292                 MINT_IN_CASE(MINT_REM_R8)
3293                         /* FIXME: what do we actually do here? */
3294                         --sp;
3295                         sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
3296                         ++ip;
3297                         MINT_IN_BREAK;
3298                 MINT_IN_CASE(MINT_REM_UN_I4)
3299                         if (sp [-1].data.i == 0)
3300                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3301                         BINOP_CAST(i, %, guint32);
3302                         MINT_IN_BREAK;
3303                 MINT_IN_CASE(MINT_REM_UN_I8)
3304                         if (sp [-1].data.l == 0)
3305                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3306                         BINOP_CAST(l, %, guint64);
3307                         MINT_IN_BREAK;
3308                 MINT_IN_CASE(MINT_AND_I4)
3309                         BINOP(i, &);
3310                         MINT_IN_BREAK;
3311                 MINT_IN_CASE(MINT_AND_I8)
3312                         BINOP(l, &);
3313                         MINT_IN_BREAK;
3314                 MINT_IN_CASE(MINT_OR_I4)
3315                         BINOP(i, |);
3316                         MINT_IN_BREAK;
3317                 MINT_IN_CASE(MINT_OR_I8)
3318                         BINOP(l, |);
3319                         MINT_IN_BREAK;
3320                 MINT_IN_CASE(MINT_XOR_I4)
3321                         BINOP(i, ^);
3322                         MINT_IN_BREAK;
3323                 MINT_IN_CASE(MINT_XOR_I8)
3324                         BINOP(l, ^);
3325                         MINT_IN_BREAK;
3326
3327 #define SHIFTOP(datamem, op) \
3328         --sp; \
3329         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.i; \
3330         ++ip;
3331
3332                 MINT_IN_CASE(MINT_SHL_I4)
3333                         SHIFTOP(i, <<);
3334                         MINT_IN_BREAK;
3335                 MINT_IN_CASE(MINT_SHL_I8)
3336                         SHIFTOP(l, <<);
3337                         MINT_IN_BREAK;
3338                 MINT_IN_CASE(MINT_SHR_I4)
3339                         SHIFTOP(i, >>);
3340                         MINT_IN_BREAK;
3341                 MINT_IN_CASE(MINT_SHR_I8)
3342                         SHIFTOP(l, >>);
3343                         MINT_IN_BREAK;
3344                 MINT_IN_CASE(MINT_SHR_UN_I4)
3345                         --sp;
3346                         sp [-1].data.i = (guint32)sp [-1].data.i >> sp [0].data.i;
3347                         ++ip;
3348                         MINT_IN_BREAK;
3349                 MINT_IN_CASE(MINT_SHR_UN_I8)
3350                         --sp;
3351                         sp [-1].data.l = (guint64)sp [-1].data.l >> sp [0].data.i;
3352                         ++ip;
3353                         MINT_IN_BREAK;
3354                 MINT_IN_CASE(MINT_NEG_I4)
3355                         sp [-1].data.i = - sp [-1].data.i;
3356                         ++ip;
3357                         MINT_IN_BREAK;
3358                 MINT_IN_CASE(MINT_NEG_I8)
3359                         sp [-1].data.l = - sp [-1].data.l;
3360                         ++ip;
3361                         MINT_IN_BREAK;
3362                 MINT_IN_CASE(MINT_NEG_R8)
3363                         sp [-1].data.f = - sp [-1].data.f;
3364                         ++ip;
3365                         MINT_IN_BREAK;
3366                 MINT_IN_CASE(MINT_NOT_I4)
3367                         sp [-1].data.i = ~ sp [-1].data.i;
3368                         ++ip;
3369                         MINT_IN_BREAK;
3370                 MINT_IN_CASE(MINT_NOT_I8)
3371                         sp [-1].data.l = ~ sp [-1].data.l;
3372                         ++ip;
3373                         MINT_IN_BREAK;
3374                 MINT_IN_CASE(MINT_CONV_I1_I4)
3375                         sp [-1].data.i = (gint8)sp [-1].data.i;
3376                         ++ip;
3377                         MINT_IN_BREAK;
3378                 MINT_IN_CASE(MINT_CONV_I1_I8)
3379                         sp [-1].data.i = (gint8)sp [-1].data.l;
3380                         ++ip;
3381                         MINT_IN_BREAK;
3382                 MINT_IN_CASE(MINT_CONV_I1_R8)
3383                         sp [-1].data.i = (gint8)sp [-1].data.f;
3384                         ++ip;
3385                         MINT_IN_BREAK;
3386                 MINT_IN_CASE(MINT_CONV_U1_I4)
3387                         sp [-1].data.i = (guint8)sp [-1].data.i;
3388                         ++ip;
3389                         MINT_IN_BREAK;
3390                 MINT_IN_CASE(MINT_CONV_U1_I8)
3391                         sp [-1].data.i = (guint8)sp [-1].data.l;
3392                         ++ip;
3393                         MINT_IN_BREAK;
3394                 MINT_IN_CASE(MINT_CONV_U1_R8)
3395                         sp [-1].data.i = (guint8)sp [-1].data.f;
3396                         ++ip;
3397                         MINT_IN_BREAK;
3398                 MINT_IN_CASE(MINT_CONV_I2_I4)
3399                         sp [-1].data.i = (gint16)sp [-1].data.i;
3400                         ++ip;
3401                         MINT_IN_BREAK;
3402                 MINT_IN_CASE(MINT_CONV_I2_I8)
3403                         sp [-1].data.i = (gint16)sp [-1].data.l;
3404                         ++ip;
3405                         MINT_IN_BREAK;
3406                 MINT_IN_CASE(MINT_CONV_I2_R8)
3407                         sp [-1].data.i = (gint16)sp [-1].data.f;
3408                         ++ip;
3409                         MINT_IN_BREAK;
3410                 MINT_IN_CASE(MINT_CONV_U2_I4)
3411                         sp [-1].data.i = (guint16)sp [-1].data.i;
3412                         ++ip;
3413                         MINT_IN_BREAK;
3414                 MINT_IN_CASE(MINT_CONV_U2_I8)
3415                         sp [-1].data.i = (guint16)sp [-1].data.l;
3416                         ++ip;
3417                         MINT_IN_BREAK;
3418                 MINT_IN_CASE(MINT_CONV_U2_R8)
3419                         sp [-1].data.i = (guint16)sp [-1].data.f;
3420                         ++ip;
3421                         MINT_IN_BREAK;
3422                 MINT_IN_CASE(MINT_CONV_I4_R8)
3423                         sp [-1].data.i = (gint32)sp [-1].data.f;
3424                         ++ip;
3425                         MINT_IN_BREAK;
3426                 MINT_IN_CASE(MINT_CONV_U4_I8)
3427                 MINT_IN_CASE(MINT_CONV_I4_I8)
3428                         sp [-1].data.i = (gint32)sp [-1].data.l;
3429                         ++ip;
3430                         MINT_IN_BREAK;
3431                 MINT_IN_CASE(MINT_CONV_I4_I8_SP)
3432                         sp [-2].data.i = (gint32)sp [-2].data.l;
3433                         ++ip;
3434                         MINT_IN_BREAK;
3435                 MINT_IN_CASE(MINT_CONV_U4_R8)
3436                         /* needed on arm64 */
3437                         if (isinf (sp [-1].data.f))
3438                                 sp [-1].data.i = 0;
3439                         else
3440                                 sp [-1].data.i = (guint32)sp [-1].data.f;
3441                         ++ip;
3442                         MINT_IN_BREAK;
3443                 MINT_IN_CASE(MINT_CONV_I8_I4)
3444                         sp [-1].data.l = sp [-1].data.i;
3445                         ++ip;
3446                         MINT_IN_BREAK;
3447                 MINT_IN_CASE(MINT_CONV_I8_I4_SP)
3448                         sp [-2].data.l = sp [-2].data.i;
3449                         ++ip;
3450                         MINT_IN_BREAK;
3451                 MINT_IN_CASE(MINT_CONV_I8_U4)
3452                         sp [-1].data.l = (guint32)sp [-1].data.i;
3453                         ++ip;
3454                         MINT_IN_BREAK;
3455                 MINT_IN_CASE(MINT_CONV_I8_R8)
3456                         sp [-1].data.l = (gint64)sp [-1].data.f;
3457                         ++ip;
3458                         MINT_IN_BREAK;
3459                 MINT_IN_CASE(MINT_CONV_R4_I4)
3460                         sp [-1].data.f = (float)sp [-1].data.i;
3461                         ++ip;
3462                         MINT_IN_BREAK;
3463                 MINT_IN_CASE(MINT_CONV_R4_I8)
3464                         sp [-1].data.f = (float)sp [-1].data.l;
3465                         ++ip;
3466                         MINT_IN_BREAK;
3467                 MINT_IN_CASE(MINT_CONV_R4_R8)
3468                         sp [-1].data.f = (float)sp [-1].data.f;
3469                         ++ip;
3470                         MINT_IN_BREAK;
3471                 MINT_IN_CASE(MINT_CONV_R8_I4)
3472                         sp [-1].data.f = (double)sp [-1].data.i;
3473                         ++ip;
3474                         MINT_IN_BREAK;
3475                 MINT_IN_CASE(MINT_CONV_R8_I8)
3476                         sp [-1].data.f = (double)sp [-1].data.l;
3477                         ++ip;
3478                         MINT_IN_BREAK;
3479                 MINT_IN_CASE(MINT_CONV_U8_I4)
3480                         sp [-1].data.l = sp [-1].data.i & 0xffffffff;
3481                         ++ip;
3482                         MINT_IN_BREAK;
3483                 MINT_IN_CASE(MINT_CONV_U8_R8)
3484                         sp [-1].data.l = (guint64)sp [-1].data.f;
3485                         ++ip;
3486                         MINT_IN_BREAK;
3487                 MINT_IN_CASE(MINT_CPOBJ) {
3488                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3489                         g_assert (c->valuetype);
3490                         /* if this assertion fails, we need to add a write barrier */
3491                         g_assert (!MONO_TYPE_IS_REFERENCE (&c->byval_arg));
3492                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE)
3493                                 stackval_from_data (&c->byval_arg, &sp [-2], sp [-1].data.p, FALSE);
3494                         else
3495                                 stackval_from_data (&c->byval_arg, sp [-2].data.p, sp [-1].data.p, FALSE);
3496                         ip += 2;
3497                         sp -= 2;
3498                         MINT_IN_BREAK;
3499                 }
3500                 MINT_IN_CASE(MINT_LDOBJ) {
3501                         void *p;
3502                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3503                         ip += 2;
3504                         p = sp [-1].data.p;
3505                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
3506                                 int size = mono_class_value_size (c, NULL);
3507                                 sp [-1].data.p = vt_sp;
3508                                 vt_sp += (size + 7) & ~7;
3509                         }
3510                         stackval_from_data (&c->byval_arg, &sp [-1], p, FALSE);
3511                         MINT_IN_BREAK;
3512                 }
3513                 MINT_IN_CASE(MINT_LDSTR)
3514                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
3515                         ++sp;
3516                         ip += 2;
3517                         MINT_IN_BREAK;
3518                 MINT_IN_CASE(MINT_NEWOBJ) {
3519                         MonoClass *newobj_class;
3520                         MonoMethodSignature *csig;
3521                         stackval valuetype_this;
3522                         guint32 token;
3523                         stackval retval;
3524
3525                         frame->ip = ip;
3526
3527                         token = * (guint16 *)(ip + 1);
3528                         ip += 2;
3529
3530                         child_frame.ip = NULL;
3531                         child_frame.ex = NULL;
3532
3533                         child_frame.runtime_method = rtm->data_items [token];
3534                         csig = mono_method_signature (child_frame.runtime_method->method);
3535                         newobj_class = child_frame.runtime_method->method->klass;
3536                         /*if (profiling_classes) {
3537                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
3538                                 count++;
3539                                 g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
3540                         }*/
3541
3542                         if (newobj_class->parent == mono_defaults.array_class) {
3543                                 sp -= csig->param_count;
3544                                 child_frame.stack_args = sp;
3545                                 o = ves_array_create (&child_frame, context->domain, newobj_class, csig, sp);
3546                                 if (child_frame.ex)
3547                                         THROW_EX (child_frame.ex, ip);
3548                                 goto array_constructed;
3549                         }
3550
3551                         g_assert (csig->hasthis);
3552                         if (csig->param_count) {
3553                                 sp -= csig->param_count;
3554                                 memmove (sp + 1, sp, csig->param_count * sizeof (stackval));
3555                         }
3556                         child_frame.stack_args = sp;
3557
3558                         /*
3559                          * First arg is the object.
3560                          */
3561                         if (newobj_class->valuetype) {
3562                                 MonoType *t = &newobj_class->byval_arg;
3563                                 memset (&valuetype_this, 0, sizeof (stackval));
3564                                 if (!newobj_class->enumtype && (t->type == MONO_TYPE_VALUETYPE || (t->type == MONO_TYPE_GENERICINST && mono_type_generic_inst_is_valuetype (t)))) {
3565                                         sp->data.p = vt_sp;
3566                                         valuetype_this.data.p = vt_sp;
3567                                 } else {
3568                                         sp->data.p = &valuetype_this;
3569                                 }
3570                         } else {
3571                                 if (newobj_class != mono_defaults.string_class) {
3572                                         context->managed_code = 0;
3573                                         o = mono_object_new_checked (context->domain, newobj_class, &error);
3574                                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3575                                         context->managed_code = 1;
3576                                         if (*mono_thread_interruption_request_flag ())
3577                                                 mono_thread_interruption_checkpoint ();
3578                                         sp->data.p = o;
3579                                 } else {
3580                                         sp->data.p = NULL;
3581                                         child_frame.retval = &retval;
3582                                 }
3583                         }
3584
3585                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
3586
3587                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
3588
3589                         context->current_frame = frame;
3590
3591                         if (context->has_resume_state) {
3592                                 if (frame == context->handler_frame)
3593                                         SET_RESUME_STATE (context);
3594                                 else
3595                                         goto exit_frame;
3596                         }
3597
3598                         if (child_frame.ex) {
3599                                 /*
3600                                  * An exception occurred, need to run finally, fault and catch handlers..
3601                                  */
3602                                 frame->ex = child_frame.ex;
3603                                 goto handle_finally;
3604                         }
3605                         /*
3606                          * a constructor returns void, but we need to return the object we created
3607                          */
3608 array_constructed:
3609                         if (newobj_class->valuetype && !newobj_class->enumtype) {
3610                                 *sp = valuetype_this;
3611                         } else if (newobj_class == mono_defaults.string_class) {
3612                                 *sp = retval;
3613                         } else {
3614                                 sp->data.p = o;
3615                         }
3616                         ++sp;
3617                         MINT_IN_BREAK;
3618                 }
3619                 MINT_IN_CASE(MINT_CASTCLASS)
3620                         c = rtm->data_items [*(guint16 *)(ip + 1)];
3621                         if ((o = sp [-1].data.p)) {
3622                                 MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
3623                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3624                                 if (!isinst_obj)
3625                                         THROW_EX (mono_get_exception_invalid_cast (), ip);
3626                         }
3627                         ip += 2;
3628                         MINT_IN_BREAK;
3629                 MINT_IN_CASE(MINT_ISINST)
3630                         c = rtm->data_items [*(guint16 *)(ip + 1)];
3631                         if ((o = sp [-1].data.p)) {
3632                                 MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
3633                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3634                                 if (!isinst_obj)
3635                                         sp [-1].data.p = NULL;
3636                         }
3637                         ip += 2;
3638                         MINT_IN_BREAK;
3639                 MINT_IN_CASE(MINT_CONV_R_UN_I4)
3640                         sp [-1].data.f = (double)(guint32)sp [-1].data.i;
3641                         ++ip;
3642                         MINT_IN_BREAK;
3643                 MINT_IN_CASE(MINT_CONV_R_UN_I8)
3644                         sp [-1].data.f = (double)(guint64)sp [-1].data.l;
3645                         ++ip;
3646                         MINT_IN_BREAK;
3647                 MINT_IN_CASE(MINT_UNBOX)
3648                         c = rtm->data_items[*(guint16 *)(ip + 1)];
3649                         
3650                         o = sp [-1].data.p;
3651                         if (!o)
3652                                 THROW_EX (mono_get_exception_null_reference (), ip);
3653
3654                         MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
3655                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3656                         if (!(isinst_obj || ((o->vtable->klass->rank == 0) && (o->vtable->klass->element_class == c->element_class))))
3657                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
3658
3659                         sp [-1].data.p = mono_object_unbox (o);
3660                         ip += 2;
3661                         MINT_IN_BREAK;
3662                 MINT_IN_CASE(MINT_THROW)
3663                         --sp;
3664                         frame->ex_handler = NULL;
3665                         if (!sp->data.p)
3666                                 sp->data.p = mono_get_exception_null_reference ();
3667                         THROW_EX ((MonoException *)sp->data.p, ip);
3668                         MINT_IN_BREAK;
3669                 MINT_IN_CASE(MINT_LDFLDA_UNSAFE)
3670                         o = sp [-1].data.p;
3671                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
3672                         ip += 2;
3673                         MINT_IN_BREAK;
3674                 MINT_IN_CASE(MINT_LDFLDA)
3675                         o = sp [-1].data.p;
3676                         if (!o)
3677                                 THROW_EX (mono_get_exception_null_reference (), ip);
3678                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
3679                         ip += 2;
3680                         MINT_IN_BREAK;
3681                 MINT_IN_CASE(MINT_CKNULL)
3682                         o = sp [-1].data.p;
3683                         if (!o)
3684                                 THROW_EX (mono_get_exception_null_reference (), ip);
3685                         ++ip;
3686                         MINT_IN_BREAK;
3687
3688 #define LDFLD(datamem, fieldtype) \
3689         o = sp [-1].data.p; \
3690         if (!o) \
3691                 THROW_EX (mono_get_exception_null_reference (), ip); \
3692         sp[-1].data.datamem = * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) ; \
3693         ip += 2;
3694
3695                 MINT_IN_CASE(MINT_LDFLD_I1) LDFLD(i, gint8); MINT_IN_BREAK;
3696                 MINT_IN_CASE(MINT_LDFLD_U1) LDFLD(i, guint8); MINT_IN_BREAK;
3697                 MINT_IN_CASE(MINT_LDFLD_I2) LDFLD(i, gint16); MINT_IN_BREAK;
3698                 MINT_IN_CASE(MINT_LDFLD_U2) LDFLD(i, guint16); MINT_IN_BREAK;
3699                 MINT_IN_CASE(MINT_LDFLD_I4) LDFLD(i, gint32); MINT_IN_BREAK;
3700                 MINT_IN_CASE(MINT_LDFLD_I8) LDFLD(l, gint64); MINT_IN_BREAK;
3701                 MINT_IN_CASE(MINT_LDFLD_R4) LDFLD(f, float); MINT_IN_BREAK;
3702                 MINT_IN_CASE(MINT_LDFLD_R8) LDFLD(f, double); MINT_IN_BREAK;
3703                 MINT_IN_CASE(MINT_LDFLD_O) LDFLD(p, gpointer); MINT_IN_BREAK;
3704                 MINT_IN_CASE(MINT_LDFLD_P) LDFLD(p, gpointer); MINT_IN_BREAK;
3705
3706                 MINT_IN_CASE(MINT_LDFLD_VT)
3707                         o = sp [-1].data.p;
3708                         if (!o)
3709                                 THROW_EX (mono_get_exception_null_reference (), ip);
3710                         i32 = READ32(ip + 2);
3711                         sp [-1].data.p = vt_sp;
3712                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
3713                         vt_sp += (i32 + 7) & ~7;
3714                         ip += 4;
3715                         MINT_IN_BREAK;
3716
3717                 MINT_IN_CASE(MINT_LDRMFLD) {
3718                         gpointer tmp;
3719                         MonoClassField *field;
3720                         char *addr;
3721
3722                         o = sp [-1].data.p;
3723                         if (!o)
3724                                 THROW_EX (mono_get_exception_null_reference (), ip);
3725                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3726                         ip += 2;
3727                         if (mono_object_is_transparent_proxy (o)) {
3728                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3729
3730                                 addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
3731                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3732                         } else {
3733                                 addr = (char*)o + field->offset;
3734                         }                               
3735
3736                         stackval_from_data (field->type, &sp [-1], addr, FALSE);
3737                         MINT_IN_BREAK;
3738                 }
3739
3740                 MINT_IN_CASE(MINT_LDRMFLD_VT) {
3741                         MonoClassField *field;
3742                         char *addr;
3743                         gpointer tmp;
3744
3745                         o = sp [-1].data.p;
3746                         if (!o)
3747                                 THROW_EX (mono_get_exception_null_reference (), ip);
3748                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3749                         i32 = READ32(ip + 2);
3750                         ip += 4;
3751                         if (mono_object_is_transparent_proxy (o)) {
3752                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3753                                 addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
3754                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3755                         } else {
3756                                 addr = (char*)o + field->offset;
3757                         }                               
3758
3759                         sp [-1].data.p = vt_sp;
3760                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
3761                         vt_sp += (i32 + 7) & ~7;
3762                         memcpy(sp [-1].data.p, addr, i32);
3763                         MINT_IN_BREAK;
3764                 }
3765
3766 #define STFLD(datamem, fieldtype) \
3767         o = sp [-2].data.p; \
3768         if (!o) \
3769                 THROW_EX (mono_get_exception_null_reference (), ip); \
3770         sp -= 2; \
3771         * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) = sp[1].data.datamem; \
3772         ip += 2;
3773
3774                 MINT_IN_CASE(MINT_STFLD_I1) STFLD(i, gint8); MINT_IN_BREAK;
3775                 MINT_IN_CASE(MINT_STFLD_U1) STFLD(i, guint8); MINT_IN_BREAK;
3776                 MINT_IN_CASE(MINT_STFLD_I2) STFLD(i, gint16); MINT_IN_BREAK;
3777                 MINT_IN_CASE(MINT_STFLD_U2) STFLD(i, guint16); MINT_IN_BREAK;
3778                 MINT_IN_CASE(MINT_STFLD_I4) STFLD(i, gint32); MINT_IN_BREAK;
3779                 MINT_IN_CASE(MINT_STFLD_I8) STFLD(l, gint64); MINT_IN_BREAK;
3780                 MINT_IN_CASE(MINT_STFLD_R4) STFLD(f, float); MINT_IN_BREAK;
3781                 MINT_IN_CASE(MINT_STFLD_R8) STFLD(f, double); MINT_IN_BREAK;
3782                 MINT_IN_CASE(MINT_STFLD_P) STFLD(p, gpointer); MINT_IN_BREAK;
3783                 MINT_IN_CASE(MINT_STFLD_O)
3784                         o = sp [-2].data.p;
3785                         if (!o)
3786                                 THROW_EX (mono_get_exception_null_reference (), ip);
3787                         sp -= 2;
3788                         mono_gc_wbarrier_set_field (o, (char *) o + * (guint16 *)(ip + 1), sp [1].data.p);
3789                         ip += 2;
3790                         MINT_IN_BREAK;
3791
3792                 MINT_IN_CASE(MINT_STFLD_VT)
3793                         o = sp [-2].data.p;
3794                         if (!o)
3795                                 THROW_EX (mono_get_exception_null_reference (), ip);
3796                         i32 = READ32(ip + 2);
3797                         sp -= 2;
3798                         memcpy((char *)o + * (guint16 *)(ip + 1), sp [1].data.p, i32);
3799                         vt_sp -= (i32 + 7) & ~7;
3800                         ip += 4;
3801                         MINT_IN_BREAK;
3802
3803                 MINT_IN_CASE(MINT_STRMFLD) {
3804                         MonoClassField *field;
3805
3806                         o = sp [-2].data.p;
3807                         if (!o)
3808                                 THROW_EX (mono_get_exception_null_reference (), ip);
3809                         
3810                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3811                         ip += 2;
3812
3813                         if (mono_object_is_transparent_proxy (o)) {
3814                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3815                                 mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
3816                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3817                         } else
3818                                 stackval_to_data (field->type, &sp [-1], (char*)o + field->offset, FALSE);
3819
3820                         sp -= 2;
3821                         MINT_IN_BREAK;
3822                 }
3823                 MINT_IN_CASE(MINT_STRMFLD_VT) {
3824                         MonoClassField *field;
3825
3826                         o = sp [-2].data.p;
3827                         if (!o)
3828                                 THROW_EX (mono_get_exception_null_reference (), ip);
3829                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3830                         i32 = READ32(ip + 2);
3831                         ip += 4;
3832
3833                         if (mono_object_is_transparent_proxy (o)) {
3834                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3835                                 mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
3836                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3837                         } else
3838                                 memcpy((char*)o + field->offset, sp [-1].data.p, i32);
3839
3840                         sp -= 2;
3841                         vt_sp -= (i32 + 7) & ~7;
3842                         MINT_IN_BREAK;
3843                 }
3844                 MINT_IN_CASE(MINT_LDSFLDA) {
3845                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
3846                         sp->data.p = mono_class_static_field_address (context->domain, field);
3847                         ip += 2;
3848                         ++sp;
3849                         MINT_IN_BREAK;
3850                 }
3851                 MINT_IN_CASE(MINT_LDSFLD) {
3852                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3853                         gpointer addr = mono_class_static_field_address (context->domain, field);
3854                         stackval_from_data (field->type, sp, addr, FALSE);
3855                         ip += 2;
3856                         ++sp;
3857                         MINT_IN_BREAK;
3858                 }
3859                 MINT_IN_CASE(MINT_LDSFLD_VT) {
3860                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3861                         gpointer addr = mono_class_static_field_address (context->domain, field);
3862                         int size = READ32 (ip + 2);
3863                         ip += 4;
3864
3865                         sp->data.p = vt_sp;
3866                         vt_sp += (size + 7) & ~7;
3867                         stackval_from_data (field->type, sp, addr, FALSE);
3868                         ++sp;
3869                         MINT_IN_BREAK;
3870                 }
3871                 MINT_IN_CASE(MINT_STSFLD) {
3872                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3873                         gpointer addr = mono_class_static_field_address (context->domain, field);
3874                         ip += 2;
3875                         --sp;
3876                         stackval_to_data (field->type, sp, addr, FALSE);
3877                         MINT_IN_BREAK;
3878                 }
3879                 MINT_IN_CASE(MINT_STSFLD_VT) {
3880                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3881                         gpointer addr = mono_class_static_field_address (context->domain, field);
3882                         int size = READ32 (ip + 2);
3883                         ip += 4;
3884
3885                         --sp;
3886                         stackval_to_data (field->type, sp, addr, FALSE);
3887                         vt_sp -= (size + 7) & ~7;
3888                         MINT_IN_BREAK;
3889                 }
3890                 MINT_IN_CASE(MINT_STOBJ_VT) {
3891                         int size;
3892                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3893                         ip += 2;
3894                         size = mono_class_value_size (c, NULL);
3895                         memcpy(sp [-2].data.p, sp [-1].data.p, size);
3896                         vt_sp -= (size + 7) & ~7;
3897                         sp -= 2;
3898                         MINT_IN_BREAK;
3899                 }
3900                 MINT_IN_CASE(MINT_STOBJ) {
3901                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3902                         ip += 2;
3903
3904                         g_assert (!c->byval_arg.byref);
3905                         if (MONO_TYPE_IS_REFERENCE (&c->byval_arg))
3906                                 mono_gc_wbarrier_generic_store (sp [-2].data.p, sp [-1].data.p);
3907                         else
3908                                 stackval_from_data (&c->byval_arg, sp [-2].data.p, (char *) &sp [-1].data.p, FALSE);
3909                         sp -= 2;
3910                         MINT_IN_BREAK;
3911                 }
3912                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_R8)
3913                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
3914                                 THROW_EX (mono_get_exception_overflow (), ip);
3915                         sp [-1].data.i = (guint32)sp [-1].data.f;
3916                         ++ip;
3917                         MINT_IN_BREAK;
3918                 MINT_IN_CASE(MINT_CONV_OVF_U8_I4)
3919                         if (sp [-1].data.i < 0)
3920                                 THROW_EX (mono_get_exception_overflow (), ip);
3921                         sp [-1].data.l = sp [-1].data.i;
3922                         ++ip;
3923                         MINT_IN_BREAK;
3924                 MINT_IN_CASE(MINT_CONV_OVF_U8_I8)
3925                         if (sp [-1].data.l < 0)
3926                                 THROW_EX (mono_get_exception_overflow (), ip);
3927                         ++ip;
3928                         MINT_IN_BREAK;
3929                 MINT_IN_CASE(MINT_CONV_OVF_I8_U8)
3930                         if ((guint64) sp [-1].data.l > MYGINT64_MAX)
3931                                 THROW_EX (mono_get_exception_overflow (), ip);
3932                         ++ip;
3933                         MINT_IN_BREAK;
3934                 MINT_IN_CASE(MINT_CONV_OVF_U8_R8)
3935                 MINT_IN_CASE(MINT_CONV_OVF_I8_UN_R8)
3936                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGINT64_MAX)
3937                                 THROW_EX (mono_get_exception_overflow (), ip);
3938                         sp [-1].data.l = (guint64)sp [-1].data.f;
3939                         ++ip;
3940                         MINT_IN_BREAK;
3941                 MINT_IN_CASE(MINT_CONV_OVF_I8_R8)
3942                         if (sp [-1].data.f < MYGINT64_MIN || sp [-1].data.f > MYGINT64_MAX)
3943                                 THROW_EX (mono_get_exception_overflow (), ip);
3944                         sp [-1].data.l = (gint64)sp [-1].data.f;
3945                         ++ip;
3946                         MINT_IN_BREAK;
3947                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_I8)
3948                         if ((mono_u)sp [-1].data.l > MYGUINT32_MAX)
3949                                 THROW_EX (mono_get_exception_overflow (), ip);
3950                         sp [-1].data.i = (mono_u)sp [-1].data.l;
3951                         ++ip;
3952                         MINT_IN_BREAK;
3953                 MINT_IN_CASE(MINT_BOX) {
3954                         c = rtm->data_items [* (guint16 *)(ip + 1)];
3955                         guint16 offset = * (guint16 *)(ip + 2);
3956
3957                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
3958                                 int size = mono_class_value_size (c, NULL);
3959                                 sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, sp [-1 - offset].data.p, &error);
3960                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3961                                 size = (size + 7) & ~7;
3962                                 vt_sp -= size;
3963                         } else {
3964                                 stackval_to_data (&c->byval_arg, &sp [-1 - offset], (char *) &sp [-1 - offset], FALSE);
3965                                 sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, &sp [-1 - offset], &error);
3966                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3967                         }
3968                         ip += 3;
3969                         MINT_IN_BREAK;
3970                 }
3971                 MINT_IN_CASE(MINT_NEWARR)
3972                         sp [-1].data.p = (MonoObject*) mono_array_new_checked (context->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i, &error);
3973                         if (!mono_error_ok (&error)) {
3974                                 THROW_EX (mono_error_convert_to_exception (&error), ip);
3975                         }
3976                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3977                         ip += 2;
3978                         /*if (profiling_classes) {
3979                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
3980                                 count++;
3981                                 g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
3982                         }*/
3983
3984                         MINT_IN_BREAK;
3985                 MINT_IN_CASE(MINT_LDLEN)
3986                         o = sp [-1].data.p;
3987                         if (!o)
3988                                 THROW_EX (mono_get_exception_null_reference (), ip);
3989                         sp [-1].data.nati = mono_array_length ((MonoArray *)o);
3990                         ++ip;
3991                         MINT_IN_BREAK;
3992                 MINT_IN_CASE(MINT_GETCHR) {
3993                         MonoString *s;
3994                         s = sp [-2].data.p;
3995                         if (!s)
3996                                 THROW_EX (mono_get_exception_null_reference (), ip);
3997                         i32 = sp [-1].data.i;
3998                         if (i32 < 0 || i32 >= mono_string_length (s))
3999                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
4000                         --sp;
4001                         sp [-1].data.i = mono_string_chars(s)[i32];
4002                         ++ip;
4003                         MINT_IN_BREAK;
4004                 }
4005                 MINT_IN_CASE(MINT_STRLEN)
4006                         ++ip;
4007                         o = sp [-1].data.p;
4008                         if (!o)
4009                                 THROW_EX (mono_get_exception_null_reference (), ip);
4010                         sp [-1].data.i = mono_string_length ((MonoString*) o);
4011                         MINT_IN_BREAK;
4012                 MINT_IN_CASE(MINT_ARRAY_RANK)
4013                         o = sp [-1].data.p;
4014                         if (!o)
4015                                 THROW_EX (mono_get_exception_null_reference (), ip);
4016                         sp [-1].data.i = mono_object_class (sp [-1].data.p)->rank;
4017                         ip++;
4018                         MINT_IN_BREAK;
4019                 MINT_IN_CASE(MINT_LDELEMA)
4020                 MINT_IN_CASE(MINT_LDELEMA_TC) {
4021                         gboolean needs_typecheck = *ip == MINT_LDELEMA_TC;
4022                         
4023                         MonoClass *klass = rtm->data_items [*(guint16 *) (ip + 1)];
4024                         guint16 numargs = *(guint16 *) (ip + 2);
4025                         ip += 3;
4026                         sp -= numargs;
4027
4028                         o = sp [0].data.p;
4029                         sp->data.p = ves_array_element_address (frame, klass, (MonoArray *) o, &sp [1], needs_typecheck);
4030                         if (frame->ex)
4031                                 THROW_EX (frame->ex, ip);
4032                         ++sp;
4033
4034                         MINT_IN_BREAK;
4035                 }
4036                 MINT_IN_CASE(MINT_LDELEM_I1) /* fall through */
4037                 MINT_IN_CASE(MINT_LDELEM_U1) /* fall through */
4038                 MINT_IN_CASE(MINT_LDELEM_I2) /* fall through */
4039                 MINT_IN_CASE(MINT_LDELEM_U2) /* fall through */
4040                 MINT_IN_CASE(MINT_LDELEM_I4) /* fall through */
4041                 MINT_IN_CASE(MINT_LDELEM_U4) /* fall through */
4042                 MINT_IN_CASE(MINT_LDELEM_I8)  /* fall through */
4043                 MINT_IN_CASE(MINT_LDELEM_I)  /* fall through */
4044                 MINT_IN_CASE(MINT_LDELEM_R4) /* fall through */
4045                 MINT_IN_CASE(MINT_LDELEM_R8) /* fall through */
4046                 MINT_IN_CASE(MINT_LDELEM_REF) /* fall through */
4047                 MINT_IN_CASE(MINT_LDELEM_VT) {
4048                         MonoArray *o;
4049                         mono_u aindex;
4050
4051                         sp -= 2;
4052
4053                         o = sp [0].data.p;
4054                         if (!o)
4055                                 THROW_EX (mono_get_exception_null_reference (), ip);
4056
4057                         aindex = sp [1].data.i;
4058                         if (aindex >= mono_array_length (o))
4059                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
4060
4061                         /*
4062                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
4063                          */
4064                         switch (*ip) {
4065                         case MINT_LDELEM_I1:
4066                                 sp [0].data.i = mono_array_get (o, gint8, aindex);
4067                                 break;
4068                         case MINT_LDELEM_U1:
4069                                 sp [0].data.i = mono_array_get (o, guint8, aindex);
4070                                 break;
4071                         case MINT_LDELEM_I2:
4072                                 sp [0].data.i = mono_array_get (o, gint16, aindex);
4073                                 break;
4074                         case MINT_LDELEM_U2:
4075                                 sp [0].data.i = mono_array_get (o, guint16, aindex);
4076                                 break;
4077                         case MINT_LDELEM_I:
4078                                 sp [0].data.nati = mono_array_get (o, mono_i, aindex);
4079                                 break;
4080                         case MINT_LDELEM_I4:
4081                                 sp [0].data.i = mono_array_get (o, gint32, aindex);
4082                                 break;
4083                         case MINT_LDELEM_U4:
4084                                 sp [0].data.i = mono_array_get (o, guint32, aindex);
4085                                 break;
4086                         case MINT_LDELEM_I8:
4087                                 sp [0].data.l = mono_array_get (o, guint64, aindex);
4088                                 break;
4089                         case MINT_LDELEM_R4:
4090                                 sp [0].data.f = mono_array_get (o, float, aindex);
4091                                 break;
4092                         case MINT_LDELEM_R8:
4093                                 sp [0].data.f = mono_array_get (o, double, aindex);
4094                                 break;
4095                         case MINT_LDELEM_REF:
4096                                 sp [0].data.p = mono_array_get (o, gpointer, aindex);
4097                                 break;
4098                         case MINT_LDELEM_VT: {
4099                                 MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
4100                                 i32 = READ32 (ip + 2);
4101                                 char *src_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
4102                                 sp [0].data.vt = vt_sp;
4103                                 stackval_from_data (&klass_vt->byval_arg, sp, src_addr, FALSE);
4104                                 vt_sp += (i32 + 7) & ~7;
4105                                 ip += 3;
4106                                 break;
4107                         }
4108                         default:
4109                                 ves_abort();
4110                         }
4111
4112                         ++ip;
4113                         ++sp;
4114                         MINT_IN_BREAK;
4115                 }
4116                 MINT_IN_CASE(MINT_STELEM_I)  /* fall through */
4117                 MINT_IN_CASE(MINT_STELEM_I1) /* fall through */ 
4118                 MINT_IN_CASE(MINT_STELEM_U1) /* fall through */
4119                 MINT_IN_CASE(MINT_STELEM_I2) /* fall through */
4120                 MINT_IN_CASE(MINT_STELEM_U2) /* fall through */
4121                 MINT_IN_CASE(MINT_STELEM_I4) /* fall through */
4122                 MINT_IN_CASE(MINT_STELEM_I8) /* fall through */
4123                 MINT_IN_CASE(MINT_STELEM_R4) /* fall through */
4124                 MINT_IN_CASE(MINT_STELEM_R8) /* fall through */
4125                 MINT_IN_CASE(MINT_STELEM_REF) /* fall through */
4126                 MINT_IN_CASE(MINT_STELEM_VT) {
4127                         mono_u aindex;
4128
4129                         sp -= 3;
4130
4131                         o = sp [0].data.p;
4132                         if (!o)
4133                                 THROW_EX (mono_get_exception_null_reference (), ip);
4134
4135                         aindex = sp [1].data.i;
4136                         if (aindex >= mono_array_length ((MonoArray *)o))
4137                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
4138
4139                         switch (*ip) {
4140                         case MINT_STELEM_I:
4141                                 mono_array_set ((MonoArray *)o, mono_i, aindex, sp [2].data.nati);
4142                                 break;
4143                         case MINT_STELEM_I1:
4144                                 mono_array_set ((MonoArray *)o, gint8, aindex, sp [2].data.i);
4145                                 break;
4146                         case MINT_STELEM_U1:
4147                                 mono_array_set ((MonoArray *) o, guint8, aindex, sp [2].data.i);
4148                                 break;
4149                         case MINT_STELEM_I2:
4150                                 mono_array_set ((MonoArray *)o, gint16, aindex, sp [2].data.i);
4151                                 break;
4152                         case MINT_STELEM_U2:
4153                                 mono_array_set ((MonoArray *)o, guint16, aindex, sp [2].data.i);
4154                                 break;
4155                         case MINT_STELEM_I4:
4156                                 mono_array_set ((MonoArray *)o, gint32, aindex, sp [2].data.i);
4157                                 break;
4158                         case MINT_STELEM_I8:
4159                                 mono_array_set ((MonoArray *)o, gint64, aindex, sp [2].data.l);
4160                                 break;
4161                         case MINT_STELEM_R4:
4162                                 mono_array_set ((MonoArray *)o, float, aindex, sp [2].data.f);
4163                                 break;
4164                         case MINT_STELEM_R8:
4165                                 mono_array_set ((MonoArray *)o, double, aindex, sp [2].data.f);
4166                                 break;
4167                         case MINT_STELEM_REF: {
4168                                 MonoObject *isinst_obj = mono_object_isinst_checked (sp [2].data.p, mono_object_class (o)->element_class, &error);
4169                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4170                                 if (sp [2].data.p && !isinst_obj)
4171                                         THROW_EX (mono_get_exception_array_type_mismatch (), ip);
4172                                 mono_array_setref ((MonoArray *) o, aindex, sp [2].data.p);
4173                                 break;
4174                         }
4175                         case MINT_STELEM_VT: {
4176                                 MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
4177                                 i32 = READ32 (ip + 2);
4178                                 char *dst_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
4179
4180                                 stackval_to_data (&klass_vt->byval_arg, &sp [2], dst_addr, FALSE);
4181                                 vt_sp -= (i32 + 7) & ~7;
4182                                 ip += 3;
4183                                 break;
4184                         }
4185                         default:
4186                                 ves_abort();
4187                         }
4188
4189                         ++ip;
4190                         MINT_IN_BREAK;
4191                 }
4192                 MINT_IN_CASE(MINT_CONV_OVF_I4_U4)
4193                         if (sp [-1].data.i < 0)
4194                                 THROW_EX (mono_get_exception_overflow (), ip);
4195                         ++ip;
4196                         MINT_IN_BREAK;
4197                 MINT_IN_CASE(MINT_CONV_OVF_I4_I8)
4198                         if (sp [-1].data.l < MYGINT32_MIN || sp [-1].data.l > MYGINT32_MAX)
4199                                 THROW_EX (mono_get_exception_overflow (), ip);
4200                         sp [-1].data.i = (gint32) sp [-1].data.l;
4201                         ++ip;
4202                         MINT_IN_BREAK;
4203                 MINT_IN_CASE(MINT_CONV_OVF_I4_U8)
4204                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGINT32_MAX)
4205                                 THROW_EX (mono_get_exception_overflow (), ip);
4206                         sp [-1].data.i = (gint32) sp [-1].data.l;
4207                         ++ip;
4208                         MINT_IN_BREAK;
4209                 MINT_IN_CASE(MINT_CONV_OVF_I4_R8)
4210                         if (sp [-1].data.f < MYGINT32_MIN || sp [-1].data.f > MYGINT32_MAX)
4211                                 THROW_EX (mono_get_exception_overflow (), ip);
4212                         sp [-1].data.i = (gint32) sp [-1].data.f;
4213                         ++ip;
4214                         MINT_IN_BREAK;
4215                 MINT_IN_CASE(MINT_CONV_OVF_U4_I4)
4216                         if (sp [-1].data.i < 0)
4217                                 THROW_EX (mono_get_exception_overflow (), ip);
4218                         ++ip;
4219                         MINT_IN_BREAK;
4220                 MINT_IN_CASE(MINT_CONV_OVF_U4_I8)
4221                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGUINT32_MAX)
4222                                 THROW_EX (mono_get_exception_overflow (), ip);
4223                         sp [-1].data.i = (guint32) sp [-1].data.l;
4224                         ++ip;
4225                         MINT_IN_BREAK;
4226                 MINT_IN_CASE(MINT_CONV_OVF_U4_R8)
4227                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
4228                                 THROW_EX (mono_get_exception_overflow (), ip);
4229                         sp [-1].data.i = (guint32) sp [-1].data.f;
4230                         ++ip;
4231                         MINT_IN_BREAK;
4232                 MINT_IN_CASE(MINT_CONV_OVF_I2_I4)
4233                         if (sp [-1].data.i < -32768 || sp [-1].data.i > 32767)
4234                                 THROW_EX (mono_get_exception_overflow (), ip);
4235                         ++ip;
4236                         MINT_IN_BREAK;
4237                 MINT_IN_CASE(MINT_CONV_OVF_I2_I8)
4238                         if (sp [-1].data.l < -32768 || sp [-1].data.l > 32767)
4239                                 THROW_EX (mono_get_exception_overflow (), ip);
4240                         sp [-1].data.i = (gint16) sp [-1].data.l;
4241                         ++ip;
4242                         MINT_IN_BREAK;
4243                 MINT_IN_CASE(MINT_CONV_OVF_I2_R8)
4244                         if (sp [-1].data.f < -32768 || sp [-1].data.f > 32767)
4245                                 THROW_EX (mono_get_exception_overflow (), ip);
4246                         sp [-1].data.i = (gint16) sp [-1].data.f;
4247                         ++ip;
4248                         MINT_IN_BREAK;
4249                 MINT_IN_CASE(MINT_CONV_OVF_U2_I4)
4250                         if (sp [-1].data.i < 0 || sp [-1].data.i > 65535)
4251                                 THROW_EX (mono_get_exception_overflow (), ip);
4252                         ++ip;
4253                         MINT_IN_BREAK;
4254                 MINT_IN_CASE(MINT_CONV_OVF_U2_I8)
4255                         if (sp [-1].data.l < 0 || sp [-1].data.l > 65535)
4256                                 THROW_EX (mono_get_exception_overflow (), ip);
4257                         sp [-1].data.i = (guint16) sp [-1].data.l;
4258                         ++ip;
4259                         MINT_IN_BREAK;
4260                 MINT_IN_CASE(MINT_CONV_OVF_U2_R8)
4261                         if (sp [-1].data.f < 0 || sp [-1].data.f > 65535)
4262                                 THROW_EX (mono_get_exception_overflow (), ip);
4263                         sp [-1].data.i = (guint16) sp [-1].data.f;
4264                         ++ip;
4265                         MINT_IN_BREAK;
4266                 MINT_IN_CASE(MINT_CONV_OVF_I1_I4)
4267                         if (sp [-1].data.i < -128 || sp [-1].data.i > 127)
4268                                 THROW_EX (mono_get_exception_overflow (), ip);
4269                         ++ip;
4270                         MINT_IN_BREAK;
4271                 MINT_IN_CASE(MINT_CONV_OVF_I1_I8)
4272                         if (sp [-1].data.l < -128 || sp [-1].data.l > 127)
4273                                 THROW_EX (mono_get_exception_overflow (), ip);
4274                         sp [-1].data.i = (gint8) sp [-1].data.l;
4275                         ++ip;
4276                         MINT_IN_BREAK;
4277                 MINT_IN_CASE(MINT_CONV_OVF_I1_R8)
4278                         if (sp [-1].data.f < -128 || sp [-1].data.f > 127)
4279                                 THROW_EX (mono_get_exception_overflow (), ip);
4280                         sp [-1].data.i = (gint8) sp [-1].data.f;
4281                         ++ip;
4282                         MINT_IN_BREAK;
4283                 MINT_IN_CASE(MINT_CONV_OVF_U1_I4)
4284                         if (sp [-1].data.i < 0 || sp [-1].data.i > 255)
4285                                 THROW_EX (mono_get_exception_overflow (), ip);
4286                         ++ip;
4287                         MINT_IN_BREAK;
4288                 MINT_IN_CASE(MINT_CONV_OVF_U1_I8)
4289                         if (sp [-1].data.l < 0 || sp [-1].data.l > 255)
4290                                 THROW_EX (mono_get_exception_overflow (), ip);
4291                         sp [-1].data.i = (guint8) sp [-1].data.l;
4292                         ++ip;
4293                         MINT_IN_BREAK;
4294                 MINT_IN_CASE(MINT_CONV_OVF_U1_R8)
4295                         if (sp [-1].data.f < 0 || sp [-1].data.f > 255)
4296                                 THROW_EX (mono_get_exception_overflow (), ip);
4297                         sp [-1].data.i = (guint8) sp [-1].data.f;
4298                         ++ip;
4299                         MINT_IN_BREAK;
4300 #if 0
4301                 MINT_IN_CASE(MINT_LDELEM) 
4302                 MINT_IN_CASE(MINT_STELEM) 
4303                 MINT_IN_CASE(MINT_UNBOX_ANY) 
4304 #endif
4305                 MINT_IN_CASE(MINT_CKFINITE)
4306                         if (!isfinite(sp [-1].data.f))
4307                                 THROW_EX (mono_get_exception_arithmetic (), ip);
4308                         ++ip;
4309                         MINT_IN_BREAK;
4310                 MINT_IN_CASE(MINT_MKREFANY) {
4311                         c = rtm->data_items [*(guint16 *)(ip + 1)];
4312
4313                         /* The value address is on the stack */
4314                         gpointer addr = sp [-1].data.p;
4315                         /* Push the typedref value on the stack */
4316                         sp [-1].data.p = vt_sp;
4317                         vt_sp += sizeof (MonoTypedRef);
4318
4319                         MonoTypedRef *tref = sp [-1].data.p;
4320                         tref->klass = c;
4321                         tref->type = &c->byval_arg;
4322                         tref->value = addr;
4323
4324                         ip += 2;
4325                         MINT_IN_BREAK;
4326                 }
4327                 MINT_IN_CASE(MINT_REFANYTYPE) {
4328                         MonoTypedRef *tref = sp [-1].data.p;
4329                         MonoType *type = tref->type;
4330
4331                         vt_sp -= sizeof (MonoTypedRef);
4332                         sp [-1].data.p = vt_sp;
4333                         vt_sp += 8;
4334                         *(gpointer*)sp [-1].data.p = type;
4335                         ip ++;
4336                         MINT_IN_BREAK;
4337                 }
4338                 MINT_IN_CASE(MINT_REFANYVAL) {
4339                         MonoTypedRef *tref = sp [-1].data.p;
4340                         gpointer addr = tref->value;
4341
4342                         vt_sp -= sizeof (MonoTypedRef);
4343
4344                         sp [-1].data.p = addr;
4345                         ip ++;
4346                         MINT_IN_BREAK;
4347                 }
4348                 MINT_IN_CASE(MINT_LDTOKEN)
4349                         sp->data.p = vt_sp;
4350                         vt_sp += 8;
4351                         * (gpointer *)sp->data.p = rtm->data_items[*(guint16 *)(ip + 1)];
4352                         ip += 2;
4353                         ++sp;
4354                         MINT_IN_BREAK;
4355                 MINT_IN_CASE(MINT_ADD_OVF_I4)
4356                         if (CHECK_ADD_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
4357                                 THROW_EX (mono_get_exception_overflow (), ip);
4358                         BINOP(i, +);
4359                         MINT_IN_BREAK;
4360                 MINT_IN_CASE(MINT_ADD_OVF_I8)
4361                         if (CHECK_ADD_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
4362                                 THROW_EX (mono_get_exception_overflow (), ip);
4363                         BINOP(l, +);
4364                         MINT_IN_BREAK;
4365                 MINT_IN_CASE(MINT_ADD_OVF_UN_I4)
4366                         if (CHECK_ADD_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
4367                                 THROW_EX (mono_get_exception_overflow (), ip);
4368                         BINOP_CAST(i, +, guint32);
4369                         MINT_IN_BREAK;
4370                 MINT_IN_CASE(MINT_ADD_OVF_UN_I8)
4371                         if (CHECK_ADD_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
4372                                 THROW_EX (mono_get_exception_overflow (), ip);
4373                         BINOP_CAST(l, +, guint64);
4374                         MINT_IN_BREAK;
4375                 MINT_IN_CASE(MINT_MUL_OVF_I4)
4376                         if (CHECK_MUL_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
4377                                 THROW_EX (mono_get_exception_overflow (), ip);
4378                         BINOP(i, *);
4379                         MINT_IN_BREAK;
4380                 MINT_IN_CASE(MINT_MUL_OVF_I8)
4381                         if (CHECK_MUL_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
4382                                 THROW_EX (mono_get_exception_overflow (), ip);
4383                         BINOP(l, *);
4384                         MINT_IN_BREAK;
4385                 MINT_IN_CASE(MINT_MUL_OVF_UN_I4)
4386                         if (CHECK_MUL_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
4387                                 THROW_EX (mono_get_exception_overflow (), ip);
4388                         BINOP_CAST(i, *, guint32);
4389                         MINT_IN_BREAK;
4390                 MINT_IN_CASE(MINT_MUL_OVF_UN_I8)
4391                         if (CHECK_MUL_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
4392                                 THROW_EX (mono_get_exception_overflow (), ip);
4393                         BINOP_CAST(l, *, guint64);
4394                         MINT_IN_BREAK;
4395                 MINT_IN_CASE(MINT_SUB_OVF_I4)
4396                         if (CHECK_SUB_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
4397                                 THROW_EX (mono_get_exception_overflow (), ip);
4398                         BINOP(i, -);
4399                         MINT_IN_BREAK;
4400                 MINT_IN_CASE(MINT_SUB_OVF_I8)
4401                         if (CHECK_SUB_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
4402                                 THROW_EX (mono_get_exception_overflow (), ip);
4403                         BINOP(l, -);
4404                         MINT_IN_BREAK;
4405                 MINT_IN_CASE(MINT_SUB_OVF_UN_I4)
4406                         if (CHECK_SUB_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
4407                                 THROW_EX (mono_get_exception_overflow (), ip);
4408                         BINOP_CAST(i, -, guint32);
4409                         MINT_IN_BREAK;
4410                 MINT_IN_CASE(MINT_SUB_OVF_UN_I8)
4411                         if (CHECK_SUB_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
4412                                 THROW_EX (mono_get_exception_overflow (), ip);
4413                         BINOP_CAST(l, -, guint64);
4414                         MINT_IN_BREAK;
4415                 MINT_IN_CASE(MINT_ENDFINALLY)
4416                         ip ++;
4417                         int clause_index = *ip;
4418                         if (clause_index == exit_at_finally)
4419                                 goto exit_frame;
4420                         while (sp > frame->stack) {
4421                                 --sp;
4422                         }
4423                         if (finally_ips) {
4424                                 ip = finally_ips->data;
4425                                 finally_ips = g_slist_remove (finally_ips, ip);
4426                                 goto main_loop;
4427                         }
4428                         if (frame->ex)
4429                                 goto handle_fault;
4430                         ves_abort();
4431                         MINT_IN_BREAK;
4432                 MINT_IN_CASE(MINT_LEAVE) /* Fall through */
4433                 MINT_IN_CASE(MINT_LEAVE_S)
4434                         while (sp > frame->stack) {
4435                                 --sp;
4436                         }
4437                         frame->ip = ip;
4438                         if (*ip == MINT_LEAVE_S) {
4439                                 ip += (short) *(ip + 1);
4440                         } else {
4441                                 ip += (gint32) READ32 (ip + 1);
4442                         }
4443                         endfinally_ip = ip;
4444                         if (frame->ex_handler != NULL && MONO_OFFSET_IN_HANDLER(frame->ex_handler, frame->ip - rtm->code)) {
4445                                 frame->ex_handler = NULL;
4446                                 frame->ex = NULL;
4447                         }
4448                         goto handle_finally;
4449                         MINT_IN_BREAK;
4450                 MINT_IN_CASE(MINT_ICALL_V_V) 
4451                 MINT_IN_CASE(MINT_ICALL_V_P)
4452                 MINT_IN_CASE(MINT_ICALL_P_V) 
4453                 MINT_IN_CASE(MINT_ICALL_P_P)
4454                 MINT_IN_CASE(MINT_ICALL_PP_V)
4455                 MINT_IN_CASE(MINT_ICALL_PI_V)
4456                 MINT_IN_CASE(MINT_ICALL_PP_P)
4457                 MINT_IN_CASE(MINT_ICALL_PI_P)
4458                 MINT_IN_CASE(MINT_ICALL_PPP_V)
4459                 MINT_IN_CASE(MINT_ICALL_PPI_V)
4460                         sp = do_icall (context, *ip, sp, rtm->data_items [*(guint16 *)(ip + 1)]);
4461                         if (*mono_thread_interruption_request_flag ()) {
4462                                 MonoException *exc = mono_thread_interruption_checkpoint ();
4463                                 if (exc) {
4464                                         frame->ex = exc;
4465                                         context->search_for_handler = 1;
4466                                 }
4467                         }
4468                         if (frame->ex != NULL)
4469                                 goto handle_exception;
4470                         ip += 2;
4471                         MINT_IN_BREAK;
4472                 MINT_IN_CASE(MINT_MONO_LDPTR) 
4473                         sp->data.p = rtm->data_items [*(guint16 *)(ip + 1)];
4474                         ip += 2;
4475                         ++sp;
4476                         MINT_IN_BREAK;
4477                 MINT_IN_CASE(MINT_MONO_NEWOBJ)
4478                         sp->data.p = mono_object_new_checked (context->domain, rtm->data_items [*(guint16 *)(ip + 1)], &error);
4479                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4480                         ip += 2;
4481                         sp++;
4482                         MINT_IN_BREAK;
4483                 MINT_IN_CASE(MINT_MONO_FREE)
4484                         ++ip;
4485                         --sp;
4486                         g_error ("that doesn't seem right");
4487                         g_free (sp->data.p);
4488                         MINT_IN_BREAK;
4489                 MINT_IN_CASE(MINT_MONO_RETOBJ)
4490                         ++ip;
4491                         sp--;
4492                         stackval_from_data (mono_method_signature (frame->runtime_method->method)->ret, frame->retval, sp->data.p,
4493                              mono_method_signature (frame->runtime_method->method)->pinvoke);
4494                         if (sp > frame->stack)
4495                                 g_warning ("retobj: more values on stack: %d", sp-frame->stack);
4496                         goto exit_frame;
4497                 MINT_IN_CASE(MINT_MONO_TLS) {
4498                         MonoTlsKey key = *(gint32 *)(ip + 1);
4499                         sp->data.p = ((gpointer (*)()) mono_tls_get_tls_getter (key, FALSE)) ();
4500                         sp++;
4501                         ip += 3;
4502                         MINT_IN_BREAK;
4503                 }
4504                 MINT_IN_CASE(MINT_MONO_JIT_ATTACH) {
4505                         ++ip;
4506
4507                         context->original_domain = NULL;
4508                         MonoDomain *tls_domain = (MonoDomain *) ((gpointer (*)()) mono_tls_get_tls_getter (TLS_KEY_DOMAIN, FALSE)) ();
4509                         gpointer tls_jit = ((gpointer (*)()) mono_tls_get_tls_getter (TLS_KEY_DOMAIN, FALSE)) ();
4510
4511                         if (tls_domain != context->domain || !tls_jit)
4512                                 context->original_domain = mono_jit_thread_attach (context->domain);
4513                         MINT_IN_BREAK;
4514                 }
4515                 MINT_IN_CASE(MINT_MONO_JIT_DETACH)
4516                         ++ip;
4517                         mono_jit_set_domain (context->original_domain);
4518                         MINT_IN_BREAK;
4519
4520 #define RELOP(datamem, op) \
4521         --sp; \
4522         sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
4523         ++ip;
4524                 MINT_IN_CASE(MINT_CEQ_I4)
4525                         RELOP(i, ==);
4526                         MINT_IN_BREAK;
4527                 MINT_IN_CASE(MINT_CEQ0_I4)
4528                         sp [-1].data.i = (sp [-1].data.i == 0);
4529                         ++ip;
4530                         MINT_IN_BREAK;
4531                 MINT_IN_CASE(MINT_CEQ_I8)
4532                         RELOP(l, ==);
4533                         MINT_IN_BREAK;
4534                 MINT_IN_CASE(MINT_CEQ_R8)
4535                         --sp; 
4536                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4537                                 sp [-1].data.i = 0;
4538                         else
4539                                 sp [-1].data.i = sp [-1].data.f == sp [0].data.f;
4540                         ++ip;
4541                         MINT_IN_BREAK;
4542                 MINT_IN_CASE(MINT_CGT_I4)
4543                         RELOP(i, >);
4544                         MINT_IN_BREAK;
4545                 MINT_IN_CASE(MINT_CGT_I8)
4546                         RELOP(l, >);
4547                         MINT_IN_BREAK;
4548                 MINT_IN_CASE(MINT_CGT_R8)
4549                         --sp; 
4550                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4551                                 sp [-1].data.i = 0;
4552                         else
4553                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
4554                         ++ip;
4555                         MINT_IN_BREAK;
4556
4557 #define RELOP_CAST(datamem, op, type) \
4558         --sp; \
4559         sp [-1].data.i = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
4560         ++ip;
4561
4562                 MINT_IN_CASE(MINT_CGT_UN_I4)
4563                         RELOP_CAST(i, >, guint32);
4564                         MINT_IN_BREAK;
4565                 MINT_IN_CASE(MINT_CGT_UN_I8)
4566                         RELOP_CAST(l, >, guint64);
4567                         MINT_IN_BREAK;
4568                 MINT_IN_CASE(MINT_CGT_UN_R8)
4569                         --sp; 
4570                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4571                                 sp [-1].data.i = 1;
4572                         else
4573                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
4574                         ++ip;
4575                         MINT_IN_BREAK;
4576                 MINT_IN_CASE(MINT_CLT_I4)
4577                         RELOP(i, <);
4578                         MINT_IN_BREAK;
4579                 MINT_IN_CASE(MINT_CLT_I8)
4580                         RELOP(l, <);
4581                         MINT_IN_BREAK;
4582                 MINT_IN_CASE(MINT_CLT_R8)
4583                         --sp; 
4584                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4585                                 sp [-1].data.i = 0;
4586                         else
4587                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
4588                         ++ip;
4589                         MINT_IN_BREAK;
4590                 MINT_IN_CASE(MINT_CLT_UN_I4)
4591                         RELOP_CAST(i, <, guint32);
4592                         MINT_IN_BREAK;
4593                 MINT_IN_CASE(MINT_CLT_UN_I8)
4594                         RELOP_CAST(l, <, guint64);
4595                         MINT_IN_BREAK;
4596                 MINT_IN_CASE(MINT_CLT_UN_R8)
4597                         --sp; 
4598                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4599                                 sp [-1].data.i = 1;
4600                         else
4601                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
4602                         ++ip;
4603                         MINT_IN_BREAK;
4604                 MINT_IN_CASE(MINT_LDFTN) {
4605                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
4606                         ++sp;
4607                         ip += 2;
4608                         MINT_IN_BREAK;
4609                 }
4610                 MINT_IN_CASE(MINT_LDVIRTFTN) {
4611                         RuntimeMethod *m = rtm->data_items [* (guint16 *)(ip + 1)];
4612                         ip += 2;
4613                         --sp;
4614                         if (!sp->data.p)
4615                                 THROW_EX (mono_get_exception_null_reference (), ip - 2);
4616                                 
4617                         sp->data.p = get_virtual_method (context->domain, m, sp->data.p);
4618                         ++sp;
4619                         MINT_IN_BREAK;
4620                 }
4621
4622 #define LDARG(datamem, argtype) \
4623         sp->data.datamem = * (argtype *)(frame->args + * (guint16 *)(ip + 1)); \
4624         ip += 2; \
4625         ++sp; 
4626         
4627                 MINT_IN_CASE(MINT_LDARG_I1) LDARG(i, gint8); MINT_IN_BREAK;
4628                 MINT_IN_CASE(MINT_LDARG_U1) LDARG(i, guint8); MINT_IN_BREAK;
4629                 MINT_IN_CASE(MINT_LDARG_I2) LDARG(i, gint16); MINT_IN_BREAK;
4630                 MINT_IN_CASE(MINT_LDARG_U2) LDARG(i, guint16); MINT_IN_BREAK;
4631                 MINT_IN_CASE(MINT_LDARG_I4) LDARG(i, gint32); MINT_IN_BREAK;
4632                 MINT_IN_CASE(MINT_LDARG_I8) LDARG(l, gint64); MINT_IN_BREAK;
4633                 MINT_IN_CASE(MINT_LDARG_R4) LDARG(f, float); MINT_IN_BREAK;
4634                 MINT_IN_CASE(MINT_LDARG_R8) LDARG(f, double); MINT_IN_BREAK;
4635                 MINT_IN_CASE(MINT_LDARG_O) LDARG(p, gpointer); MINT_IN_BREAK;
4636                 MINT_IN_CASE(MINT_LDARG_P) LDARG(p, gpointer); MINT_IN_BREAK;
4637
4638                 MINT_IN_CASE(MINT_LDARG_VT)
4639                         sp->data.p = vt_sp;
4640                         i32 = READ32(ip + 2);
4641                         memcpy(sp->data.p, frame->args + * (guint16 *)(ip + 1), i32);
4642                         vt_sp += (i32 + 7) & ~7;
4643                         ip += 4;
4644                         ++sp;
4645                         MINT_IN_BREAK;
4646
4647 #define STARG(datamem, argtype) \
4648         --sp; \
4649         * (argtype *)(frame->args + * (guint16 *)(ip + 1)) = sp->data.datamem; \
4650         ip += 2; \
4651         
4652                 MINT_IN_CASE(MINT_STARG_I1) STARG(i, gint8); MINT_IN_BREAK;
4653                 MINT_IN_CASE(MINT_STARG_U1) STARG(i, guint8); MINT_IN_BREAK;
4654                 MINT_IN_CASE(MINT_STARG_I2) STARG(i, gint16); MINT_IN_BREAK;
4655                 MINT_IN_CASE(MINT_STARG_U2) STARG(i, guint16); MINT_IN_BREAK;
4656                 MINT_IN_CASE(MINT_STARG_I4) STARG(i, gint32); MINT_IN_BREAK;
4657                 MINT_IN_CASE(MINT_STARG_I8) STARG(l, gint64); MINT_IN_BREAK;
4658                 MINT_IN_CASE(MINT_STARG_R4) STARG(f, float); MINT_IN_BREAK;
4659                 MINT_IN_CASE(MINT_STARG_R8) STARG(f, double); MINT_IN_BREAK;
4660                 MINT_IN_CASE(MINT_STARG_O) STARG(p, gpointer); MINT_IN_BREAK;
4661                 MINT_IN_CASE(MINT_STARG_P) STARG(p, gpointer); MINT_IN_BREAK;
4662
4663                 MINT_IN_CASE(MINT_STARG_VT) 
4664                         i32 = READ32(ip + 2);
4665                         --sp;
4666                         memcpy(frame->args + * (guint16 *)(ip + 1), sp->data.p, i32);
4667                         vt_sp -= (i32 + 7) & ~7;
4668                         ip += 4;
4669                         MINT_IN_BREAK;
4670
4671 #define STINARG(datamem, argtype) \
4672         do { \
4673                 int n = * (guint16 *)(ip + 1); \
4674                 * (argtype *)(frame->args + rtm->arg_offsets [n]) = frame->stack_args [n].data.datamem; \
4675                 ip += 2; \
4676         } while (0)
4677         
4678                 MINT_IN_CASE(MINT_STINARG_I1) STINARG(i, gint8); MINT_IN_BREAK;
4679                 MINT_IN_CASE(MINT_STINARG_U1) STINARG(i, guint8); MINT_IN_BREAK;
4680                 MINT_IN_CASE(MINT_STINARG_I2) STINARG(i, gint16); MINT_IN_BREAK;
4681                 MINT_IN_CASE(MINT_STINARG_U2) STINARG(i, guint16); MINT_IN_BREAK;
4682                 MINT_IN_CASE(MINT_STINARG_I4) STINARG(i, gint32); MINT_IN_BREAK;
4683                 MINT_IN_CASE(MINT_STINARG_I8) STINARG(l, gint64); MINT_IN_BREAK;
4684                 MINT_IN_CASE(MINT_STINARG_R4) STINARG(f, float); MINT_IN_BREAK;
4685                 MINT_IN_CASE(MINT_STINARG_R8) STINARG(f, double); MINT_IN_BREAK;
4686                 MINT_IN_CASE(MINT_STINARG_O) STINARG(p, gpointer); MINT_IN_BREAK;
4687                 MINT_IN_CASE(MINT_STINARG_P) STINARG(p, gpointer); MINT_IN_BREAK;
4688
4689                 MINT_IN_CASE(MINT_STINARG_VT) {
4690                         int n = * (guint16 *)(ip + 1);
4691                         i32 = READ32(ip + 2);
4692                         memcpy (frame->args + rtm->arg_offsets [n], frame->stack_args [n].data.p, i32);
4693                         ip += 4;
4694                         MINT_IN_BREAK;
4695                 }
4696
4697                 MINT_IN_CASE(MINT_LDARGA)
4698                         sp->data.p = frame->args + * (guint16 *)(ip + 1);
4699                         ip += 2;
4700                         ++sp;
4701                         MINT_IN_BREAK;
4702
4703 #define LDLOC(datamem, argtype) \
4704         sp->data.datamem = * (argtype *)(locals + * (guint16 *)(ip + 1)); \
4705         ip += 2; \
4706         ++sp; 
4707         
4708                 MINT_IN_CASE(MINT_LDLOC_I1) LDLOC(i, gint8); MINT_IN_BREAK;
4709                 MINT_IN_CASE(MINT_LDLOC_U1) LDLOC(i, guint8); MINT_IN_BREAK;
4710                 MINT_IN_CASE(MINT_LDLOC_I2) LDLOC(i, gint16); MINT_IN_BREAK;
4711                 MINT_IN_CASE(MINT_LDLOC_U2) LDLOC(i, guint16); MINT_IN_BREAK;
4712                 MINT_IN_CASE(MINT_LDLOC_I4) LDLOC(i, gint32); MINT_IN_BREAK;
4713                 MINT_IN_CASE(MINT_LDLOC_I8) LDLOC(l, gint64); MINT_IN_BREAK;
4714                 MINT_IN_CASE(MINT_LDLOC_R4) LDLOC(f, float); MINT_IN_BREAK;
4715                 MINT_IN_CASE(MINT_LDLOC_R8) LDLOC(f, double); MINT_IN_BREAK;
4716                 MINT_IN_CASE(MINT_LDLOC_O) LDLOC(p, gpointer); MINT_IN_BREAK;
4717                 MINT_IN_CASE(MINT_LDLOC_P) LDLOC(p, gpointer); MINT_IN_BREAK;
4718
4719                 MINT_IN_CASE(MINT_LDLOC_VT)
4720                         sp->data.p = vt_sp;
4721                         i32 = READ32(ip + 2);
4722                         memcpy(sp->data.p, locals + * (guint16 *)(ip + 1), i32);
4723                         vt_sp += (i32 + 7) & ~7;
4724                         ip += 4;
4725                         ++sp;
4726                         MINT_IN_BREAK;
4727
4728                 MINT_IN_CASE(MINT_LDLOCA_S)
4729                         sp->data.p = locals + * (guint16 *)(ip + 1);
4730                         ip += 2;
4731                         ++sp;
4732                         MINT_IN_BREAK;
4733
4734 #define STLOC(datamem, argtype) \
4735         --sp; \
4736         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp->data.datamem; \
4737         ip += 2;
4738         
4739                 MINT_IN_CASE(MINT_STLOC_I1) STLOC(i, gint8); MINT_IN_BREAK;
4740                 MINT_IN_CASE(MINT_STLOC_U1) STLOC(i, guint8); MINT_IN_BREAK;
4741                 MINT_IN_CASE(MINT_STLOC_I2) STLOC(i, gint16); MINT_IN_BREAK;
4742                 MINT_IN_CASE(MINT_STLOC_U2) STLOC(i, guint16); MINT_IN_BREAK;
4743                 MINT_IN_CASE(MINT_STLOC_I4) STLOC(i, gint32); MINT_IN_BREAK;
4744                 MINT_IN_CASE(MINT_STLOC_I8) STLOC(l, gint64); MINT_IN_BREAK;
4745                 MINT_IN_CASE(MINT_STLOC_R4) STLOC(f, float); MINT_IN_BREAK;
4746                 MINT_IN_CASE(MINT_STLOC_R8) STLOC(f, double); MINT_IN_BREAK;
4747                 MINT_IN_CASE(MINT_STLOC_O) STLOC(p, gpointer); MINT_IN_BREAK;
4748                 MINT_IN_CASE(MINT_STLOC_P) STLOC(p, gpointer); MINT_IN_BREAK;
4749
4750 #define STLOC_NP(datamem, argtype) \
4751         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp [-1].data.datamem; \
4752         ip += 2;
4753
4754                 MINT_IN_CASE(MINT_STLOC_NP_I4) STLOC_NP(i, gint32); MINT_IN_BREAK;
4755                 MINT_IN_CASE(MINT_STLOC_NP_O) STLOC_NP(p, gpointer); MINT_IN_BREAK;
4756
4757                 MINT_IN_CASE(MINT_STLOC_VT)
4758                         i32 = READ32(ip + 2);
4759                         --sp;
4760                         memcpy(locals + * (guint16 *)(ip + 1), sp->data.p, i32);
4761                         vt_sp -= (i32 + 7) & ~7;
4762                         ip += 4;
4763                         MINT_IN_BREAK;
4764
4765                 MINT_IN_CASE(MINT_LOCALLOC) {
4766                         if (sp != frame->stack + 1) /*FIX?*/
4767                                 THROW_EX (mono_get_exception_execution_engine (NULL), ip);
4768
4769                         int len = sp [-1].data.i;
4770                         sp [-1].data.p = alloca (len);
4771                         MonoMethodHeader *header = mono_method_get_header_checked (frame->runtime_method->method, &error);
4772                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4773                         if (header && header->init_locals)
4774                                 memset (sp [-1].data.p, 0, len);
4775                         ++ip;
4776                         MINT_IN_BREAK;
4777                 }
4778                 MINT_IN_CASE(MINT_ENDFILTER)
4779                         /* top of stack is result of filter */
4780                         frame->retval = &sp [-1];
4781                         goto exit_frame;
4782                 MINT_IN_CASE(MINT_INITOBJ)
4783                         --sp;
4784                         memset (sp->data.vt, 0, READ32(ip + 1));
4785                         ip += 3;
4786                         MINT_IN_BREAK;
4787                 MINT_IN_CASE(MINT_CPBLK)
4788                         sp -= 3;
4789                         if (!sp [0].data.p || !sp [1].data.p)
4790                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
4791                         ++ip;
4792                         /* FIXME: value and size may be int64... */
4793                         memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
4794                         MINT_IN_BREAK;
4795 #if 0
4796                 MINT_IN_CASE(MINT_CONSTRAINED_) {
4797                         guint32 token;
4798                         /* FIXME: implement */
4799                         ++ip;
4800                         token = READ32 (ip);
4801                         ip += 2;
4802                         MINT_IN_BREAK;
4803                 }
4804 #endif
4805                 MINT_IN_CASE(MINT_INITBLK)
4806                         sp -= 3;
4807                         if (!sp [0].data.p)
4808                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
4809                         ++ip;
4810                         /* FIXME: value and size may be int64... */
4811                         memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
4812                         MINT_IN_BREAK;
4813 #if 0
4814                 MINT_IN_CASE(MINT_NO_)
4815                         /* FIXME: implement */
4816                         ip += 2;
4817                         MINT_IN_BREAK;
4818 #endif
4819                 MINT_IN_CASE(MINT_RETHROW)
4820                         /* 
4821                          * need to clarify what this should actually do:
4822                          * start the search from the last found handler in
4823                          * this method or continue in the caller or what.
4824                          * Also, do we need to run finally/fault handlers after a retrow?
4825                          * Well, this implementation will follow the usual search
4826                          * for an handler, considering the current ip as throw spot.
4827                          * We need to NULL frame->ex_handler for the later code to
4828                          * actually run the new found handler.
4829                          */
4830                         frame->ex_handler = NULL;
4831                         THROW_EX (frame->ex, ip - 1);
4832                         MINT_IN_BREAK;
4833                 MINT_IN_DEFAULT
4834                         g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip, mono_interp_opname[*ip], ip-rtm->code);
4835                         THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip);
4836                 }
4837         }
4838
4839         g_assert_not_reached ();
4840         /*
4841          * Exception handling code.
4842          * The exception object is stored in frame->ex.
4843          */
4844
4845         handle_exception:
4846         {
4847                 int i;
4848                 guint32 ip_offset;
4849                 MonoInvocation *inv;
4850                 MonoExceptionClause *clause;
4851                 /*char *message;*/
4852                 MonoObject *ex_obj;
4853
4854 #if DEBUG_INTERP
4855                 if (tracing)
4856                         g_print ("* Handling exception '%s' at IL_%04x\n", 
4857                                 frame->ex == NULL ? "** Unknown **" : mono_object_class (frame->ex)->name, 
4858                                 rtm == NULL ? 0 : frame->ip - rtm->code);
4859 #endif
4860                 if (die_on_exception)
4861                         goto die_on_ex;
4862
4863                 for (inv = frame; inv; inv = inv->parent) {
4864                         MonoMethod *method;
4865                         if (inv->runtime_method == NULL)
4866                                 continue;
4867                         method = inv->runtime_method->method;
4868                         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
4869                                 continue;
4870                         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
4871                                 continue;
4872                         if (inv->ip == NULL)
4873                                 continue;
4874                         ip_offset = inv->ip - inv->runtime_method->code;
4875                         inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one  - this one wins */
4876                         for (i = 0; i < inv->runtime_method->num_clauses; ++i) {
4877                                 clause = &inv->runtime_method->clauses [i];
4878 #if DEBUG_INTERP
4879                                 g_print ("* clause [%d]: %p\n", i, clause);
4880 #endif
4881                                 if (!MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
4882                                         continue;
4883                                 }
4884                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
4885 #if DEBUG_INTERP
4886                                         if (tracing)
4887                                                 g_print ("* Filter found at '%s'\n", method->name);
4888 #endif
4889                                         MonoInvocation dup_frame;
4890                                         stackval retval;
4891                                         memcpy (&dup_frame, inv, sizeof (MonoInvocation));
4892                                         dup_frame.retval = &retval;
4893                                         ves_exec_method_with_context (&dup_frame, context, inv->runtime_method->code + clause->data.filter_offset, frame->ex, -1);
4894                                         if (dup_frame.retval->data.i) {
4895 #if DEBUG_INTERP
4896                                                 if (tracing)
4897                                                         g_print ("* Matched Filter at '%s'\n", method->name);
4898 #endif
4899                                                 inv->ex_handler = clause;
4900                                                 goto handle_finally;
4901                                         }
4902                                 } else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
4903                                         MonoObject *isinst_obj = mono_object_isinst_checked ((MonoObject*)frame->ex, clause->data.catch_class, &error);
4904                                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4905                                         if (isinst_obj) {
4906                                                 /* 
4907                                                  * OK, we found an handler, now we need to execute the finally
4908                                                  * and fault blocks before branching to the handler code.
4909                                                  */
4910 #if DEBUG_INTERP
4911                                                 if (tracing)
4912                                                         g_print ("* Found handler at '%s'\n", method->name);
4913 #endif
4914                                                 inv->ex_handler = clause;
4915                                                 goto handle_finally;
4916                                         }
4917                                 }
4918                         }
4919                 }
4920                 /*
4921                  * If we get here, no handler was found: print a stack trace.
4922                  */
4923                 for (inv = frame; inv; inv = inv->parent) {
4924                         if (inv->invoke_trap)
4925                                 goto handle_finally;
4926                 }
4927 die_on_ex:
4928                 ex_obj = (MonoObject *) frame->ex;
4929                 mono_unhandled_exception (ex_obj);
4930                 MonoJitTlsData *jit_tls = (MonoJitTlsData *) mono_tls_get_jit_tls ();
4931                 jit_tls->abort_func (ex_obj);
4932                 g_assert_not_reached ();
4933         }
4934         handle_finally:
4935         {
4936                 int i;
4937                 guint32 ip_offset;
4938                 MonoExceptionClause *clause;
4939                 GSList *old_list = finally_ips;
4940                 MonoMethod *method = frame->runtime_method->method;
4941                 MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
4942                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4943                 
4944 #if DEBUG_INTERP
4945                 if (tracing)
4946                         g_print ("* Handle finally IL_%04x\n", endfinally_ip == NULL ? 0 : endfinally_ip - rtm->code);
4947 #endif
4948                 if (rtm == NULL || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
4949                                 || (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
4950                         goto exit_frame;
4951                 }
4952                 ip_offset = frame->ip - rtm->code;
4953
4954                 if (endfinally_ip != NULL)
4955                         finally_ips = g_slist_prepend(finally_ips, (void *)endfinally_ip);
4956                 for (i = 0; i < header->num_clauses; ++i)
4957                         if (frame->ex_handler == &rtm->clauses [i])
4958                                 break;
4959                 while (i > 0) {
4960                         --i;
4961                         clause = &rtm->clauses [i];
4962                         if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset) && (endfinally_ip == NULL || !(MONO_OFFSET_IN_CLAUSE (clause, endfinally_ip - rtm->code)))) {
4963                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
4964                                         ip = rtm->code + clause->handler_offset;
4965                                         finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
4966 #if DEBUG_INTERP
4967                                         if (tracing)
4968                                                 g_print ("* Found finally at IL_%04x with exception: %s\n", clause->handler_offset, frame->ex? "yes": "no");
4969 #endif
4970                                 }
4971                         }
4972                 }
4973
4974                 endfinally_ip = NULL;
4975
4976                 if (old_list != finally_ips && finally_ips) {
4977                         ip = finally_ips->data;
4978                         finally_ips = g_slist_remove (finally_ips, ip);
4979                         sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
4980                         goto main_loop;
4981                 }
4982
4983                 /*
4984                  * If an exception is set, we need to execute the fault handler, too,
4985                  * otherwise, we continue normally.
4986                  */
4987                 if (frame->ex)
4988                         goto handle_fault;
4989                 ves_abort();
4990         }
4991         handle_fault:
4992         {
4993                 int i;
4994                 guint32 ip_offset;
4995                 MonoExceptionClause *clause;
4996                 MonoMethod *method = frame->runtime_method->method;
4997                 MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
4998                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4999                 
5000 #if DEBUG_INTERP
5001                 if (tracing)
5002                         g_print ("* Handle fault\n");
5003 #endif
5004                 ip_offset = frame->ip - rtm->code;
5005                 for (i = 0; i < header->num_clauses; ++i) {
5006                         clause = &rtm->clauses [i];
5007                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
5008                                 ip = rtm->code + clause->handler_offset;
5009 #if DEBUG_INTERP
5010                                 if (tracing)
5011                                         g_print ("* Executing handler at IL_%04x\n", clause->handler_offset);
5012 #endif
5013                                 goto main_loop;
5014                         }
5015                 }
5016                 /*
5017                  * If the handler for the exception was found in this method, we jump
5018                  * to it right away, otherwise we return and let the caller run
5019                  * the finally, fault and catch blocks.
5020                  * This same code should be present in the endfault opcode, but it
5021                  * is corrently not assigned in the ECMA specs: LAMESPEC.
5022                  */
5023                 if (frame->ex_handler) {
5024 #if DEBUG_INTERP
5025                         if (tracing)
5026                                 g_print ("* Executing handler at IL_%04x\n", frame->ex_handler->handler_offset);
5027 #endif
5028                         ip = rtm->code + frame->ex_handler->handler_offset;
5029                         sp = frame->stack;
5030                         vt_sp = (unsigned char *) sp + rtm->stack_size;
5031                         sp->data.p = frame->ex;
5032                         ++sp;
5033                         goto main_loop;
5034                 }
5035                 goto exit_frame;
5036         }
5037 exit_frame:
5038         DEBUG_LEAVE ();
5039 }
5040
5041 void
5042 ves_exec_method (MonoInvocation *frame)
5043 {
5044         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
5045         ThreadContext context_struct;
5046         MonoError error;
5047         jmp_buf env;
5048
5049         frame->ex = NULL;
5050
5051         if (setjmp(env)) {
5052                 mono_unhandled_exception ((MonoObject*)frame->ex);
5053                 return;
5054         }
5055         if (context == NULL) {
5056                 context = &context_struct;
5057                 context_struct.domain = mono_domain_get ();
5058                 context_struct.base_frame = frame;
5059                 context_struct.current_frame = NULL;
5060                 context_struct.env_frame = frame;
5061                 context_struct.current_env = &env;
5062                 context_struct.search_for_handler = 0;
5063                 context_struct.managed_code = 0;
5064                 mono_native_tls_set_value (thread_context_id, context);
5065         }
5066         frame->ip = NULL;
5067         frame->parent = context->current_frame;
5068         frame->runtime_method = mono_interp_get_runtime_method (context->domain, frame->method, &error);
5069         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
5070         context->managed_code = 1;
5071         ves_exec_method_with_context (frame, context, NULL, NULL, -1);
5072         context->managed_code = 0;
5073         if (frame->ex) {
5074                 if (context != &context_struct && context->current_env) {
5075                         context->env_frame->ex = frame->ex;
5076                         longjmp (*context->current_env, 1);
5077                 }
5078                 else
5079                         mono_unhandled_exception ((MonoObject*)frame->ex);
5080         }
5081         if (context->base_frame == frame)
5082                 mono_native_tls_set_value (thread_context_id, NULL);
5083         else
5084                 context->current_frame = frame->parent;
5085 }
5086
5087 void
5088 mono_interp_parse_options (const char *options)
5089 {
5090         char **args, **ptr;
5091
5092         args = g_strsplit (options, ",", -1);
5093         for (ptr = args; ptr && *ptr; ptr ++) {
5094                 char *arg = *ptr;
5095
5096                 if (strncmp (arg, "jit=", 4) == 0)
5097                         jit_classes = g_slist_prepend (jit_classes, arg + 4);
5098         }
5099 }
5100
5101 void
5102 mono_interp_init ()
5103 {
5104         mono_native_tls_alloc (&thread_context_id, NULL);
5105         mono_native_tls_set_value (thread_context_id, NULL);
5106
5107         mono_interp_transform_init ();
5108 }
5109
5110 typedef int (*TestMethod) (void);
5111
5112 static void
5113 interp_regression_step (MonoImage *image, int verbose, int *total_run, int *total, GTimer *timer, MonoDomain *domain)
5114 {
5115         int result, expected, failed, cfailed, run;
5116         double elapsed, transform_time;
5117         int i;
5118         MonoObject *result_obj;
5119         static gboolean filter_method_init = FALSE;
5120         static const char *filter_method = NULL;
5121
5122         g_print ("Test run: image=%s\n", mono_image_get_filename (image));
5123         cfailed = failed = run = 0;
5124         transform_time = elapsed = 0.0;
5125
5126         g_timer_start (timer);
5127         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
5128                 MonoObject *exc = NULL;
5129                 MonoError error;
5130                 MonoMethod *method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
5131                 if (!method) {
5132                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
5133                         continue;
5134                 }
5135
5136                 if (!filter_method_init) {
5137                         filter_method = g_getenv ("INTERP_FILTER_METHOD");
5138                         filter_method_init = TRUE;
5139                 }
5140                 gboolean filter = FALSE;
5141                 if (filter_method) {
5142                         const char *name = filter_method;
5143
5144                         if ((strchr (name, '.') > name) || strchr (name, ':')) {
5145                                 MonoMethodDesc *desc = mono_method_desc_new (name, TRUE);
5146                                 filter = mono_method_desc_full_match (desc, method);
5147                                 mono_method_desc_free (desc);
5148                         } else {
5149                                 filter = strcmp (method->name, name) == 0;
5150                         }
5151                 } else { /* no filter, check for `Category' attribute on method */
5152                         filter = TRUE;
5153                         MonoCustomAttrInfo* ainfo = mono_custom_attrs_from_method_checked (method, &error);
5154                         mono_error_cleanup (&error);
5155
5156                         if (ainfo) {
5157                                 int j;
5158                                 for (j = 0; j < ainfo->num_attrs && filter; ++j) {
5159                                         MonoCustomAttrEntry *centry = &ainfo->attrs [j];
5160                                         if (centry->ctor == NULL)
5161                                                 continue;
5162
5163                                         MonoClass *klass = centry->ctor->klass;
5164                                         if (strcmp (klass->name, "CategoryAttribute"))
5165                                                 continue;
5166
5167                                         MonoObject *obj = mono_custom_attrs_get_attr_checked (ainfo, klass, &error);
5168                                         /* FIXME: there is an ordering problem if there're multiple attributes, do this instead:
5169                                          * MonoObject *obj = create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, &error); */
5170                                         mono_error_cleanup (&error);
5171                                         MonoMethod *getter = mono_class_get_method_from_name (klass, "get_Category", -1);
5172                                         MonoObject *str = mono_interp_runtime_invoke (getter, obj, NULL, &exc, &error);
5173                                         mono_error_cleanup (&error);
5174                                         char *utf8_str = mono_string_to_utf8_checked ((MonoString *) str, &error);
5175                                         mono_error_cleanup (&error);
5176                                         if (!strcmp (utf8_str, "!INTERPRETER")) {
5177                                                 g_print ("skip %s...\n", method->name);
5178                                                 filter = FALSE;
5179                                         }
5180                                 }
5181                         }
5182                 }
5183                 if (strncmp (method->name, "test_", 5) == 0 && filter) {
5184                         MonoError interp_error;
5185                         MonoObject *exc = NULL;
5186
5187                         result_obj = mono_interp_runtime_invoke (method, NULL, NULL, &exc, &interp_error);
5188                         if (!mono_error_ok (&interp_error)) {
5189                                 cfailed++;
5190                                 g_print ("Test '%s' execution failed.\n", method->name);
5191                         } else if (exc != NULL) {
5192                                 g_print ("Exception in Test '%s' occured:\n", method->name);
5193                                 mono_object_describe (exc);
5194                                 run++;
5195                                 failed++;
5196                         } else {
5197                                 result = *(gint32 *) mono_object_unbox (result_obj);
5198                                 expected = atoi (method->name + 5);  // FIXME: oh no.
5199                                 run++;
5200
5201                                 if (result != expected) {
5202                                         failed++;
5203                                         g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
5204                                 }
5205                         }
5206                 }
5207         }
5208         g_timer_stop (timer);
5209         elapsed = g_timer_elapsed (timer, NULL);
5210         if (failed > 0 || cfailed > 0){
5211                 g_print ("Results: total tests: %d, failed: %d, cfailed: %d (pass: %.2f%%)\n",
5212                                 run, failed, cfailed, 100.0*(run-failed-cfailed)/run);
5213         } else {
5214                 g_print ("Results: total tests: %d, all pass \n",  run);
5215         }
5216
5217         g_print ("Elapsed time: %f secs (%f, %f)\n\n", elapsed,
5218                         elapsed - transform_time, transform_time);
5219         *total += failed + cfailed;
5220         *total_run += run;
5221 }
5222
5223 static int
5224 interp_regression (MonoImage *image, int verbose, int *total_run)
5225 {
5226         MonoMethod *method;
5227         GTimer *timer = g_timer_new ();
5228         MonoDomain *domain = mono_domain_get ();
5229         guint32 i;
5230         int total;
5231
5232         /* load the metadata */
5233         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
5234                 MonoError error;
5235                 method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
5236                 if (!method) {
5237                         mono_error_cleanup (&error);
5238                         continue;
5239                 }
5240                 mono_class_init (method->klass);
5241         }
5242
5243         total = 0;
5244         *total_run = 0;
5245         interp_regression_step (image, verbose, total_run, &total, timer, domain);
5246
5247         g_timer_destroy (timer);
5248         return total;
5249 }
5250
5251 int
5252 mono_interp_regression_list (int verbose, int count, char *images [])
5253 {
5254         int i, total, total_run, run;
5255         
5256         total_run = total = 0;
5257         for (i = 0; i < count; ++i) {
5258                 MonoAssembly *ass = mono_assembly_open_predicate (images [i], FALSE, FALSE, NULL, NULL, NULL);
5259                 if (!ass) {
5260                         g_warning ("failed to load assembly: %s", images [i]);
5261                         continue;
5262                 }
5263                 total += interp_regression (mono_assembly_get_image (ass), verbose, &run);
5264                 total_run += run;
5265         }
5266         if (total > 0) {
5267                 g_print ("Overall results: tests: %d, failed: %d (pass: %.2f%%)\n", total_run, total, 100.0*(total_run-total)/total_run);
5268         } else {
5269                 g_print ("Overall results: tests: %d, 100%% pass\n", total_run);
5270         }
5271         
5272         return total;
5273 }
5274
5275 /*
5276  * mono_interp_set_resume_state:
5277  *
5278  *   Set the state the interpeter will continue to execute from after execution returns to the interpreter.
5279  */
5280 void
5281 mono_interp_set_resume_state (MonoException *ex, StackFrameInfo *frame, gpointer handler_ip)
5282 {
5283         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
5284
5285         context->has_resume_state = TRUE;
5286         context->handler_frame = frame->interp_frame;
5287         /* This is on the stack, so it doesn't need a wbarrier */
5288         context->handler_frame->ex = ex;
5289         context->handler_ip = handler_ip;
5290 }
5291
5292 /*
5293  * mono_interp_run_finally:
5294  *
5295  *   Run the finally clause identified by CLAUSE_INDEX in the intepreter frame given by
5296  * frame->interp_frame.
5297  */
5298 void
5299 mono_interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip)
5300 {
5301        MonoInvocation *iframe = frame->interp_frame;
5302        ThreadContext *context = mono_native_tls_get_value (thread_context_id);
5303
5304        ves_exec_method_with_context (iframe, context, handler_ip, NULL, clause_index);
5305 }
5306
5307 typedef struct {
5308         MonoInvocation *current;
5309 } StackIter;
5310
5311 /*
5312  * mono_interp_frame_iter_init:
5313  *
5314  *   Initialize an iterator for iterating through interpreted frames.
5315  */
5316 void
5317 mono_interp_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_data)
5318 {
5319         StackIter *stack_iter = (StackIter*)iter;
5320
5321         stack_iter->current = (MonoInvocation*)interp_exit_data;
5322 }
5323
5324 gboolean
5325 mono_interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame)
5326 {
5327         StackIter *stack_iter = (StackIter*)iter;
5328         MonoInvocation *iframe = stack_iter->current;
5329
5330         memset (frame, 0, sizeof (StackFrameInfo));
5331         /* pinvoke frames doesn't have runtime_method set */
5332         while (iframe && !iframe->runtime_method)
5333                 iframe = iframe->parent;
5334         if (!iframe)
5335                 return FALSE;
5336
5337         frame->type = FRAME_TYPE_INTERP;
5338         frame->interp_frame = iframe;
5339         frame->method = iframe->runtime_method->method;
5340         frame->actual_method = frame->method;
5341         /* This is the offset in the interpreter IR */
5342         frame->native_offset = iframe->ip - iframe->runtime_method->code;
5343         frame->ji = iframe->runtime_method->jinfo;
5344
5345         stack_iter->current = iframe->parent;
5346
5347         return TRUE;
5348 }