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