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