Merge pull request #5317 from alexrp/master
[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
2440                         if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL)
2441                                 MONO_PROFILER_RAISE (method_tail_call, (frame->imethod->method, new_method->method));
2442
2443                         if (!new_method->transformed) {
2444                                 frame->ip = ip;
2445                                 frame->ex = mono_interp_transform_method (new_method, context);
2446                                 if (frame->ex)
2447                                         goto exit_frame;
2448                         }
2449                         ip += 2;
2450                         if (new_method->alloca_size > rtm->alloca_size)
2451                                 g_error ("MINT_JMP to method which needs more stack space (%d > %d)", new_method->alloca_size, rtm->alloca_size); 
2452                         rtm = frame->imethod = new_method;
2453                         vt_sp = (unsigned char *) sp + rtm->stack_size;
2454 #if DEBUG_INTERP
2455                         vtalloc = vt_sp;
2456 #endif
2457                         locals = vt_sp + rtm->vt_stack_size;
2458                         frame->locals = locals;
2459                         ip = rtm->new_body_start; /* bypass storing input args from callers frame */
2460                         MINT_IN_BREAK;
2461                 }
2462                 MINT_IN_CASE(MINT_CALLI) {
2463                         MonoMethodSignature *csignature;
2464                         stackval *endsp = sp;
2465
2466                         frame->ip = ip;
2467                         
2468                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
2469                         ip += 2;
2470                         --sp;
2471                         --endsp;
2472                         child_frame.imethod = sp->data.p;
2473
2474                         sp->data.p = vt_sp;
2475                         child_frame.retval = sp;
2476                         /* decrement by the actual number of args */
2477                         sp -= csignature->param_count;
2478                         if (csignature->hasthis)
2479                                 --sp;
2480                         child_frame.stack_args = sp;
2481
2482 #ifndef DISABLE_REMOTING
2483                         /* `this' can be NULL for string:.ctor */
2484                         if (csignature->hasthis && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
2485                                 child_frame.imethod = mono_interp_get_imethod (rtm->domain, mono_marshal_get_remoting_invoke (child_frame.imethod->method), &error);
2486                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2487                         } else
2488 #endif
2489                         if (child_frame.imethod->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2490                                 child_frame.imethod = mono_interp_get_imethod (rtm->domain, mono_marshal_get_native_wrapper (child_frame.imethod->method, FALSE, FALSE), &error);
2491                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2492                         }
2493
2494                         if (csignature->hasthis) {
2495                                 MonoObject *this_arg = sp->data.p;
2496
2497                                 if (this_arg->vtable->klass->valuetype) {
2498                                         gpointer *unboxed = mono_object_unbox (this_arg);
2499                                         sp [0].data.p = unboxed;
2500                                 }
2501                         }
2502
2503                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2504
2505                         context->current_frame = frame;
2506
2507                         if (context->has_resume_state) {
2508                                 if (frame == context->handler_frame)
2509                                         SET_RESUME_STATE (context);
2510                                 else
2511                                         goto exit_frame;
2512                         }
2513
2514                         if (child_frame.ex) {
2515                                 /*
2516                                  * An exception occurred, need to run finally, fault and catch handlers..
2517                                  */
2518                                 frame->ex = child_frame.ex;
2519                                 goto handle_finally;
2520                         }
2521
2522                         /* need to handle typedbyref ... */
2523                         if (csignature->ret->type != MONO_TYPE_VOID) {
2524                                 *sp = *endsp;
2525                                 sp++;
2526                         }
2527                         MINT_IN_BREAK;
2528                 }
2529                 MINT_IN_CASE(MINT_CALLI_NAT) {
2530                         MonoMethodSignature *csignature;
2531                         stackval *endsp = sp;
2532                         unsigned char *code = NULL;
2533
2534                         frame->ip = ip;
2535                         
2536                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
2537                         ip += 2;
2538                         --sp;
2539                         --endsp;
2540                         code = sp->data.p;
2541                         child_frame.imethod = NULL;
2542
2543                         sp->data.p = vt_sp;
2544                         child_frame.retval = sp;
2545                         /* decrement by the actual number of args */
2546                         sp -= csignature->param_count;
2547                         if (csignature->hasthis)
2548                                 --sp;
2549                         child_frame.stack_args = sp;
2550                         ves_pinvoke_method (&child_frame, csignature, (MonoFuncV) code, FALSE, context);
2551
2552                         context->current_frame = frame;
2553
2554                         if (context->has_resume_state) {
2555                                 if (frame == context->handler_frame)
2556                                         SET_RESUME_STATE (context);
2557                                 else
2558                                         goto exit_frame;
2559                         }
2560
2561                         if (child_frame.ex) {
2562                                 /*
2563                                  * An exception occurred, need to run finally, fault and catch handlers..
2564                                  */
2565                                 frame->ex = child_frame.ex;
2566                                 if (context->search_for_handler) {
2567                                         context->search_for_handler = 0;
2568                                         goto handle_exception;
2569                                 }
2570                                 goto handle_finally;
2571                         }
2572
2573                         /* need to handle typedbyref ... */
2574                         if (csignature->ret->type != MONO_TYPE_VOID) {
2575                                 *sp = *endsp;
2576                                 sp++;
2577                         }
2578                         MINT_IN_BREAK;
2579                 }
2580                 MINT_IN_CASE(MINT_CALL) {
2581                         stackval *endsp = sp;
2582
2583                         frame->ip = ip;
2584                         
2585                         child_frame.imethod = rtm->data_items [* (guint16 *)(ip + 1)];
2586                         ip += 2;
2587                         sp->data.p = vt_sp;
2588                         child_frame.retval = sp;
2589                         /* decrement by the actual number of args */
2590                         sp -= child_frame.imethod->param_count;
2591                         if (child_frame.imethod->hasthis)
2592                                 --sp;
2593                         child_frame.stack_args = sp;
2594
2595 #ifndef DISABLE_REMOTING
2596                         /* `this' can be NULL for string:.ctor */
2597                         if (child_frame.imethod->hasthis && !child_frame.imethod->method->klass->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
2598                                 child_frame.imethod = mono_interp_get_imethod (rtm->domain, mono_marshal_get_remoting_invoke (child_frame.imethod->method), &error);
2599                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2600                         }
2601 #endif
2602
2603                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2604
2605                         context->current_frame = frame;
2606
2607                         if (context->has_resume_state) {
2608                                 if (frame == context->handler_frame)
2609                                         SET_RESUME_STATE (context);
2610                                 else
2611                                         goto exit_frame;
2612                         }
2613
2614                         if (child_frame.ex) {
2615                                 /*
2616                                  * An exception occurred, need to run finally, fault and catch handlers..
2617                                  */
2618                                 frame->ex = child_frame.ex;
2619                                 goto handle_exception;;
2620                         }
2621
2622                         /* need to handle typedbyref ... */
2623                         *sp = *endsp;
2624                         sp++;
2625                         MINT_IN_BREAK;
2626                 }
2627                 MINT_IN_CASE(MINT_VCALL) {
2628                         frame->ip = ip;
2629                         
2630                         child_frame.imethod = rtm->data_items [* (guint16 *)(ip + 1)];
2631                         ip += 2;
2632
2633                         sp->data.p = vt_sp;
2634                         child_frame.retval = sp;
2635                         /* decrement by the actual number of args */
2636                         sp -= child_frame.imethod->param_count;
2637                         if (child_frame.imethod->hasthis) {
2638                                 --sp;
2639                                 MonoObject *this_arg = sp->data.p;
2640                                 if (!this_arg)
2641                                         THROW_EX (mono_get_exception_null_reference(), ip - 2);
2642                         }
2643                         child_frame.stack_args = sp;
2644
2645 #ifndef DISABLE_REMOTING
2646                         if (child_frame.imethod->hasthis && !child_frame.imethod->method->klass->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
2647                                 child_frame.imethod = mono_interp_get_imethod (rtm->domain, mono_marshal_get_remoting_invoke (child_frame.imethod->method), &error);
2648                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2649                         }
2650 #endif
2651
2652                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2653
2654                         context->current_frame = frame;
2655
2656                         if (context->has_resume_state) {
2657                                 if (frame == context->handler_frame)
2658                                         SET_RESUME_STATE (context);
2659                                 else
2660                                         goto exit_frame;
2661                         }
2662
2663                         if (child_frame.ex) {
2664                                 /*
2665                                  * An exception occurred, need to run finally, fault and catch handlers..
2666                                  */
2667                                 frame->ex = child_frame.ex;
2668                                 goto handle_finally;
2669                         }
2670                         MINT_IN_BREAK;
2671                 }
2672
2673                 MINT_IN_CASE(MINT_JIT_CALL) {
2674                         InterpMethod *rmethod = rtm->data_items [* (guint16 *)(ip + 1)];
2675                         frame->ip = ip;
2676                         ip += 2;
2677                         sp = do_jit_call (sp, vt_sp, context, frame, rmethod);
2678
2679                         if (context->has_resume_state) {
2680                                 /*
2681                                  * If this bit is set, it means the call has thrown the exception, and we
2682                                  * reached this point because the EH code in mono_handle_exception ()
2683                                  * unwound all the JITted frames below us. mono_interp_set_resume_state ()
2684                                  * has set the fields in context to indicate where we have to resume execution.
2685                                  */
2686                                 if (frame == context->handler_frame)
2687                                         SET_RESUME_STATE (context);
2688                                 else
2689                                         goto exit_frame;
2690                         }
2691                         if (rmethod->rtype->type != MONO_TYPE_VOID)
2692                                 sp++;
2693
2694                         MINT_IN_BREAK;
2695                 }
2696
2697                 MINT_IN_CASE(MINT_CALLVIRT) {
2698                         stackval *endsp = sp;
2699                         MonoObject *this_arg;
2700                         guint32 token;
2701
2702                         frame->ip = ip;
2703                         
2704                         token = * (unsigned short *)(ip + 1);
2705                         ip += 2;
2706                         child_frame.imethod = rtm->data_items [token];
2707                         sp->data.p = vt_sp;
2708                         child_frame.retval = sp;
2709
2710                         /* decrement by the actual number of args */
2711                         sp -= child_frame.imethod->param_count + 1;
2712                         child_frame.stack_args = sp;
2713                         this_arg = sp->data.p;
2714                         if (!this_arg)
2715                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
2716                         child_frame.imethod = get_virtual_method (child_frame.imethod, this_arg);
2717
2718                         MonoClass *this_class = this_arg->vtable->klass;
2719                         if (this_class->valuetype && child_frame.imethod->method->klass->valuetype) {
2720                                 /* unbox */
2721                                 gpointer *unboxed = mono_object_unbox (this_arg);
2722                                 sp [0].data.p = unboxed;
2723                         }
2724
2725                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2726
2727                         context->current_frame = frame;
2728
2729                         if (context->has_resume_state) {
2730                                 if (frame == context->handler_frame)
2731                                         SET_RESUME_STATE (context);
2732                                 else
2733                                         goto exit_frame;
2734                         }
2735
2736                         if (child_frame.ex) {
2737                                 /*
2738                                  * An exception occurred, need to run finally, fault and catch handlers..
2739                                  */
2740                                 frame->ex = child_frame.ex;
2741                                 if (context->search_for_handler) {
2742                                         context->search_for_handler = 0;
2743                                         goto handle_exception;
2744                                 }
2745                                 goto handle_finally;
2746                         }
2747
2748                         /* need to handle typedbyref ... */
2749                         *sp = *endsp;
2750                         sp++;
2751                         MINT_IN_BREAK;
2752                 }
2753                 MINT_IN_CASE(MINT_VCALLVIRT) {
2754                         MonoObject *this_arg;
2755                         guint32 token;
2756
2757                         frame->ip = ip;
2758                         
2759                         token = * (unsigned short *)(ip + 1);
2760                         ip += 2;
2761                         child_frame.imethod = rtm->data_items [token];
2762                         sp->data.p = vt_sp;
2763                         child_frame.retval = sp;
2764
2765                         /* decrement by the actual number of args */
2766                         sp -= child_frame.imethod->param_count + 1;
2767                         child_frame.stack_args = sp;
2768                         this_arg = sp->data.p;
2769                         if (!this_arg)
2770                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
2771                         child_frame.imethod = get_virtual_method (child_frame.imethod, this_arg);
2772
2773                         MonoClass *this_class = this_arg->vtable->klass;
2774                         if (this_class->valuetype && child_frame.imethod->method->klass->valuetype) {
2775                                 gpointer *unboxed = mono_object_unbox (this_arg);
2776                                 sp [0].data.p = unboxed;
2777                         }
2778
2779                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
2780
2781                         context->current_frame = frame;
2782
2783                         if (context->has_resume_state) {
2784                                 if (frame == context->handler_frame)
2785                                         SET_RESUME_STATE (context);
2786                                 else
2787                                         goto exit_frame;
2788                         }
2789
2790                         if (child_frame.ex) {
2791                                 /*
2792                                  * An exception occurred, need to run finally, fault and catch handlers..
2793                                  */
2794                                 frame->ex = child_frame.ex;
2795                                 if (context->search_for_handler) {
2796                                         context->search_for_handler = 0;
2797                                         goto handle_exception;
2798                                 }
2799                                 goto handle_finally;
2800                         }
2801                         MINT_IN_BREAK;
2802                 }
2803                 MINT_IN_CASE(MINT_CALLRUN)
2804                         ves_imethod (frame, context);
2805                         if (frame->ex) {
2806                                 rtm = NULL;
2807                                 goto handle_exception;
2808                         }
2809                         goto exit_frame;
2810                 MINT_IN_CASE(MINT_RET)
2811                         --sp;
2812                         *frame->retval = *sp;
2813                         if (sp > frame->stack)
2814                                 g_warning ("ret: more values on stack: %d", sp-frame->stack);
2815                         goto exit_frame;
2816                 MINT_IN_CASE(MINT_RET_VOID)
2817                         if (sp > frame->stack)
2818                                 g_warning ("ret.void: more values on stack: %d %s", sp-frame->stack, mono_method_full_name (frame->imethod->method, TRUE));
2819                         goto exit_frame;
2820                 MINT_IN_CASE(MINT_RET_VT)
2821                         i32 = READ32(ip + 1);
2822                         --sp;
2823                         memcpy(frame->retval->data.p, sp->data.p, i32);
2824                         if (sp > frame->stack)
2825                                 g_warning ("ret.vt: more values on stack: %d", sp-frame->stack);
2826                         goto exit_frame;
2827                 MINT_IN_CASE(MINT_BR_S)
2828                         ip += (short) *(ip + 1);
2829                         MINT_IN_BREAK;
2830                 MINT_IN_CASE(MINT_BR)
2831                         ip += (gint32) READ32(ip + 1);
2832                         MINT_IN_BREAK;
2833 #define ZEROP_S(datamem, op) \
2834         --sp; \
2835         if (sp->data.datamem op 0) \
2836                 ip += * (gint16 *)(ip + 1); \
2837         else \
2838                 ip += 2;
2839
2840 #define ZEROP(datamem, op) \
2841         --sp; \
2842         if (sp->data.datamem op 0) \
2843                 ip += READ32(ip + 1); \
2844         else \
2845                 ip += 3;
2846
2847                 MINT_IN_CASE(MINT_BRFALSE_I4_S)
2848                         ZEROP_S(i, ==);
2849                         MINT_IN_BREAK;
2850                 MINT_IN_CASE(MINT_BRFALSE_I8_S)
2851                         ZEROP_S(l, ==);
2852                         MINT_IN_BREAK;
2853                 MINT_IN_CASE(MINT_BRFALSE_R8_S)
2854                         ZEROP_S(f, ==);
2855                         MINT_IN_BREAK;
2856                 MINT_IN_CASE(MINT_BRFALSE_I4)
2857                         ZEROP(i, ==);
2858                         MINT_IN_BREAK;
2859                 MINT_IN_CASE(MINT_BRFALSE_I8)
2860                         ZEROP(l, ==);
2861                         MINT_IN_BREAK;
2862                 MINT_IN_CASE(MINT_BRFALSE_R8)
2863                         ZEROP_S(f, ==);
2864                         MINT_IN_BREAK;
2865                 MINT_IN_CASE(MINT_BRTRUE_I4_S)
2866                         ZEROP_S(i, !=);
2867                         MINT_IN_BREAK;
2868                 MINT_IN_CASE(MINT_BRTRUE_I8_S)
2869                         ZEROP_S(l, !=);
2870                         MINT_IN_BREAK;
2871                 MINT_IN_CASE(MINT_BRTRUE_R8_S)
2872                         ZEROP_S(f, !=);
2873                         MINT_IN_BREAK;
2874                 MINT_IN_CASE(MINT_BRTRUE_I4)
2875                         ZEROP(i, !=);
2876                         MINT_IN_BREAK;
2877                 MINT_IN_CASE(MINT_BRTRUE_I8)
2878                         ZEROP(l, !=);
2879                         MINT_IN_BREAK;
2880                 MINT_IN_CASE(MINT_BRTRUE_R8)
2881                         ZEROP(f, !=);
2882                         MINT_IN_BREAK;
2883 #define CONDBR_S(cond) \
2884         sp -= 2; \
2885         if (cond) \
2886                 ip += * (gint16 *)(ip + 1); \
2887         else \
2888                 ip += 2;
2889 #define BRELOP_S(datamem, op) \
2890         CONDBR_S(sp[0].data.datamem op sp[1].data.datamem)
2891
2892 #define CONDBR(cond) \
2893         sp -= 2; \
2894         if (cond) \
2895                 ip += READ32(ip + 1); \
2896         else \
2897                 ip += 3;
2898
2899 #define BRELOP(datamem, op) \
2900         CONDBR(sp[0].data.datamem op sp[1].data.datamem)
2901
2902                 MINT_IN_CASE(MINT_BEQ_I4_S)
2903                         BRELOP_S(i, ==)
2904                         MINT_IN_BREAK;
2905                 MINT_IN_CASE(MINT_BEQ_I8_S)
2906                         BRELOP_S(l, ==)
2907                         MINT_IN_BREAK;
2908                 MINT_IN_CASE(MINT_BEQ_R8_S)
2909                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
2910                         MINT_IN_BREAK;
2911                 MINT_IN_CASE(MINT_BEQ_I4)
2912                         BRELOP(i, ==)
2913                         MINT_IN_BREAK;
2914                 MINT_IN_CASE(MINT_BEQ_I8)
2915                         BRELOP(l, ==)
2916                         MINT_IN_BREAK;
2917                 MINT_IN_CASE(MINT_BEQ_R8)
2918                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
2919                         MINT_IN_BREAK;
2920                 MINT_IN_CASE(MINT_BGE_I4_S)
2921                         BRELOP_S(i, >=)
2922                         MINT_IN_BREAK;
2923                 MINT_IN_CASE(MINT_BGE_I8_S)
2924                         BRELOP_S(l, >=)
2925                         MINT_IN_BREAK;
2926                 MINT_IN_CASE(MINT_BGE_R8_S)
2927                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
2928                         MINT_IN_BREAK;
2929                 MINT_IN_CASE(MINT_BGE_I4)
2930                         BRELOP(i, >=)
2931                         MINT_IN_BREAK;
2932                 MINT_IN_CASE(MINT_BGE_I8)
2933                         BRELOP(l, >=)
2934                         MINT_IN_BREAK;
2935                 MINT_IN_CASE(MINT_BGE_R8)
2936                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
2937                         MINT_IN_BREAK;
2938                 MINT_IN_CASE(MINT_BGT_I4_S)
2939                         BRELOP_S(i, >)
2940                         MINT_IN_BREAK;
2941                 MINT_IN_CASE(MINT_BGT_I8_S)
2942                         BRELOP_S(l, >)
2943                         MINT_IN_BREAK;
2944                 MINT_IN_CASE(MINT_BGT_R8_S)
2945                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
2946                         MINT_IN_BREAK;
2947                 MINT_IN_CASE(MINT_BGT_I4)
2948                         BRELOP(i, >)
2949                         MINT_IN_BREAK;
2950                 MINT_IN_CASE(MINT_BGT_I8)
2951                         BRELOP(l, >)
2952                         MINT_IN_BREAK;
2953                 MINT_IN_CASE(MINT_BGT_R8)
2954                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
2955                         MINT_IN_BREAK;
2956                 MINT_IN_CASE(MINT_BLT_I4_S)
2957                         BRELOP_S(i, <)
2958                         MINT_IN_BREAK;
2959                 MINT_IN_CASE(MINT_BLT_I8_S)
2960                         BRELOP_S(l, <)
2961                         MINT_IN_BREAK;
2962                 MINT_IN_CASE(MINT_BLT_R8_S)
2963                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
2964                         MINT_IN_BREAK;
2965                 MINT_IN_CASE(MINT_BLT_I4)
2966                         BRELOP(i, <)
2967                         MINT_IN_BREAK;
2968                 MINT_IN_CASE(MINT_BLT_I8)
2969                         BRELOP(l, <)
2970                         MINT_IN_BREAK;
2971                 MINT_IN_CASE(MINT_BLT_R8)
2972                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
2973                         MINT_IN_BREAK;
2974                 MINT_IN_CASE(MINT_BLE_I4_S)
2975                         BRELOP_S(i, <=)
2976                         MINT_IN_BREAK;
2977                 MINT_IN_CASE(MINT_BLE_I8_S)
2978                         BRELOP_S(l, <=)
2979                         MINT_IN_BREAK;
2980                 MINT_IN_CASE(MINT_BLE_R8_S)
2981                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
2982                         MINT_IN_BREAK;
2983                 MINT_IN_CASE(MINT_BLE_I4)
2984                         BRELOP(i, <=)
2985                         MINT_IN_BREAK;
2986                 MINT_IN_CASE(MINT_BLE_I8)
2987                         BRELOP(l, <=)
2988                         MINT_IN_BREAK;
2989                 MINT_IN_CASE(MINT_BLE_R8)
2990                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
2991                         MINT_IN_BREAK;
2992                 MINT_IN_CASE(MINT_BNE_UN_I4_S)
2993                         BRELOP_S(i, !=)
2994                         MINT_IN_BREAK;
2995                 MINT_IN_CASE(MINT_BNE_UN_I8_S)
2996                         BRELOP_S(l, !=)
2997                         MINT_IN_BREAK;
2998                 MINT_IN_CASE(MINT_BNE_UN_R8_S)
2999                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
3000                         MINT_IN_BREAK;
3001                 MINT_IN_CASE(MINT_BNE_UN_I4)
3002                         BRELOP(i, !=)
3003                         MINT_IN_BREAK;
3004                 MINT_IN_CASE(MINT_BNE_UN_I8)
3005                         BRELOP(l, !=)
3006                         MINT_IN_BREAK;
3007                 MINT_IN_CASE(MINT_BNE_UN_R8)
3008                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
3009                         MINT_IN_BREAK;
3010
3011 #define BRELOP_S_CAST(datamem, op, type) \
3012         sp -= 2; \
3013         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
3014                 ip += * (gint16 *)(ip + 1); \
3015         else \
3016                 ip += 2;
3017
3018 #define BRELOP_CAST(datamem, op, type) \
3019         sp -= 2; \
3020         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
3021                 ip += READ32(ip + 1); \
3022         else \
3023                 ip += 3;
3024
3025                 MINT_IN_CASE(MINT_BGE_UN_I4_S)
3026                         BRELOP_S_CAST(i, >=, guint32);
3027                         MINT_IN_BREAK;
3028                 MINT_IN_CASE(MINT_BGE_UN_I8_S)
3029                         BRELOP_S_CAST(l, >=, guint64);
3030                         MINT_IN_BREAK;
3031                 MINT_IN_CASE(MINT_BGE_UN_R8_S)
3032                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
3033                         MINT_IN_BREAK;
3034                 MINT_IN_CASE(MINT_BGE_UN_I4)
3035                         BRELOP_CAST(i, >=, guint32);
3036                         MINT_IN_BREAK;
3037                 MINT_IN_CASE(MINT_BGE_UN_I8)
3038                         BRELOP_CAST(l, >=, guint64);
3039                         MINT_IN_BREAK;
3040                 MINT_IN_CASE(MINT_BGE_UN_R8)
3041                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
3042                         MINT_IN_BREAK;
3043                 MINT_IN_CASE(MINT_BGT_UN_I4_S)
3044                         BRELOP_S_CAST(i, >, guint32);
3045                         MINT_IN_BREAK;
3046                 MINT_IN_CASE(MINT_BGT_UN_I8_S)
3047                         BRELOP_S_CAST(l, >, guint64);
3048                         MINT_IN_BREAK;
3049                 MINT_IN_CASE(MINT_BGT_UN_R8_S)
3050                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
3051                         MINT_IN_BREAK;
3052                 MINT_IN_CASE(MINT_BGT_UN_I4)
3053                         BRELOP_CAST(i, >, guint32);
3054                         MINT_IN_BREAK;
3055                 MINT_IN_CASE(MINT_BGT_UN_I8)
3056                         BRELOP_CAST(l, >, guint64);
3057                         MINT_IN_BREAK;
3058                 MINT_IN_CASE(MINT_BGT_UN_R8)
3059                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
3060                         MINT_IN_BREAK;
3061                 MINT_IN_CASE(MINT_BLE_UN_I4_S)
3062                         BRELOP_S_CAST(i, <=, guint32);
3063                         MINT_IN_BREAK;
3064                 MINT_IN_CASE(MINT_BLE_UN_I8_S)
3065                         BRELOP_S_CAST(l, <=, guint64);
3066                         MINT_IN_BREAK;
3067                 MINT_IN_CASE(MINT_BLE_UN_R8_S)
3068                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
3069                         MINT_IN_BREAK;
3070                 MINT_IN_CASE(MINT_BLE_UN_I4)
3071                         BRELOP_CAST(i, <=, guint32);
3072                         MINT_IN_BREAK;
3073                 MINT_IN_CASE(MINT_BLE_UN_I8)
3074                         BRELOP_CAST(l, <=, guint64);
3075                         MINT_IN_BREAK;
3076                 MINT_IN_CASE(MINT_BLE_UN_R8)
3077                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
3078                         MINT_IN_BREAK;
3079                 MINT_IN_CASE(MINT_BLT_UN_I4_S)
3080                         BRELOP_S_CAST(i, <, guint32);
3081                         MINT_IN_BREAK;
3082                 MINT_IN_CASE(MINT_BLT_UN_I8_S)
3083                         BRELOP_S_CAST(l, <, guint64);
3084                         MINT_IN_BREAK;
3085                 MINT_IN_CASE(MINT_BLT_UN_R8_S)
3086                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
3087                         MINT_IN_BREAK;
3088                 MINT_IN_CASE(MINT_BLT_UN_I4)
3089                         BRELOP_CAST(i, <, guint32);
3090                         MINT_IN_BREAK;
3091                 MINT_IN_CASE(MINT_BLT_UN_I8)
3092                         BRELOP_CAST(l, <, guint64);
3093                         MINT_IN_BREAK;
3094                 MINT_IN_CASE(MINT_BLT_UN_R8)
3095                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
3096                         MINT_IN_BREAK;
3097                 MINT_IN_CASE(MINT_SWITCH) {
3098                         guint32 n;
3099                         const unsigned short *st;
3100                         ++ip;
3101                         n = READ32 (ip);
3102                         ip += 2;
3103                         st = ip + 2 * n;
3104                         --sp;
3105                         if ((guint32)sp->data.i < n) {
3106                                 gint offset;
3107                                 ip += 2 * (guint32)sp->data.i;
3108                                 offset = READ32 (ip);
3109                                 ip = ip + offset;
3110                         } else {
3111                                 ip = st;
3112                         }
3113                         MINT_IN_BREAK;
3114                 }
3115                 MINT_IN_CASE(MINT_LDIND_I1)
3116                         ++ip;
3117                         sp[-1].data.i = *(gint8*)sp[-1].data.p;
3118                         MINT_IN_BREAK;
3119                 MINT_IN_CASE(MINT_LDIND_U1)
3120                         ++ip;
3121                         sp[-1].data.i = *(guint8*)sp[-1].data.p;
3122                         MINT_IN_BREAK;
3123                 MINT_IN_CASE(MINT_LDIND_I2)
3124                         ++ip;
3125                         sp[-1].data.i = *(gint16*)sp[-1].data.p;
3126                         MINT_IN_BREAK;
3127                 MINT_IN_CASE(MINT_LDIND_U2)
3128                         ++ip;
3129                         sp[-1].data.i = *(guint16*)sp[-1].data.p;
3130                         MINT_IN_BREAK;
3131                 MINT_IN_CASE(MINT_LDIND_I4) /* Fall through */
3132                 MINT_IN_CASE(MINT_LDIND_U4)
3133                         ++ip;
3134                         sp[-1].data.i = *(gint32*)sp[-1].data.p;
3135                         MINT_IN_BREAK;
3136                 MINT_IN_CASE(MINT_LDIND_I8)
3137                         ++ip;
3138                         /* memmove handles unaligned case */
3139                         memmove (&sp [-1].data.l, sp [-1].data.p, sizeof (gint64));
3140                         MINT_IN_BREAK;
3141                 MINT_IN_CASE(MINT_LDIND_I) {
3142                         guint16 offset = * (guint16 *)(ip + 1);
3143                         sp[-1 - offset].data.p = *(gpointer*)sp[-1 - offset].data.p;
3144                         ip += 2;
3145                         MINT_IN_BREAK;
3146                 }
3147                 MINT_IN_CASE(MINT_LDIND_R4)
3148                         ++ip;
3149                         sp[-1].data.f = *(gfloat*)sp[-1].data.p;
3150                         MINT_IN_BREAK;
3151                 MINT_IN_CASE(MINT_LDIND_R8)
3152                         ++ip;
3153                         sp[-1].data.f = *(gdouble*)sp[-1].data.p;
3154                         MINT_IN_BREAK;
3155                 MINT_IN_CASE(MINT_LDIND_REF)
3156                         ++ip;
3157                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
3158                         MINT_IN_BREAK;
3159                 MINT_IN_CASE(MINT_STIND_REF) 
3160                         ++ip;
3161                         sp -= 2;
3162                         mono_gc_wbarrier_generic_store (sp->data.p, sp [1].data.p);
3163                         MINT_IN_BREAK;
3164                 MINT_IN_CASE(MINT_STIND_I1)
3165                         ++ip;
3166                         sp -= 2;
3167                         * (gint8 *) sp->data.p = (gint8)sp[1].data.i;
3168                         MINT_IN_BREAK;
3169                 MINT_IN_CASE(MINT_STIND_I2)
3170                         ++ip;
3171                         sp -= 2;
3172                         * (gint16 *) sp->data.p = (gint16)sp[1].data.i;
3173                         MINT_IN_BREAK;
3174                 MINT_IN_CASE(MINT_STIND_I4)
3175                         ++ip;
3176                         sp -= 2;
3177                         * (gint32 *) sp->data.p = sp[1].data.i;
3178                         MINT_IN_BREAK;
3179                 MINT_IN_CASE(MINT_STIND_I)
3180                         ++ip;
3181                         sp -= 2;
3182                         * (mono_i *) sp->data.p = (mono_i)sp[1].data.p;
3183                         MINT_IN_BREAK;
3184                 MINT_IN_CASE(MINT_STIND_I8)
3185                         ++ip;
3186                         sp -= 2;
3187                         * (gint64 *) sp->data.p = sp[1].data.l;
3188                         MINT_IN_BREAK;
3189                 MINT_IN_CASE(MINT_STIND_R4)
3190                         ++ip;
3191                         sp -= 2;
3192                         * (float *) sp->data.p = (gfloat)sp[1].data.f;
3193                         MINT_IN_BREAK;
3194                 MINT_IN_CASE(MINT_STIND_R8)
3195                         ++ip;
3196                         sp -= 2;
3197                         * (double *) sp->data.p = sp[1].data.f;
3198                         MINT_IN_BREAK;
3199                 MINT_IN_CASE(MINT_MONO_ATOMIC_STORE_I4)
3200                         ++ip;
3201                         sp -= 2;
3202                         InterlockedWrite ((gint32 *) sp->data.p, sp [1].data.i);
3203                         MINT_IN_BREAK;
3204 #define BINOP(datamem, op) \
3205         --sp; \
3206         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.datamem; \
3207         ++ip;
3208                 MINT_IN_CASE(MINT_ADD_I4)
3209                         BINOP(i, +);
3210                         MINT_IN_BREAK;
3211                 MINT_IN_CASE(MINT_ADD_I8)
3212                         BINOP(l, +);
3213                         MINT_IN_BREAK;
3214                 MINT_IN_CASE(MINT_ADD_R8)
3215                         BINOP(f, +);
3216                         MINT_IN_BREAK;
3217                 MINT_IN_CASE(MINT_ADD1_I4)
3218                         ++sp [-1].data.i;
3219                         ++ip;
3220                         MINT_IN_BREAK;
3221                 MINT_IN_CASE(MINT_SUB_I4)
3222                         BINOP(i, -);
3223                         MINT_IN_BREAK;
3224                 MINT_IN_CASE(MINT_SUB_I8)
3225                         BINOP(l, -);
3226                         MINT_IN_BREAK;
3227                 MINT_IN_CASE(MINT_SUB_R8)
3228                         BINOP(f, -);
3229                         MINT_IN_BREAK;
3230                 MINT_IN_CASE(MINT_SUB1_I4)
3231                         --sp [-1].data.i;
3232                         ++ip;
3233                         MINT_IN_BREAK;
3234                 MINT_IN_CASE(MINT_MUL_I4)
3235                         BINOP(i, *);
3236                         MINT_IN_BREAK;
3237                 MINT_IN_CASE(MINT_MUL_I8)
3238                         BINOP(l, *);
3239                         MINT_IN_BREAK;
3240                 MINT_IN_CASE(MINT_MUL_R8)
3241                         BINOP(f, *);
3242                         MINT_IN_BREAK;
3243                 MINT_IN_CASE(MINT_DIV_I4)
3244                         if (sp [-1].data.i == 0)
3245                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3246                         if (sp [-1].data.i == (-1))
3247                                 THROW_EX (mono_get_exception_overflow (), ip);
3248                         BINOP(i, /);
3249                         MINT_IN_BREAK;
3250                 MINT_IN_CASE(MINT_DIV_I8)
3251                         if (sp [-1].data.l == 0)
3252                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3253                         if (sp [-1].data.l == (-1))
3254                                 THROW_EX (mono_get_exception_overflow (), ip);
3255                         BINOP(l, /);
3256                         MINT_IN_BREAK;
3257                 MINT_IN_CASE(MINT_DIV_R8)
3258                         BINOP(f, /);
3259                         MINT_IN_BREAK;
3260
3261 #define BINOP_CAST(datamem, op, type) \
3262         --sp; \
3263         sp [-1].data.datamem = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
3264         ++ip;
3265                 MINT_IN_CASE(MINT_DIV_UN_I4)
3266                         if (sp [-1].data.i == 0)
3267                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3268                         BINOP_CAST(i, /, guint32);
3269                         MINT_IN_BREAK;
3270                 MINT_IN_CASE(MINT_DIV_UN_I8)
3271                         if (sp [-1].data.l == 0)
3272                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3273                         BINOP_CAST(l, /, guint64);
3274                         MINT_IN_BREAK;
3275                 MINT_IN_CASE(MINT_REM_I4)
3276                         if (sp [-1].data.i == 0)
3277                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3278                         if (sp [-1].data.i == (-1))
3279                                 THROW_EX (mono_get_exception_overflow (), ip);
3280                         BINOP(i, %);
3281                         MINT_IN_BREAK;
3282                 MINT_IN_CASE(MINT_REM_I8)
3283                         if (sp [-1].data.l == 0)
3284                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3285                         if (sp [-1].data.l == (-1))
3286                                 THROW_EX (mono_get_exception_overflow (), ip);
3287                         BINOP(l, %);
3288                         MINT_IN_BREAK;
3289                 MINT_IN_CASE(MINT_REM_R8)
3290                         /* FIXME: what do we actually do here? */
3291                         --sp;
3292                         sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
3293                         ++ip;
3294                         MINT_IN_BREAK;
3295                 MINT_IN_CASE(MINT_REM_UN_I4)
3296                         if (sp [-1].data.i == 0)
3297                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3298                         BINOP_CAST(i, %, guint32);
3299                         MINT_IN_BREAK;
3300                 MINT_IN_CASE(MINT_REM_UN_I8)
3301                         if (sp [-1].data.l == 0)
3302                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3303                         BINOP_CAST(l, %, guint64);
3304                         MINT_IN_BREAK;
3305                 MINT_IN_CASE(MINT_AND_I4)
3306                         BINOP(i, &);
3307                         MINT_IN_BREAK;
3308                 MINT_IN_CASE(MINT_AND_I8)
3309                         BINOP(l, &);
3310                         MINT_IN_BREAK;
3311                 MINT_IN_CASE(MINT_OR_I4)
3312                         BINOP(i, |);
3313                         MINT_IN_BREAK;
3314                 MINT_IN_CASE(MINT_OR_I8)
3315                         BINOP(l, |);
3316                         MINT_IN_BREAK;
3317                 MINT_IN_CASE(MINT_XOR_I4)
3318                         BINOP(i, ^);
3319                         MINT_IN_BREAK;
3320                 MINT_IN_CASE(MINT_XOR_I8)
3321                         BINOP(l, ^);
3322                         MINT_IN_BREAK;
3323
3324 #define SHIFTOP(datamem, op) \
3325         --sp; \
3326         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.i; \
3327         ++ip;
3328
3329                 MINT_IN_CASE(MINT_SHL_I4)
3330                         SHIFTOP(i, <<);
3331                         MINT_IN_BREAK;
3332                 MINT_IN_CASE(MINT_SHL_I8)
3333                         SHIFTOP(l, <<);
3334                         MINT_IN_BREAK;
3335                 MINT_IN_CASE(MINT_SHR_I4)
3336                         SHIFTOP(i, >>);
3337                         MINT_IN_BREAK;
3338                 MINT_IN_CASE(MINT_SHR_I8)
3339                         SHIFTOP(l, >>);
3340                         MINT_IN_BREAK;
3341                 MINT_IN_CASE(MINT_SHR_UN_I4)
3342                         --sp;
3343                         sp [-1].data.i = (guint32)sp [-1].data.i >> sp [0].data.i;
3344                         ++ip;
3345                         MINT_IN_BREAK;
3346                 MINT_IN_CASE(MINT_SHR_UN_I8)
3347                         --sp;
3348                         sp [-1].data.l = (guint64)sp [-1].data.l >> sp [0].data.i;
3349                         ++ip;
3350                         MINT_IN_BREAK;
3351                 MINT_IN_CASE(MINT_NEG_I4)
3352                         sp [-1].data.i = - sp [-1].data.i;
3353                         ++ip;
3354                         MINT_IN_BREAK;
3355                 MINT_IN_CASE(MINT_NEG_I8)
3356                         sp [-1].data.l = - sp [-1].data.l;
3357                         ++ip;
3358                         MINT_IN_BREAK;
3359                 MINT_IN_CASE(MINT_NEG_R8)
3360                         sp [-1].data.f = - sp [-1].data.f;
3361                         ++ip;
3362                         MINT_IN_BREAK;
3363                 MINT_IN_CASE(MINT_NOT_I4)
3364                         sp [-1].data.i = ~ sp [-1].data.i;
3365                         ++ip;
3366                         MINT_IN_BREAK;
3367                 MINT_IN_CASE(MINT_NOT_I8)
3368                         sp [-1].data.l = ~ sp [-1].data.l;
3369                         ++ip;
3370                         MINT_IN_BREAK;
3371                 MINT_IN_CASE(MINT_CONV_I1_I4)
3372                         sp [-1].data.i = (gint8)sp [-1].data.i;
3373                         ++ip;
3374                         MINT_IN_BREAK;
3375                 MINT_IN_CASE(MINT_CONV_I1_I8)
3376                         sp [-1].data.i = (gint8)sp [-1].data.l;
3377                         ++ip;
3378                         MINT_IN_BREAK;
3379                 MINT_IN_CASE(MINT_CONV_I1_R8)
3380                         sp [-1].data.i = (gint8)sp [-1].data.f;
3381                         ++ip;
3382                         MINT_IN_BREAK;
3383                 MINT_IN_CASE(MINT_CONV_U1_I4)
3384                         sp [-1].data.i = (guint8)sp [-1].data.i;
3385                         ++ip;
3386                         MINT_IN_BREAK;
3387                 MINT_IN_CASE(MINT_CONV_U1_I8)
3388                         sp [-1].data.i = (guint8)sp [-1].data.l;
3389                         ++ip;
3390                         MINT_IN_BREAK;
3391                 MINT_IN_CASE(MINT_CONV_U1_R8)
3392                         sp [-1].data.i = (guint8)sp [-1].data.f;
3393                         ++ip;
3394                         MINT_IN_BREAK;
3395                 MINT_IN_CASE(MINT_CONV_I2_I4)
3396                         sp [-1].data.i = (gint16)sp [-1].data.i;
3397                         ++ip;
3398                         MINT_IN_BREAK;
3399                 MINT_IN_CASE(MINT_CONV_I2_I8)
3400                         sp [-1].data.i = (gint16)sp [-1].data.l;
3401                         ++ip;
3402                         MINT_IN_BREAK;
3403                 MINT_IN_CASE(MINT_CONV_I2_R8)
3404                         sp [-1].data.i = (gint16)sp [-1].data.f;
3405                         ++ip;
3406                         MINT_IN_BREAK;
3407                 MINT_IN_CASE(MINT_CONV_U2_I4)
3408                         sp [-1].data.i = (guint16)sp [-1].data.i;
3409                         ++ip;
3410                         MINT_IN_BREAK;
3411                 MINT_IN_CASE(MINT_CONV_U2_I8)
3412                         sp [-1].data.i = (guint16)sp [-1].data.l;
3413                         ++ip;
3414                         MINT_IN_BREAK;
3415                 MINT_IN_CASE(MINT_CONV_U2_R8)
3416                         sp [-1].data.i = (guint16)sp [-1].data.f;
3417                         ++ip;
3418                         MINT_IN_BREAK;
3419                 MINT_IN_CASE(MINT_CONV_I4_R8)
3420                         sp [-1].data.i = (gint32)sp [-1].data.f;
3421                         ++ip;
3422                         MINT_IN_BREAK;
3423                 MINT_IN_CASE(MINT_CONV_U4_I8)
3424                 MINT_IN_CASE(MINT_CONV_I4_I8)
3425                         sp [-1].data.i = (gint32)sp [-1].data.l;
3426                         ++ip;
3427                         MINT_IN_BREAK;
3428                 MINT_IN_CASE(MINT_CONV_I4_I8_SP)
3429                         sp [-2].data.i = (gint32)sp [-2].data.l;
3430                         ++ip;
3431                         MINT_IN_BREAK;
3432                 MINT_IN_CASE(MINT_CONV_U4_R8)
3433                         /* needed on arm64 */
3434                         if (isinf (sp [-1].data.f))
3435                                 sp [-1].data.i = 0;
3436                         else
3437                                 sp [-1].data.i = (guint32)sp [-1].data.f;
3438                         ++ip;
3439                         MINT_IN_BREAK;
3440                 MINT_IN_CASE(MINT_CONV_I8_I4)
3441                         sp [-1].data.l = sp [-1].data.i;
3442                         ++ip;
3443                         MINT_IN_BREAK;
3444                 MINT_IN_CASE(MINT_CONV_I8_I4_SP)
3445                         sp [-2].data.l = sp [-2].data.i;
3446                         ++ip;
3447                         MINT_IN_BREAK;
3448                 MINT_IN_CASE(MINT_CONV_I8_U4)
3449                         sp [-1].data.l = (guint32)sp [-1].data.i;
3450                         ++ip;
3451                         MINT_IN_BREAK;
3452                 MINT_IN_CASE(MINT_CONV_I8_R8)
3453                         sp [-1].data.l = (gint64)sp [-1].data.f;
3454                         ++ip;
3455                         MINT_IN_BREAK;
3456                 MINT_IN_CASE(MINT_CONV_R4_I4)
3457                         sp [-1].data.f = (float)sp [-1].data.i;
3458                         ++ip;
3459                         MINT_IN_BREAK;
3460                 MINT_IN_CASE(MINT_CONV_R4_I8)
3461                         sp [-1].data.f = (float)sp [-1].data.l;
3462                         ++ip;
3463                         MINT_IN_BREAK;
3464                 MINT_IN_CASE(MINT_CONV_R4_R8)
3465                         sp [-1].data.f = (float)sp [-1].data.f;
3466                         ++ip;
3467                         MINT_IN_BREAK;
3468                 MINT_IN_CASE(MINT_CONV_R8_I4)
3469                         sp [-1].data.f = (double)sp [-1].data.i;
3470                         ++ip;
3471                         MINT_IN_BREAK;
3472                 MINT_IN_CASE(MINT_CONV_R8_I8)
3473                         sp [-1].data.f = (double)sp [-1].data.l;
3474                         ++ip;
3475                         MINT_IN_BREAK;
3476                 MINT_IN_CASE(MINT_CONV_U8_I4)
3477                         sp [-1].data.l = sp [-1].data.i & 0xffffffff;
3478                         ++ip;
3479                         MINT_IN_BREAK;
3480                 MINT_IN_CASE(MINT_CONV_U8_R8)
3481                         sp [-1].data.l = (guint64)sp [-1].data.f;
3482                         ++ip;
3483                         MINT_IN_BREAK;
3484                 MINT_IN_CASE(MINT_CPOBJ) {
3485                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3486                         g_assert (c->valuetype);
3487                         /* if this assertion fails, we need to add a write barrier */
3488                         g_assert (!MONO_TYPE_IS_REFERENCE (&c->byval_arg));
3489                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE)
3490                                 stackval_from_data (&c->byval_arg, &sp [-2], sp [-1].data.p, FALSE);
3491                         else
3492                                 stackval_from_data (&c->byval_arg, sp [-2].data.p, sp [-1].data.p, FALSE);
3493                         ip += 2;
3494                         sp -= 2;
3495                         MINT_IN_BREAK;
3496                 }
3497                 MINT_IN_CASE(MINT_LDOBJ) {
3498                         void *p;
3499                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3500                         ip += 2;
3501                         p = sp [-1].data.p;
3502                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
3503                                 int size = mono_class_value_size (c, NULL);
3504                                 sp [-1].data.p = vt_sp;
3505                                 vt_sp += (size + 7) & ~7;
3506                         }
3507                         stackval_from_data (&c->byval_arg, &sp [-1], p, FALSE);
3508                         MINT_IN_BREAK;
3509                 }
3510                 MINT_IN_CASE(MINT_LDSTR)
3511                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
3512                         ++sp;
3513                         ip += 2;
3514                         MINT_IN_BREAK;
3515                 MINT_IN_CASE(MINT_NEWOBJ) {
3516                         MonoClass *newobj_class;
3517                         MonoMethodSignature *csig;
3518                         stackval valuetype_this;
3519                         guint32 token;
3520                         stackval retval;
3521
3522                         frame->ip = ip;
3523
3524                         token = * (guint16 *)(ip + 1);
3525                         ip += 2;
3526
3527                         child_frame.ip = NULL;
3528                         child_frame.ex = NULL;
3529
3530                         child_frame.imethod = rtm->data_items [token];
3531                         csig = mono_method_signature (child_frame.imethod->method);
3532                         newobj_class = child_frame.imethod->method->klass;
3533                         /*if (profiling_classes) {
3534                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
3535                                 count++;
3536                                 g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
3537                         }*/
3538
3539                         if (newobj_class->parent == mono_defaults.array_class) {
3540                                 sp -= csig->param_count;
3541                                 child_frame.stack_args = sp;
3542                                 o = ves_array_create (&child_frame, rtm->domain, newobj_class, csig, sp);
3543                                 if (child_frame.ex)
3544                                         THROW_EX (child_frame.ex, ip);
3545                                 goto array_constructed;
3546                         }
3547
3548                         g_assert (csig->hasthis);
3549                         if (csig->param_count) {
3550                                 sp -= csig->param_count;
3551                                 memmove (sp + 1, sp, csig->param_count * sizeof (stackval));
3552                         }
3553                         child_frame.stack_args = sp;
3554
3555                         /*
3556                          * First arg is the object.
3557                          */
3558                         if (newobj_class->valuetype) {
3559                                 MonoType *t = &newobj_class->byval_arg;
3560                                 memset (&valuetype_this, 0, sizeof (stackval));
3561                                 if (!newobj_class->enumtype && (t->type == MONO_TYPE_VALUETYPE || (t->type == MONO_TYPE_GENERICINST && mono_type_generic_inst_is_valuetype (t)))) {
3562                                         sp->data.p = vt_sp;
3563                                         valuetype_this.data.p = vt_sp;
3564                                 } else {
3565                                         sp->data.p = &valuetype_this;
3566                                 }
3567                         } else {
3568                                 if (newobj_class != mono_defaults.string_class) {
3569                                         context->managed_code = 0;
3570                                         o = mono_object_new_checked (rtm->domain, newobj_class, &error);
3571                                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3572                                         context->managed_code = 1;
3573                                         if (*mono_thread_interruption_request_flag ())
3574                                                 mono_thread_interruption_checkpoint ();
3575                                         sp->data.p = o;
3576                                 } else {
3577                                         sp->data.p = NULL;
3578                                         child_frame.retval = &retval;
3579                                 }
3580                         }
3581
3582                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
3583
3584                         ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
3585
3586                         context->current_frame = frame;
3587
3588                         if (context->has_resume_state) {
3589                                 if (frame == context->handler_frame)
3590                                         SET_RESUME_STATE (context);
3591                                 else
3592                                         goto exit_frame;
3593                         }
3594
3595                         if (child_frame.ex) {
3596                                 /*
3597                                  * An exception occurred, need to run finally, fault and catch handlers..
3598                                  */
3599                                 frame->ex = child_frame.ex;
3600                                 goto handle_finally;
3601                         }
3602                         /*
3603                          * a constructor returns void, but we need to return the object we created
3604                          */
3605 array_constructed:
3606                         if (newobj_class->valuetype && !newobj_class->enumtype) {
3607                                 *sp = valuetype_this;
3608                         } else if (newobj_class == mono_defaults.string_class) {
3609                                 *sp = retval;
3610                         } else {
3611                                 sp->data.p = o;
3612                         }
3613                         ++sp;
3614                         MINT_IN_BREAK;
3615                 }
3616                 MINT_IN_CASE(MINT_CASTCLASS)
3617                         c = rtm->data_items [*(guint16 *)(ip + 1)];
3618                         if ((o = sp [-1].data.p)) {
3619                                 MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
3620                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3621                                 if (!isinst_obj)
3622                                         THROW_EX (mono_get_exception_invalid_cast (), ip);
3623                         }
3624                         ip += 2;
3625                         MINT_IN_BREAK;
3626                 MINT_IN_CASE(MINT_ISINST)
3627                         c = rtm->data_items [*(guint16 *)(ip + 1)];
3628                         if ((o = sp [-1].data.p)) {
3629                                 MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
3630                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3631                                 if (!isinst_obj)
3632                                         sp [-1].data.p = NULL;
3633                         }
3634                         ip += 2;
3635                         MINT_IN_BREAK;
3636                 MINT_IN_CASE(MINT_CONV_R_UN_I4)
3637                         sp [-1].data.f = (double)(guint32)sp [-1].data.i;
3638                         ++ip;
3639                         MINT_IN_BREAK;
3640                 MINT_IN_CASE(MINT_CONV_R_UN_I8)
3641                         sp [-1].data.f = (double)(guint64)sp [-1].data.l;
3642                         ++ip;
3643                         MINT_IN_BREAK;
3644                 MINT_IN_CASE(MINT_UNBOX)
3645                         c = rtm->data_items[*(guint16 *)(ip + 1)];
3646                         
3647                         o = sp [-1].data.p;
3648                         if (!o)
3649                                 THROW_EX (mono_get_exception_null_reference (), ip);
3650
3651                         MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
3652                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3653                         if (!(isinst_obj || ((o->vtable->klass->rank == 0) && (o->vtable->klass->element_class == c->element_class))))
3654                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
3655
3656                         sp [-1].data.p = mono_object_unbox (o);
3657                         ip += 2;
3658                         MINT_IN_BREAK;
3659                 MINT_IN_CASE(MINT_THROW)
3660                         --sp;
3661                         frame->ex_handler = NULL;
3662                         if (!sp->data.p)
3663                                 sp->data.p = mono_get_exception_null_reference ();
3664
3665                         THROW_EX ((MonoException *)sp->data.p, ip);
3666                         MINT_IN_BREAK;
3667                 MINT_IN_CASE(MINT_LDFLDA_UNSAFE)
3668                         o = sp [-1].data.p;
3669                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
3670                         ip += 2;
3671                         MINT_IN_BREAK;
3672                 MINT_IN_CASE(MINT_LDFLDA)
3673                         o = sp [-1].data.p;
3674                         if (!o)
3675                                 THROW_EX (mono_get_exception_null_reference (), ip);
3676                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
3677                         ip += 2;
3678                         MINT_IN_BREAK;
3679                 MINT_IN_CASE(MINT_CKNULL)
3680                         o = sp [-1].data.p;
3681                         if (!o)
3682                                 THROW_EX (mono_get_exception_null_reference (), ip);
3683                         ++ip;
3684                         MINT_IN_BREAK;
3685
3686 #define LDFLD(datamem, fieldtype) \
3687         o = sp [-1].data.p; \
3688         if (!o) \
3689                 THROW_EX (mono_get_exception_null_reference (), ip); \
3690         sp[-1].data.datamem = * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) ; \
3691         ip += 2;
3692
3693                 MINT_IN_CASE(MINT_LDFLD_I1) LDFLD(i, gint8); MINT_IN_BREAK;
3694                 MINT_IN_CASE(MINT_LDFLD_U1) LDFLD(i, guint8); MINT_IN_BREAK;
3695                 MINT_IN_CASE(MINT_LDFLD_I2) LDFLD(i, gint16); MINT_IN_BREAK;
3696                 MINT_IN_CASE(MINT_LDFLD_U2) LDFLD(i, guint16); MINT_IN_BREAK;
3697                 MINT_IN_CASE(MINT_LDFLD_I4) LDFLD(i, gint32); MINT_IN_BREAK;
3698                 MINT_IN_CASE(MINT_LDFLD_I8) LDFLD(l, gint64); MINT_IN_BREAK;
3699                 MINT_IN_CASE(MINT_LDFLD_R4) LDFLD(f, float); MINT_IN_BREAK;
3700                 MINT_IN_CASE(MINT_LDFLD_R8) LDFLD(f, double); MINT_IN_BREAK;
3701                 MINT_IN_CASE(MINT_LDFLD_O) LDFLD(p, gpointer); MINT_IN_BREAK;
3702                 MINT_IN_CASE(MINT_LDFLD_P) LDFLD(p, gpointer); MINT_IN_BREAK;
3703
3704                 MINT_IN_CASE(MINT_LDFLD_VT)
3705                         o = sp [-1].data.p;
3706                         if (!o)
3707                                 THROW_EX (mono_get_exception_null_reference (), ip);
3708                         i32 = READ32(ip + 2);
3709                         sp [-1].data.p = vt_sp;
3710                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
3711                         vt_sp += (i32 + 7) & ~7;
3712                         ip += 4;
3713                         MINT_IN_BREAK;
3714
3715                 MINT_IN_CASE(MINT_LDRMFLD) {
3716                         gpointer tmp;
3717                         MonoClassField *field;
3718                         char *addr;
3719
3720                         o = sp [-1].data.p;
3721                         if (!o)
3722                                 THROW_EX (mono_get_exception_null_reference (), ip);
3723                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3724                         ip += 2;
3725 #ifndef DISABLE_REMOTING
3726                         if (mono_object_is_transparent_proxy (o)) {
3727                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3728
3729                                 addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
3730                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3731                         } else
3732 #endif
3733                                 addr = (char*)o + field->offset;
3734
3735                         stackval_from_data (field->type, &sp [-1], addr, FALSE);
3736                         MINT_IN_BREAK;
3737                 }
3738
3739                 MINT_IN_CASE(MINT_LDRMFLD_VT) {
3740                         MonoClassField *field;
3741                         char *addr;
3742                         gpointer tmp;
3743
3744                         o = sp [-1].data.p;
3745                         if (!o)
3746                                 THROW_EX (mono_get_exception_null_reference (), ip);
3747                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3748                         i32 = READ32(ip + 2);
3749                         ip += 4;
3750 #ifndef DISABLE_REMOTING
3751                         if (mono_object_is_transparent_proxy (o)) {
3752                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3753                                 addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
3754                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3755                         } else
3756 #endif
3757                                 addr = (char*)o + field->offset;
3758
3759                         sp [-1].data.p = vt_sp;
3760                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
3761                         vt_sp += (i32 + 7) & ~7;
3762                         memcpy(sp [-1].data.p, addr, i32);
3763                         MINT_IN_BREAK;
3764                 }
3765
3766 #define STFLD(datamem, fieldtype) \
3767         o = sp [-2].data.p; \
3768         if (!o) \
3769                 THROW_EX (mono_get_exception_null_reference (), ip); \
3770         sp -= 2; \
3771         * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) = sp[1].data.datamem; \
3772         ip += 2;
3773
3774                 MINT_IN_CASE(MINT_STFLD_I1) STFLD(i, gint8); MINT_IN_BREAK;
3775                 MINT_IN_CASE(MINT_STFLD_U1) STFLD(i, guint8); MINT_IN_BREAK;
3776                 MINT_IN_CASE(MINT_STFLD_I2) STFLD(i, gint16); MINT_IN_BREAK;
3777                 MINT_IN_CASE(MINT_STFLD_U2) STFLD(i, guint16); MINT_IN_BREAK;
3778                 MINT_IN_CASE(MINT_STFLD_I4) STFLD(i, gint32); MINT_IN_BREAK;
3779                 MINT_IN_CASE(MINT_STFLD_I8) STFLD(l, gint64); MINT_IN_BREAK;
3780                 MINT_IN_CASE(MINT_STFLD_R4) STFLD(f, float); MINT_IN_BREAK;
3781                 MINT_IN_CASE(MINT_STFLD_R8) STFLD(f, double); MINT_IN_BREAK;
3782                 MINT_IN_CASE(MINT_STFLD_P) STFLD(p, gpointer); MINT_IN_BREAK;
3783                 MINT_IN_CASE(MINT_STFLD_O)
3784                         o = sp [-2].data.p;
3785                         if (!o)
3786                                 THROW_EX (mono_get_exception_null_reference (), ip);
3787                         sp -= 2;
3788                         mono_gc_wbarrier_set_field (o, (char *) o + * (guint16 *)(ip + 1), sp [1].data.p);
3789                         ip += 2;
3790                         MINT_IN_BREAK;
3791
3792                 MINT_IN_CASE(MINT_STFLD_VT)
3793                         o = sp [-2].data.p;
3794                         if (!o)
3795                                 THROW_EX (mono_get_exception_null_reference (), ip);
3796                         i32 = READ32(ip + 2);
3797                         sp -= 2;
3798                         memcpy((char *)o + * (guint16 *)(ip + 1), sp [1].data.p, i32);
3799                         vt_sp -= (i32 + 7) & ~7;
3800                         ip += 4;
3801                         MINT_IN_BREAK;
3802
3803                 MINT_IN_CASE(MINT_STRMFLD) {
3804                         MonoClassField *field;
3805
3806                         o = sp [-2].data.p;
3807                         if (!o)
3808                                 THROW_EX (mono_get_exception_null_reference (), ip);
3809                         
3810                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3811                         ip += 2;
3812
3813 #ifndef DISABLE_REMOTING
3814                         if (mono_object_is_transparent_proxy (o)) {
3815                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3816                                 mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
3817                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3818                         } else
3819 #endif
3820                                 stackval_to_data (field->type, &sp [-1], (char*)o + field->offset, FALSE);
3821
3822                         sp -= 2;
3823                         MINT_IN_BREAK;
3824                 }
3825                 MINT_IN_CASE(MINT_STRMFLD_VT) {
3826                         MonoClassField *field;
3827
3828                         o = sp [-2].data.p;
3829                         if (!o)
3830                                 THROW_EX (mono_get_exception_null_reference (), ip);
3831                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3832                         i32 = READ32(ip + 2);
3833                         ip += 4;
3834
3835 #ifndef DISABLE_REMOTING
3836                         if (mono_object_is_transparent_proxy (o)) {
3837                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3838                                 mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
3839                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3840                         } else
3841 #endif
3842                                 memcpy((char*)o + field->offset, sp [-1].data.p, i32);
3843
3844                         sp -= 2;
3845                         vt_sp -= (i32 + 7) & ~7;
3846                         MINT_IN_BREAK;
3847                 }
3848                 MINT_IN_CASE(MINT_LDSFLDA) {
3849                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
3850                         sp->data.p = mono_class_static_field_address (rtm->domain, field);
3851                         ip += 2;
3852                         ++sp;
3853                         MINT_IN_BREAK;
3854                 }
3855                 MINT_IN_CASE(MINT_LDSFLD) {
3856                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3857                         gpointer addr = mono_class_static_field_address (rtm->domain, field);
3858                         stackval_from_data (field->type, sp, addr, FALSE);
3859                         ip += 2;
3860                         ++sp;
3861                         MINT_IN_BREAK;
3862                 }
3863                 MINT_IN_CASE(MINT_LDSFLD_VT) {
3864                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3865                         gpointer addr = mono_class_static_field_address (rtm->domain, field);
3866                         int size = READ32 (ip + 2);
3867                         ip += 4;
3868
3869                         sp->data.p = vt_sp;
3870                         vt_sp += (size + 7) & ~7;
3871                         stackval_from_data (field->type, sp, addr, FALSE);
3872                         ++sp;
3873                         MINT_IN_BREAK;
3874                 }
3875                 MINT_IN_CASE(MINT_STSFLD) {
3876                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3877                         gpointer addr = mono_class_static_field_address (rtm->domain, field);
3878                         ip += 2;
3879                         --sp;
3880                         stackval_to_data (field->type, sp, addr, FALSE);
3881                         MINT_IN_BREAK;
3882                 }
3883                 MINT_IN_CASE(MINT_STSFLD_VT) {
3884                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3885                         gpointer addr = mono_class_static_field_address (rtm->domain, field);
3886                         int size = READ32 (ip + 2);
3887                         ip += 4;
3888
3889                         --sp;
3890                         stackval_to_data (field->type, sp, addr, FALSE);
3891                         vt_sp -= (size + 7) & ~7;
3892                         MINT_IN_BREAK;
3893                 }
3894                 MINT_IN_CASE(MINT_STOBJ_VT) {
3895                         int size;
3896                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3897                         ip += 2;
3898                         size = mono_class_value_size (c, NULL);
3899                         memcpy(sp [-2].data.p, sp [-1].data.p, size);
3900                         vt_sp -= (size + 7) & ~7;
3901                         sp -= 2;
3902                         MINT_IN_BREAK;
3903                 }
3904                 MINT_IN_CASE(MINT_STOBJ) {
3905                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3906                         ip += 2;
3907
3908                         g_assert (!c->byval_arg.byref);
3909                         if (MONO_TYPE_IS_REFERENCE (&c->byval_arg))
3910                                 mono_gc_wbarrier_generic_store (sp [-2].data.p, sp [-1].data.p);
3911                         else
3912                                 stackval_from_data (&c->byval_arg, sp [-2].data.p, (char *) &sp [-1].data.p, FALSE);
3913                         sp -= 2;
3914                         MINT_IN_BREAK;
3915                 }
3916                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_R8)
3917                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
3918                                 THROW_EX (mono_get_exception_overflow (), ip);
3919                         sp [-1].data.i = (guint32)sp [-1].data.f;
3920                         ++ip;
3921                         MINT_IN_BREAK;
3922                 MINT_IN_CASE(MINT_CONV_OVF_U8_I4)
3923                         if (sp [-1].data.i < 0)
3924                                 THROW_EX (mono_get_exception_overflow (), ip);
3925                         sp [-1].data.l = sp [-1].data.i;
3926                         ++ip;
3927                         MINT_IN_BREAK;
3928                 MINT_IN_CASE(MINT_CONV_OVF_U8_I8)
3929                         if (sp [-1].data.l < 0)
3930                                 THROW_EX (mono_get_exception_overflow (), ip);
3931                         ++ip;
3932                         MINT_IN_BREAK;
3933                 MINT_IN_CASE(MINT_CONV_OVF_I8_U8)
3934                         if ((guint64) sp [-1].data.l > MYGINT64_MAX)
3935                                 THROW_EX (mono_get_exception_overflow (), ip);
3936                         ++ip;
3937                         MINT_IN_BREAK;
3938                 MINT_IN_CASE(MINT_CONV_OVF_U8_R8)
3939                 MINT_IN_CASE(MINT_CONV_OVF_I8_UN_R8)
3940                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGINT64_MAX)
3941                                 THROW_EX (mono_get_exception_overflow (), ip);
3942                         sp [-1].data.l = (guint64)sp [-1].data.f;
3943                         ++ip;
3944                         MINT_IN_BREAK;
3945                 MINT_IN_CASE(MINT_CONV_OVF_I8_R8)
3946                         if (sp [-1].data.f < MYGINT64_MIN || sp [-1].data.f > MYGINT64_MAX)
3947                                 THROW_EX (mono_get_exception_overflow (), ip);
3948                         sp [-1].data.l = (gint64)sp [-1].data.f;
3949                         ++ip;
3950                         MINT_IN_BREAK;
3951                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_I8)
3952                         if ((mono_u)sp [-1].data.l > MYGUINT32_MAX)
3953                                 THROW_EX (mono_get_exception_overflow (), ip);
3954                         sp [-1].data.i = (mono_u)sp [-1].data.l;
3955                         ++ip;
3956                         MINT_IN_BREAK;
3957                 MINT_IN_CASE(MINT_BOX) {
3958                         c = rtm->data_items [* (guint16 *)(ip + 1)];
3959                         guint16 offset = * (guint16 *)(ip + 2);
3960
3961                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
3962                                 int size = mono_class_value_size (c, NULL);
3963                                 sp [-1 - offset].data.p = mono_value_box_checked (rtm->domain, c, sp [-1 - offset].data.p, &error);
3964                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3965                                 size = (size + 7) & ~7;
3966                                 vt_sp -= size;
3967                         } else {
3968                                 stackval_to_data (&c->byval_arg, &sp [-1 - offset], (char *) &sp [-1 - offset], FALSE);
3969                                 sp [-1 - offset].data.p = mono_value_box_checked (rtm->domain, c, &sp [-1 - offset], &error);
3970                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3971                         }
3972                         ip += 3;
3973                         MINT_IN_BREAK;
3974                 }
3975                 MINT_IN_CASE(MINT_NEWARR)
3976                         sp [-1].data.p = (MonoObject*) mono_array_new_checked (rtm->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i, &error);
3977                         if (!mono_error_ok (&error)) {
3978                                 THROW_EX (mono_error_convert_to_exception (&error), ip);
3979                         }
3980                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3981                         ip += 2;
3982                         /*if (profiling_classes) {
3983                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
3984                                 count++;
3985                                 g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
3986                         }*/
3987
3988                         MINT_IN_BREAK;
3989                 MINT_IN_CASE(MINT_LDLEN)
3990                         o = sp [-1].data.p;
3991                         if (!o)
3992                                 THROW_EX (mono_get_exception_null_reference (), ip);
3993                         sp [-1].data.nati = mono_array_length ((MonoArray *)o);
3994                         ++ip;
3995                         MINT_IN_BREAK;
3996                 MINT_IN_CASE(MINT_GETCHR) {
3997                         MonoString *s;
3998                         s = sp [-2].data.p;
3999                         if (!s)
4000                                 THROW_EX (mono_get_exception_null_reference (), ip);
4001                         i32 = sp [-1].data.i;
4002                         if (i32 < 0 || i32 >= mono_string_length (s))
4003                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
4004                         --sp;
4005                         sp [-1].data.i = mono_string_chars(s)[i32];
4006                         ++ip;
4007                         MINT_IN_BREAK;
4008                 }
4009                 MINT_IN_CASE(MINT_STRLEN)
4010                         ++ip;
4011                         o = sp [-1].data.p;
4012                         if (!o)
4013                                 THROW_EX (mono_get_exception_null_reference (), ip);
4014                         sp [-1].data.i = mono_string_length ((MonoString*) o);
4015                         MINT_IN_BREAK;
4016                 MINT_IN_CASE(MINT_ARRAY_RANK)
4017                         o = sp [-1].data.p;
4018                         if (!o)
4019                                 THROW_EX (mono_get_exception_null_reference (), ip);
4020                         sp [-1].data.i = mono_object_class (sp [-1].data.p)->rank;
4021                         ip++;
4022                         MINT_IN_BREAK;
4023                 MINT_IN_CASE(MINT_LDELEMA)
4024                 MINT_IN_CASE(MINT_LDELEMA_TC) {
4025                         gboolean needs_typecheck = *ip == MINT_LDELEMA_TC;
4026                         
4027                         MonoClass *klass = rtm->data_items [*(guint16 *) (ip + 1)];
4028                         guint16 numargs = *(guint16 *) (ip + 2);
4029                         ip += 3;
4030                         sp -= numargs;
4031
4032                         o = sp [0].data.p;
4033                         sp->data.p = ves_array_element_address (frame, klass, (MonoArray *) o, &sp [1], needs_typecheck);
4034                         if (frame->ex)
4035                                 THROW_EX (frame->ex, ip);
4036                         ++sp;
4037
4038                         MINT_IN_BREAK;
4039                 }
4040                 MINT_IN_CASE(MINT_LDELEM_I1) /* fall through */
4041                 MINT_IN_CASE(MINT_LDELEM_U1) /* fall through */
4042                 MINT_IN_CASE(MINT_LDELEM_I2) /* fall through */
4043                 MINT_IN_CASE(MINT_LDELEM_U2) /* fall through */
4044                 MINT_IN_CASE(MINT_LDELEM_I4) /* fall through */
4045                 MINT_IN_CASE(MINT_LDELEM_U4) /* fall through */
4046                 MINT_IN_CASE(MINT_LDELEM_I8)  /* fall through */
4047                 MINT_IN_CASE(MINT_LDELEM_I)  /* fall through */
4048                 MINT_IN_CASE(MINT_LDELEM_R4) /* fall through */
4049                 MINT_IN_CASE(MINT_LDELEM_R8) /* fall through */
4050                 MINT_IN_CASE(MINT_LDELEM_REF) /* fall through */
4051                 MINT_IN_CASE(MINT_LDELEM_VT) {
4052                         MonoArray *o;
4053                         mono_u aindex;
4054
4055                         sp -= 2;
4056
4057                         o = sp [0].data.p;
4058                         if (!o)
4059                                 THROW_EX (mono_get_exception_null_reference (), ip);
4060
4061                         aindex = sp [1].data.i;
4062                         if (aindex >= mono_array_length (o))
4063                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
4064
4065                         /*
4066                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
4067                          */
4068                         switch (*ip) {
4069                         case MINT_LDELEM_I1:
4070                                 sp [0].data.i = mono_array_get (o, gint8, aindex);
4071                                 break;
4072                         case MINT_LDELEM_U1:
4073                                 sp [0].data.i = mono_array_get (o, guint8, aindex);
4074                                 break;
4075                         case MINT_LDELEM_I2:
4076                                 sp [0].data.i = mono_array_get (o, gint16, aindex);
4077                                 break;
4078                         case MINT_LDELEM_U2:
4079                                 sp [0].data.i = mono_array_get (o, guint16, aindex);
4080                                 break;
4081                         case MINT_LDELEM_I:
4082                                 sp [0].data.nati = mono_array_get (o, mono_i, aindex);
4083                                 break;
4084                         case MINT_LDELEM_I4:
4085                                 sp [0].data.i = mono_array_get (o, gint32, aindex);
4086                                 break;
4087                         case MINT_LDELEM_U4:
4088                                 sp [0].data.i = mono_array_get (o, guint32, aindex);
4089                                 break;
4090                         case MINT_LDELEM_I8:
4091                                 sp [0].data.l = mono_array_get (o, guint64, aindex);
4092                                 break;
4093                         case MINT_LDELEM_R4:
4094                                 sp [0].data.f = mono_array_get (o, float, aindex);
4095                                 break;
4096                         case MINT_LDELEM_R8:
4097                                 sp [0].data.f = mono_array_get (o, double, aindex);
4098                                 break;
4099                         case MINT_LDELEM_REF:
4100                                 sp [0].data.p = mono_array_get (o, gpointer, aindex);
4101                                 break;
4102                         case MINT_LDELEM_VT: {
4103                                 MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
4104                                 i32 = READ32 (ip + 2);
4105                                 char *src_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
4106                                 sp [0].data.vt = vt_sp;
4107                                 stackval_from_data (&klass_vt->byval_arg, sp, src_addr, FALSE);
4108                                 vt_sp += (i32 + 7) & ~7;
4109                                 ip += 3;
4110                                 break;
4111                         }
4112                         default:
4113                                 ves_abort();
4114                         }
4115
4116                         ++ip;
4117                         ++sp;
4118                         MINT_IN_BREAK;
4119                 }
4120                 MINT_IN_CASE(MINT_STELEM_I)  /* fall through */
4121                 MINT_IN_CASE(MINT_STELEM_I1) /* fall through */ 
4122                 MINT_IN_CASE(MINT_STELEM_U1) /* fall through */
4123                 MINT_IN_CASE(MINT_STELEM_I2) /* fall through */
4124                 MINT_IN_CASE(MINT_STELEM_U2) /* fall through */
4125                 MINT_IN_CASE(MINT_STELEM_I4) /* fall through */
4126                 MINT_IN_CASE(MINT_STELEM_I8) /* fall through */
4127                 MINT_IN_CASE(MINT_STELEM_R4) /* fall through */
4128                 MINT_IN_CASE(MINT_STELEM_R8) /* fall through */
4129                 MINT_IN_CASE(MINT_STELEM_REF) /* fall through */
4130                 MINT_IN_CASE(MINT_STELEM_VT) {
4131                         mono_u aindex;
4132
4133                         sp -= 3;
4134
4135                         o = sp [0].data.p;
4136                         if (!o)
4137                                 THROW_EX (mono_get_exception_null_reference (), ip);
4138
4139                         aindex = sp [1].data.i;
4140                         if (aindex >= mono_array_length ((MonoArray *)o))
4141                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
4142
4143                         switch (*ip) {
4144                         case MINT_STELEM_I:
4145                                 mono_array_set ((MonoArray *)o, mono_i, aindex, sp [2].data.nati);
4146                                 break;
4147                         case MINT_STELEM_I1:
4148                                 mono_array_set ((MonoArray *)o, gint8, aindex, sp [2].data.i);
4149                                 break;
4150                         case MINT_STELEM_U1:
4151                                 mono_array_set ((MonoArray *) o, guint8, aindex, sp [2].data.i);
4152                                 break;
4153                         case MINT_STELEM_I2:
4154                                 mono_array_set ((MonoArray *)o, gint16, aindex, sp [2].data.i);
4155                                 break;
4156                         case MINT_STELEM_U2:
4157                                 mono_array_set ((MonoArray *)o, guint16, aindex, sp [2].data.i);
4158                                 break;
4159                         case MINT_STELEM_I4:
4160                                 mono_array_set ((MonoArray *)o, gint32, aindex, sp [2].data.i);
4161                                 break;
4162                         case MINT_STELEM_I8:
4163                                 mono_array_set ((MonoArray *)o, gint64, aindex, sp [2].data.l);
4164                                 break;
4165                         case MINT_STELEM_R4:
4166                                 mono_array_set ((MonoArray *)o, float, aindex, sp [2].data.f);
4167                                 break;
4168                         case MINT_STELEM_R8:
4169                                 mono_array_set ((MonoArray *)o, double, aindex, sp [2].data.f);
4170                                 break;
4171                         case MINT_STELEM_REF: {
4172                                 MonoObject *isinst_obj = mono_object_isinst_checked (sp [2].data.p, mono_object_class (o)->element_class, &error);
4173                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4174                                 if (sp [2].data.p && !isinst_obj)
4175                                         THROW_EX (mono_get_exception_array_type_mismatch (), ip);
4176                                 mono_array_setref ((MonoArray *) o, aindex, sp [2].data.p);
4177                                 break;
4178                         }
4179                         case MINT_STELEM_VT: {
4180                                 MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
4181                                 i32 = READ32 (ip + 2);
4182                                 char *dst_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
4183
4184                                 stackval_to_data (&klass_vt->byval_arg, &sp [2], dst_addr, FALSE);
4185                                 vt_sp -= (i32 + 7) & ~7;
4186                                 ip += 3;
4187                                 break;
4188                         }
4189                         default:
4190                                 ves_abort();
4191                         }
4192
4193                         ++ip;
4194                         MINT_IN_BREAK;
4195                 }
4196                 MINT_IN_CASE(MINT_CONV_OVF_I4_U4)
4197                         if (sp [-1].data.i < 0)
4198                                 THROW_EX (mono_get_exception_overflow (), ip);
4199                         ++ip;
4200                         MINT_IN_BREAK;
4201                 MINT_IN_CASE(MINT_CONV_OVF_I4_I8)
4202                         if (sp [-1].data.l < MYGINT32_MIN || sp [-1].data.l > MYGINT32_MAX)
4203                                 THROW_EX (mono_get_exception_overflow (), ip);
4204                         sp [-1].data.i = (gint32) sp [-1].data.l;
4205                         ++ip;
4206                         MINT_IN_BREAK;
4207                 MINT_IN_CASE(MINT_CONV_OVF_I4_U8)
4208                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGINT32_MAX)
4209                                 THROW_EX (mono_get_exception_overflow (), ip);
4210                         sp [-1].data.i = (gint32) sp [-1].data.l;
4211                         ++ip;
4212                         MINT_IN_BREAK;
4213                 MINT_IN_CASE(MINT_CONV_OVF_I4_R8)
4214                         if (sp [-1].data.f < MYGINT32_MIN || sp [-1].data.f > MYGINT32_MAX)
4215                                 THROW_EX (mono_get_exception_overflow (), ip);
4216                         sp [-1].data.i = (gint32) sp [-1].data.f;
4217                         ++ip;
4218                         MINT_IN_BREAK;
4219                 MINT_IN_CASE(MINT_CONV_OVF_U4_I4)
4220                         if (sp [-1].data.i < 0)
4221                                 THROW_EX (mono_get_exception_overflow (), ip);
4222                         ++ip;
4223                         MINT_IN_BREAK;
4224                 MINT_IN_CASE(MINT_CONV_OVF_U4_I8)
4225                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGUINT32_MAX)
4226                                 THROW_EX (mono_get_exception_overflow (), ip);
4227                         sp [-1].data.i = (guint32) sp [-1].data.l;
4228                         ++ip;
4229                         MINT_IN_BREAK;
4230                 MINT_IN_CASE(MINT_CONV_OVF_U4_R8)
4231                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
4232                                 THROW_EX (mono_get_exception_overflow (), ip);
4233                         sp [-1].data.i = (guint32) sp [-1].data.f;
4234                         ++ip;
4235                         MINT_IN_BREAK;
4236                 MINT_IN_CASE(MINT_CONV_OVF_I2_I4)
4237                         if (sp [-1].data.i < -32768 || sp [-1].data.i > 32767)
4238                                 THROW_EX (mono_get_exception_overflow (), ip);
4239                         ++ip;
4240                         MINT_IN_BREAK;
4241                 MINT_IN_CASE(MINT_CONV_OVF_I2_I8)
4242                         if (sp [-1].data.l < -32768 || sp [-1].data.l > 32767)
4243                                 THROW_EX (mono_get_exception_overflow (), ip);
4244                         sp [-1].data.i = (gint16) sp [-1].data.l;
4245                         ++ip;
4246                         MINT_IN_BREAK;
4247                 MINT_IN_CASE(MINT_CONV_OVF_I2_R8)
4248                         if (sp [-1].data.f < -32768 || sp [-1].data.f > 32767)
4249                                 THROW_EX (mono_get_exception_overflow (), ip);
4250                         sp [-1].data.i = (gint16) sp [-1].data.f;
4251                         ++ip;
4252                         MINT_IN_BREAK;
4253                 MINT_IN_CASE(MINT_CONV_OVF_U2_I4)
4254                         if (sp [-1].data.i < 0 || sp [-1].data.i > 65535)
4255                                 THROW_EX (mono_get_exception_overflow (), ip);
4256                         ++ip;
4257                         MINT_IN_BREAK;
4258                 MINT_IN_CASE(MINT_CONV_OVF_U2_I8)
4259                         if (sp [-1].data.l < 0 || sp [-1].data.l > 65535)
4260                                 THROW_EX (mono_get_exception_overflow (), ip);
4261                         sp [-1].data.i = (guint16) sp [-1].data.l;
4262                         ++ip;
4263                         MINT_IN_BREAK;
4264                 MINT_IN_CASE(MINT_CONV_OVF_U2_R8)
4265                         if (sp [-1].data.f < 0 || sp [-1].data.f > 65535)
4266                                 THROW_EX (mono_get_exception_overflow (), ip);
4267                         sp [-1].data.i = (guint16) sp [-1].data.f;
4268                         ++ip;
4269                         MINT_IN_BREAK;
4270                 MINT_IN_CASE(MINT_CONV_OVF_I1_I4)
4271                         if (sp [-1].data.i < -128 || sp [-1].data.i > 127)
4272                                 THROW_EX (mono_get_exception_overflow (), ip);
4273                         ++ip;
4274                         MINT_IN_BREAK;
4275                 MINT_IN_CASE(MINT_CONV_OVF_I1_I8)
4276                         if (sp [-1].data.l < -128 || sp [-1].data.l > 127)
4277                                 THROW_EX (mono_get_exception_overflow (), ip);
4278                         sp [-1].data.i = (gint8) sp [-1].data.l;
4279                         ++ip;
4280                         MINT_IN_BREAK;
4281                 MINT_IN_CASE(MINT_CONV_OVF_I1_R8)
4282                         if (sp [-1].data.f < -128 || sp [-1].data.f > 127)
4283                                 THROW_EX (mono_get_exception_overflow (), ip);
4284                         sp [-1].data.i = (gint8) sp [-1].data.f;
4285                         ++ip;
4286                         MINT_IN_BREAK;
4287                 MINT_IN_CASE(MINT_CONV_OVF_U1_I4)
4288                         if (sp [-1].data.i < 0 || sp [-1].data.i > 255)
4289                                 THROW_EX (mono_get_exception_overflow (), ip);
4290                         ++ip;
4291                         MINT_IN_BREAK;
4292                 MINT_IN_CASE(MINT_CONV_OVF_U1_I8)
4293                         if (sp [-1].data.l < 0 || sp [-1].data.l > 255)
4294                                 THROW_EX (mono_get_exception_overflow (), ip);
4295                         sp [-1].data.i = (guint8) sp [-1].data.l;
4296                         ++ip;
4297                         MINT_IN_BREAK;
4298                 MINT_IN_CASE(MINT_CONV_OVF_U1_R8)
4299                         if (sp [-1].data.f < 0 || sp [-1].data.f > 255)
4300                                 THROW_EX (mono_get_exception_overflow (), ip);
4301                         sp [-1].data.i = (guint8) sp [-1].data.f;
4302                         ++ip;
4303                         MINT_IN_BREAK;
4304 #if 0
4305                 MINT_IN_CASE(MINT_LDELEM) 
4306                 MINT_IN_CASE(MINT_STELEM) 
4307                 MINT_IN_CASE(MINT_UNBOX_ANY) 
4308 #endif
4309                 MINT_IN_CASE(MINT_CKFINITE)
4310                         if (!isfinite(sp [-1].data.f))
4311                                 THROW_EX (mono_get_exception_arithmetic (), ip);
4312                         ++ip;
4313                         MINT_IN_BREAK;
4314                 MINT_IN_CASE(MINT_MKREFANY) {
4315                         c = rtm->data_items [*(guint16 *)(ip + 1)];
4316
4317                         /* The value address is on the stack */
4318                         gpointer addr = sp [-1].data.p;
4319                         /* Push the typedref value on the stack */
4320                         sp [-1].data.p = vt_sp;
4321                         vt_sp += sizeof (MonoTypedRef);
4322
4323                         MonoTypedRef *tref = sp [-1].data.p;
4324                         tref->klass = c;
4325                         tref->type = &c->byval_arg;
4326                         tref->value = addr;
4327
4328                         ip += 2;
4329                         MINT_IN_BREAK;
4330                 }
4331                 MINT_IN_CASE(MINT_REFANYTYPE) {
4332                         MonoTypedRef *tref = sp [-1].data.p;
4333                         MonoType *type = tref->type;
4334
4335                         vt_sp -= sizeof (MonoTypedRef);
4336                         sp [-1].data.p = vt_sp;
4337                         vt_sp += 8;
4338                         *(gpointer*)sp [-1].data.p = type;
4339                         ip ++;
4340                         MINT_IN_BREAK;
4341                 }
4342                 MINT_IN_CASE(MINT_REFANYVAL) {
4343                         MonoTypedRef *tref = sp [-1].data.p;
4344                         gpointer addr = tref->value;
4345
4346                         vt_sp -= sizeof (MonoTypedRef);
4347
4348                         sp [-1].data.p = addr;
4349                         ip ++;
4350                         MINT_IN_BREAK;
4351                 }
4352                 MINT_IN_CASE(MINT_LDTOKEN)
4353                         sp->data.p = vt_sp;
4354                         vt_sp += 8;
4355                         * (gpointer *)sp->data.p = rtm->data_items[*(guint16 *)(ip + 1)];
4356                         ip += 2;
4357                         ++sp;
4358                         MINT_IN_BREAK;
4359                 MINT_IN_CASE(MINT_ADD_OVF_I4)
4360                         if (CHECK_ADD_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
4361                                 THROW_EX (mono_get_exception_overflow (), ip);
4362                         BINOP(i, +);
4363                         MINT_IN_BREAK;
4364                 MINT_IN_CASE(MINT_ADD_OVF_I8)
4365                         if (CHECK_ADD_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
4366                                 THROW_EX (mono_get_exception_overflow (), ip);
4367                         BINOP(l, +);
4368                         MINT_IN_BREAK;
4369                 MINT_IN_CASE(MINT_ADD_OVF_UN_I4)
4370                         if (CHECK_ADD_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
4371                                 THROW_EX (mono_get_exception_overflow (), ip);
4372                         BINOP_CAST(i, +, guint32);
4373                         MINT_IN_BREAK;
4374                 MINT_IN_CASE(MINT_ADD_OVF_UN_I8)
4375                         if (CHECK_ADD_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
4376                                 THROW_EX (mono_get_exception_overflow (), ip);
4377                         BINOP_CAST(l, +, guint64);
4378                         MINT_IN_BREAK;
4379                 MINT_IN_CASE(MINT_MUL_OVF_I4)
4380                         if (CHECK_MUL_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
4381                                 THROW_EX (mono_get_exception_overflow (), ip);
4382                         BINOP(i, *);
4383                         MINT_IN_BREAK;
4384                 MINT_IN_CASE(MINT_MUL_OVF_I8)
4385                         if (CHECK_MUL_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
4386                                 THROW_EX (mono_get_exception_overflow (), ip);
4387                         BINOP(l, *);
4388                         MINT_IN_BREAK;
4389                 MINT_IN_CASE(MINT_MUL_OVF_UN_I4)
4390                         if (CHECK_MUL_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
4391                                 THROW_EX (mono_get_exception_overflow (), ip);
4392                         BINOP_CAST(i, *, guint32);
4393                         MINT_IN_BREAK;
4394                 MINT_IN_CASE(MINT_MUL_OVF_UN_I8)
4395                         if (CHECK_MUL_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
4396                                 THROW_EX (mono_get_exception_overflow (), ip);
4397                         BINOP_CAST(l, *, guint64);
4398                         MINT_IN_BREAK;
4399                 MINT_IN_CASE(MINT_SUB_OVF_I4)
4400                         if (CHECK_SUB_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
4401                                 THROW_EX (mono_get_exception_overflow (), ip);
4402                         BINOP(i, -);
4403                         MINT_IN_BREAK;
4404                 MINT_IN_CASE(MINT_SUB_OVF_I8)
4405                         if (CHECK_SUB_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
4406                                 THROW_EX (mono_get_exception_overflow (), ip);
4407                         BINOP(l, -);
4408                         MINT_IN_BREAK;
4409                 MINT_IN_CASE(MINT_SUB_OVF_UN_I4)
4410                         if (CHECK_SUB_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
4411                                 THROW_EX (mono_get_exception_overflow (), ip);
4412                         BINOP_CAST(i, -, guint32);
4413                         MINT_IN_BREAK;
4414                 MINT_IN_CASE(MINT_SUB_OVF_UN_I8)
4415                         if (CHECK_SUB_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
4416                                 THROW_EX (mono_get_exception_overflow (), ip);
4417                         BINOP_CAST(l, -, guint64);
4418                         MINT_IN_BREAK;
4419                 MINT_IN_CASE(MINT_ENDFINALLY)
4420                         ip ++;
4421                         int clause_index = *ip;
4422                         if (clause_index == exit_at_finally)
4423                                 goto exit_frame;
4424                         while (sp > frame->stack) {
4425                                 --sp;
4426                         }
4427                         if (finally_ips) {
4428                                 ip = finally_ips->data;
4429                                 finally_ips = g_slist_remove (finally_ips, ip);
4430                                 goto main_loop;
4431                         }
4432                         if (frame->ex)
4433                                 goto handle_catch;
4434                         ves_abort();
4435                         MINT_IN_BREAK;
4436                 MINT_IN_CASE(MINT_LEAVE) /* Fall through */
4437                 MINT_IN_CASE(MINT_LEAVE_S)
4438                         while (sp > frame->stack) {
4439                                 --sp;
4440                         }
4441                         frame->ip = ip;
4442                         if (*ip == MINT_LEAVE_S) {
4443                                 ip += (short) *(ip + 1);
4444                         } else {
4445                                 ip += (gint32) READ32 (ip + 1);
4446                         }
4447                         endfinally_ip = ip;
4448                         if (frame->ex_handler != NULL && MONO_OFFSET_IN_HANDLER(frame->ex_handler, frame->ip - rtm->code)) {
4449                                 frame->ex_handler = NULL;
4450                                 frame->ex = NULL;
4451                         }
4452                         goto handle_finally;
4453                         MINT_IN_BREAK;
4454                 MINT_IN_CASE(MINT_ICALL_V_V) 
4455                 MINT_IN_CASE(MINT_ICALL_V_P)
4456                 MINT_IN_CASE(MINT_ICALL_P_V) 
4457                 MINT_IN_CASE(MINT_ICALL_P_P)
4458                 MINT_IN_CASE(MINT_ICALL_PP_V)
4459                 MINT_IN_CASE(MINT_ICALL_PI_V)
4460                 MINT_IN_CASE(MINT_ICALL_PP_P)
4461                 MINT_IN_CASE(MINT_ICALL_PI_P)
4462                 MINT_IN_CASE(MINT_ICALL_PPP_V)
4463                 MINT_IN_CASE(MINT_ICALL_PPI_V)
4464                         sp = do_icall (context, *ip, sp, rtm->data_items [*(guint16 *)(ip + 1)]);
4465                         if (*mono_thread_interruption_request_flag ()) {
4466                                 MonoException *exc = mono_thread_interruption_checkpoint ();
4467                                 if (exc) {
4468                                         frame->ex = exc;
4469                                         context->search_for_handler = 1;
4470                                 }
4471                         }
4472                         if (frame->ex != NULL)
4473                                 goto handle_exception;
4474                         ip += 2;
4475                         MINT_IN_BREAK;
4476                 MINT_IN_CASE(MINT_MONO_LDPTR) 
4477                         sp->data.p = rtm->data_items [*(guint16 *)(ip + 1)];
4478                         ip += 2;
4479                         ++sp;
4480                         MINT_IN_BREAK;
4481                 MINT_IN_CASE(MINT_MONO_NEWOBJ)
4482                         sp->data.p = mono_object_new_checked (rtm->domain, rtm->data_items [*(guint16 *)(ip + 1)], &error);
4483                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4484                         ip += 2;
4485                         sp++;
4486                         MINT_IN_BREAK;
4487                 MINT_IN_CASE(MINT_MONO_FREE)
4488                         ++ip;
4489                         --sp;
4490                         g_error ("that doesn't seem right");
4491                         g_free (sp->data.p);
4492                         MINT_IN_BREAK;
4493                 MINT_IN_CASE(MINT_MONO_RETOBJ)
4494                         ++ip;
4495                         sp--;
4496                         stackval_from_data (mono_method_signature (frame->imethod->method)->ret, frame->retval, sp->data.p,
4497                              mono_method_signature (frame->imethod->method)->pinvoke);
4498                         if (sp > frame->stack)
4499                                 g_warning ("retobj: more values on stack: %d", sp-frame->stack);
4500                         goto exit_frame;
4501                 MINT_IN_CASE(MINT_MONO_TLS) {
4502                         MonoTlsKey key = *(gint32 *)(ip + 1);
4503                         sp->data.p = ((gpointer (*)()) mono_tls_get_tls_getter (key, FALSE)) ();
4504                         sp++;
4505                         ip += 3;
4506                         MINT_IN_BREAK;
4507                 }
4508                 MINT_IN_CASE(MINT_MONO_MEMORY_BARRIER) {
4509                         ++ip;
4510                         mono_memory_barrier ();
4511                         MINT_IN_BREAK;
4512                 }
4513                 MINT_IN_CASE(MINT_MONO_JIT_ATTACH) {
4514                         ++ip;
4515
4516                         context->original_domain = NULL;
4517                         MonoDomain *tls_domain = (MonoDomain *) ((gpointer (*)()) mono_tls_get_tls_getter (TLS_KEY_DOMAIN, FALSE)) ();
4518                         gpointer tls_jit = ((gpointer (*)()) mono_tls_get_tls_getter (TLS_KEY_DOMAIN, FALSE)) ();
4519
4520                         if (tls_domain != rtm->domain || !tls_jit)
4521                                 context->original_domain = mono_jit_thread_attach (rtm->domain);
4522                         MINT_IN_BREAK;
4523                 }
4524                 MINT_IN_CASE(MINT_MONO_JIT_DETACH)
4525                         ++ip;
4526                         mono_jit_set_domain (context->original_domain);
4527                         MINT_IN_BREAK;
4528                 MINT_IN_CASE(MINT_MONO_LDDOMAIN)
4529                         sp->data.p = mono_domain_get ();
4530                         ++sp;
4531                         ++ip;
4532                         MINT_IN_BREAK;
4533                 MINT_IN_CASE(MINT_SDB_INTR_LOC)
4534                         if (G_UNLIKELY (ss_enabled)) {
4535                                 static void (*ss_tramp) (void);
4536
4537                                 if (!ss_tramp) {
4538                                         void *tramp = mini_get_single_step_trampoline ();
4539                                         mono_memory_barrier ();
4540                                         ss_tramp = tramp;
4541                                 }
4542
4543                                 /*
4544                                  * Make this point to the MINT_SDB_SEQ_POINT instruction which follows this since
4545                                  * the address of that instruction is stored as the seq point address.
4546                                  */
4547                                 frame->ip = ip + 1;
4548
4549                                 /*
4550                                  * Use the same trampoline as the JIT. This ensures that
4551                                  * the debugger has the context for the last interpreter
4552                                  * native frame.
4553                                  */
4554                                 do_debugger_tramp (ss_tramp, frame);
4555
4556                                 if (context->has_resume_state) {
4557                                         if (frame == context->handler_frame)
4558                                                 SET_RESUME_STATE (context);
4559                                         else
4560                                                 goto exit_frame;
4561                                 }
4562                         }
4563                         ++ip;
4564                         MINT_IN_BREAK;
4565                 MINT_IN_CASE(MINT_SDB_SEQ_POINT)
4566                         /* Just a placeholder for a breakpoint */
4567                         ++ip;
4568                         MINT_IN_BREAK;
4569                 MINT_IN_CASE(MINT_SDB_BREAKPOINT) {
4570                         static void (*bp_tramp) (void);
4571                         if (!bp_tramp) {
4572                                 void *tramp = mini_get_breakpoint_trampoline ();
4573                                 mono_memory_barrier ();
4574                                 bp_tramp = tramp;
4575                         }
4576
4577                         frame->ip = ip;
4578
4579                         /* Use the same trampoline as the JIT */
4580                         do_debugger_tramp (bp_tramp, frame);
4581
4582                         if (context->has_resume_state) {
4583                                 if (frame == context->handler_frame)
4584                                         SET_RESUME_STATE (context);
4585                                 else
4586                                         goto exit_frame;
4587                         }
4588
4589                         ++ip;
4590                         MINT_IN_BREAK;
4591                 }
4592
4593 #define RELOP(datamem, op) \
4594         --sp; \
4595         sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
4596         ++ip;
4597                 MINT_IN_CASE(MINT_CEQ_I4)
4598                         RELOP(i, ==);
4599                         MINT_IN_BREAK;
4600                 MINT_IN_CASE(MINT_CEQ0_I4)
4601                         sp [-1].data.i = (sp [-1].data.i == 0);
4602                         ++ip;
4603                         MINT_IN_BREAK;
4604                 MINT_IN_CASE(MINT_CEQ_I8)
4605                         RELOP(l, ==);
4606                         MINT_IN_BREAK;
4607                 MINT_IN_CASE(MINT_CEQ_R8)
4608                         --sp; 
4609                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4610                                 sp [-1].data.i = 0;
4611                         else
4612                                 sp [-1].data.i = sp [-1].data.f == sp [0].data.f;
4613                         ++ip;
4614                         MINT_IN_BREAK;
4615                 MINT_IN_CASE(MINT_CGT_I4)
4616                         RELOP(i, >);
4617                         MINT_IN_BREAK;
4618                 MINT_IN_CASE(MINT_CGT_I8)
4619                         RELOP(l, >);
4620                         MINT_IN_BREAK;
4621                 MINT_IN_CASE(MINT_CGT_R8)
4622                         --sp; 
4623                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4624                                 sp [-1].data.i = 0;
4625                         else
4626                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
4627                         ++ip;
4628                         MINT_IN_BREAK;
4629
4630 #define RELOP_CAST(datamem, op, type) \
4631         --sp; \
4632         sp [-1].data.i = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
4633         ++ip;
4634
4635                 MINT_IN_CASE(MINT_CGT_UN_I4)
4636                         RELOP_CAST(i, >, guint32);
4637                         MINT_IN_BREAK;
4638                 MINT_IN_CASE(MINT_CGT_UN_I8)
4639                         RELOP_CAST(l, >, guint64);
4640                         MINT_IN_BREAK;
4641                 MINT_IN_CASE(MINT_CGT_UN_R8)
4642                         --sp; 
4643                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4644                                 sp [-1].data.i = 1;
4645                         else
4646                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
4647                         ++ip;
4648                         MINT_IN_BREAK;
4649                 MINT_IN_CASE(MINT_CLT_I4)
4650                         RELOP(i, <);
4651                         MINT_IN_BREAK;
4652                 MINT_IN_CASE(MINT_CLT_I8)
4653                         RELOP(l, <);
4654                         MINT_IN_BREAK;
4655                 MINT_IN_CASE(MINT_CLT_R8)
4656                         --sp; 
4657                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4658                                 sp [-1].data.i = 0;
4659                         else
4660                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
4661                         ++ip;
4662                         MINT_IN_BREAK;
4663                 MINT_IN_CASE(MINT_CLT_UN_I4)
4664                         RELOP_CAST(i, <, guint32);
4665                         MINT_IN_BREAK;
4666                 MINT_IN_CASE(MINT_CLT_UN_I8)
4667                         RELOP_CAST(l, <, guint64);
4668                         MINT_IN_BREAK;
4669                 MINT_IN_CASE(MINT_CLT_UN_R8)
4670                         --sp; 
4671                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4672                                 sp [-1].data.i = 1;
4673                         else
4674                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
4675                         ++ip;
4676                         MINT_IN_BREAK;
4677                 MINT_IN_CASE(MINT_LDFTN) {
4678                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
4679                         ++sp;
4680                         ip += 2;
4681                         MINT_IN_BREAK;
4682                 }
4683                 MINT_IN_CASE(MINT_LDVIRTFTN) {
4684                         InterpMethod *m = rtm->data_items [* (guint16 *)(ip + 1)];
4685                         ip += 2;
4686                         --sp;
4687                         if (!sp->data.p)
4688                                 THROW_EX (mono_get_exception_null_reference (), ip - 2);
4689                                 
4690                         sp->data.p = get_virtual_method (m, sp->data.p);
4691                         ++sp;
4692                         MINT_IN_BREAK;
4693                 }
4694
4695 #define LDARG(datamem, argtype) \
4696         sp->data.datamem = * (argtype *)(frame->args + * (guint16 *)(ip + 1)); \
4697         ip += 2; \
4698         ++sp; 
4699         
4700                 MINT_IN_CASE(MINT_LDARG_I1) LDARG(i, gint8); MINT_IN_BREAK;
4701                 MINT_IN_CASE(MINT_LDARG_U1) LDARG(i, guint8); MINT_IN_BREAK;
4702                 MINT_IN_CASE(MINT_LDARG_I2) LDARG(i, gint16); MINT_IN_BREAK;
4703                 MINT_IN_CASE(MINT_LDARG_U2) LDARG(i, guint16); MINT_IN_BREAK;
4704                 MINT_IN_CASE(MINT_LDARG_I4) LDARG(i, gint32); MINT_IN_BREAK;
4705                 MINT_IN_CASE(MINT_LDARG_I8) LDARG(l, gint64); MINT_IN_BREAK;
4706                 MINT_IN_CASE(MINT_LDARG_R4) LDARG(f, float); MINT_IN_BREAK;
4707                 MINT_IN_CASE(MINT_LDARG_R8) LDARG(f, double); MINT_IN_BREAK;
4708                 MINT_IN_CASE(MINT_LDARG_O) LDARG(p, gpointer); MINT_IN_BREAK;
4709                 MINT_IN_CASE(MINT_LDARG_P) LDARG(p, gpointer); MINT_IN_BREAK;
4710
4711                 MINT_IN_CASE(MINT_LDARG_VT)
4712                         sp->data.p = vt_sp;
4713                         i32 = READ32(ip + 2);
4714                         memcpy(sp->data.p, frame->args + * (guint16 *)(ip + 1), i32);
4715                         vt_sp += (i32 + 7) & ~7;
4716                         ip += 4;
4717                         ++sp;
4718                         MINT_IN_BREAK;
4719
4720 #define STARG(datamem, argtype) \
4721         --sp; \
4722         * (argtype *)(frame->args + * (guint16 *)(ip + 1)) = sp->data.datamem; \
4723         ip += 2; \
4724         
4725                 MINT_IN_CASE(MINT_STARG_I1) STARG(i, gint8); MINT_IN_BREAK;
4726                 MINT_IN_CASE(MINT_STARG_U1) STARG(i, guint8); MINT_IN_BREAK;
4727                 MINT_IN_CASE(MINT_STARG_I2) STARG(i, gint16); MINT_IN_BREAK;
4728                 MINT_IN_CASE(MINT_STARG_U2) STARG(i, guint16); MINT_IN_BREAK;
4729                 MINT_IN_CASE(MINT_STARG_I4) STARG(i, gint32); MINT_IN_BREAK;
4730                 MINT_IN_CASE(MINT_STARG_I8) STARG(l, gint64); MINT_IN_BREAK;
4731                 MINT_IN_CASE(MINT_STARG_R4) STARG(f, float); MINT_IN_BREAK;
4732                 MINT_IN_CASE(MINT_STARG_R8) STARG(f, double); MINT_IN_BREAK;
4733                 MINT_IN_CASE(MINT_STARG_O) STARG(p, gpointer); MINT_IN_BREAK;
4734                 MINT_IN_CASE(MINT_STARG_P) STARG(p, gpointer); MINT_IN_BREAK;
4735
4736                 MINT_IN_CASE(MINT_STARG_VT) 
4737                         i32 = READ32(ip + 2);
4738                         --sp;
4739                         memcpy(frame->args + * (guint16 *)(ip + 1), sp->data.p, i32);
4740                         vt_sp -= (i32 + 7) & ~7;
4741                         ip += 4;
4742                         MINT_IN_BREAK;
4743
4744 #define STINARG(datamem, argtype) \
4745         do { \
4746                 int n = * (guint16 *)(ip + 1); \
4747                 * (argtype *)(frame->args + rtm->arg_offsets [n]) = frame->stack_args [n].data.datamem; \
4748                 ip += 2; \
4749         } while (0)
4750         
4751                 MINT_IN_CASE(MINT_STINARG_I1) STINARG(i, gint8); MINT_IN_BREAK;
4752                 MINT_IN_CASE(MINT_STINARG_U1) STINARG(i, guint8); MINT_IN_BREAK;
4753                 MINT_IN_CASE(MINT_STINARG_I2) STINARG(i, gint16); MINT_IN_BREAK;
4754                 MINT_IN_CASE(MINT_STINARG_U2) STINARG(i, guint16); MINT_IN_BREAK;
4755                 MINT_IN_CASE(MINT_STINARG_I4) STINARG(i, gint32); MINT_IN_BREAK;
4756                 MINT_IN_CASE(MINT_STINARG_I8) STINARG(l, gint64); MINT_IN_BREAK;
4757                 MINT_IN_CASE(MINT_STINARG_R4) STINARG(f, float); MINT_IN_BREAK;
4758                 MINT_IN_CASE(MINT_STINARG_R8) STINARG(f, double); MINT_IN_BREAK;
4759                 MINT_IN_CASE(MINT_STINARG_O) STINARG(p, gpointer); MINT_IN_BREAK;
4760                 MINT_IN_CASE(MINT_STINARG_P) STINARG(p, gpointer); MINT_IN_BREAK;
4761
4762                 MINT_IN_CASE(MINT_STINARG_VT) {
4763                         int n = * (guint16 *)(ip + 1);
4764                         i32 = READ32(ip + 2);
4765                         memcpy (frame->args + rtm->arg_offsets [n], frame->stack_args [n].data.p, i32);
4766                         ip += 4;
4767                         MINT_IN_BREAK;
4768                 }
4769
4770                 MINT_IN_CASE(MINT_PROF_ENTER) {
4771                         ip += 1;
4772
4773                         if (MONO_PROFILER_ENABLED (method_enter)) {
4774                                 MonoProfilerCallContext *prof_ctx = NULL;
4775
4776                                 if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_ENTER_CONTEXT) {
4777                                         prof_ctx = g_new0 (MonoProfilerCallContext, 1);
4778                                         prof_ctx->interp_frame = frame;
4779                                         prof_ctx->method = frame->imethod->method;
4780                                 }
4781
4782                                 MONO_PROFILER_RAISE (method_enter, (frame->imethod->method, prof_ctx));
4783
4784                                 g_free (prof_ctx);
4785                         }
4786
4787                         MINT_IN_BREAK;
4788                 }
4789
4790                 MINT_IN_CASE(MINT_LDARGA)
4791                         sp->data.p = frame->args + * (guint16 *)(ip + 1);
4792                         ip += 2;
4793                         ++sp;
4794                         MINT_IN_BREAK;
4795
4796 #define LDLOC(datamem, argtype) \
4797         sp->data.datamem = * (argtype *)(locals + * (guint16 *)(ip + 1)); \
4798         ip += 2; \
4799         ++sp; 
4800         
4801                 MINT_IN_CASE(MINT_LDLOC_I1) LDLOC(i, gint8); MINT_IN_BREAK;
4802                 MINT_IN_CASE(MINT_LDLOC_U1) LDLOC(i, guint8); MINT_IN_BREAK;
4803                 MINT_IN_CASE(MINT_LDLOC_I2) LDLOC(i, gint16); MINT_IN_BREAK;
4804                 MINT_IN_CASE(MINT_LDLOC_U2) LDLOC(i, guint16); MINT_IN_BREAK;
4805                 MINT_IN_CASE(MINT_LDLOC_I4) LDLOC(i, gint32); MINT_IN_BREAK;
4806                 MINT_IN_CASE(MINT_LDLOC_I8) LDLOC(l, gint64); MINT_IN_BREAK;
4807                 MINT_IN_CASE(MINT_LDLOC_R4) LDLOC(f, float); MINT_IN_BREAK;
4808                 MINT_IN_CASE(MINT_LDLOC_R8) LDLOC(f, double); MINT_IN_BREAK;
4809                 MINT_IN_CASE(MINT_LDLOC_O) LDLOC(p, gpointer); MINT_IN_BREAK;
4810                 MINT_IN_CASE(MINT_LDLOC_P) LDLOC(p, gpointer); MINT_IN_BREAK;
4811
4812                 MINT_IN_CASE(MINT_LDLOC_VT)
4813                         sp->data.p = vt_sp;
4814                         i32 = READ32(ip + 2);
4815                         memcpy(sp->data.p, locals + * (guint16 *)(ip + 1), i32);
4816                         vt_sp += (i32 + 7) & ~7;
4817                         ip += 4;
4818                         ++sp;
4819                         MINT_IN_BREAK;
4820
4821                 MINT_IN_CASE(MINT_LDLOCA_S)
4822                         sp->data.p = locals + * (guint16 *)(ip + 1);
4823                         ip += 2;
4824                         ++sp;
4825                         MINT_IN_BREAK;
4826
4827 #define STLOC(datamem, argtype) \
4828         --sp; \
4829         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp->data.datamem; \
4830         ip += 2;
4831         
4832                 MINT_IN_CASE(MINT_STLOC_I1) STLOC(i, gint8); MINT_IN_BREAK;
4833                 MINT_IN_CASE(MINT_STLOC_U1) STLOC(i, guint8); MINT_IN_BREAK;
4834                 MINT_IN_CASE(MINT_STLOC_I2) STLOC(i, gint16); MINT_IN_BREAK;
4835                 MINT_IN_CASE(MINT_STLOC_U2) STLOC(i, guint16); MINT_IN_BREAK;
4836                 MINT_IN_CASE(MINT_STLOC_I4) STLOC(i, gint32); MINT_IN_BREAK;
4837                 MINT_IN_CASE(MINT_STLOC_I8) STLOC(l, gint64); MINT_IN_BREAK;
4838                 MINT_IN_CASE(MINT_STLOC_R4) STLOC(f, float); MINT_IN_BREAK;
4839                 MINT_IN_CASE(MINT_STLOC_R8) STLOC(f, double); MINT_IN_BREAK;
4840                 MINT_IN_CASE(MINT_STLOC_O) STLOC(p, gpointer); MINT_IN_BREAK;
4841                 MINT_IN_CASE(MINT_STLOC_P) STLOC(p, gpointer); MINT_IN_BREAK;
4842
4843 #define STLOC_NP(datamem, argtype) \
4844         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp [-1].data.datamem; \
4845         ip += 2;
4846
4847                 MINT_IN_CASE(MINT_STLOC_NP_I4) STLOC_NP(i, gint32); MINT_IN_BREAK;
4848                 MINT_IN_CASE(MINT_STLOC_NP_O) STLOC_NP(p, gpointer); MINT_IN_BREAK;
4849
4850                 MINT_IN_CASE(MINT_STLOC_VT)
4851                         i32 = READ32(ip + 2);
4852                         --sp;
4853                         memcpy(locals + * (guint16 *)(ip + 1), sp->data.p, i32);
4854                         vt_sp -= (i32 + 7) & ~7;
4855                         ip += 4;
4856                         MINT_IN_BREAK;
4857
4858                 MINT_IN_CASE(MINT_LOCALLOC) {
4859                         if (sp != frame->stack + 1) /*FIX?*/
4860                                 THROW_EX (mono_get_exception_execution_engine (NULL), ip);
4861
4862                         int len = sp [-1].data.i;
4863                         sp [-1].data.p = alloca (len);
4864                         MonoMethodHeader *header = mono_method_get_header_checked (frame->imethod->method, &error);
4865                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4866                         if (header && header->init_locals)
4867                                 memset (sp [-1].data.p, 0, len);
4868                         ++ip;
4869                         MINT_IN_BREAK;
4870                 }
4871                 MINT_IN_CASE(MINT_ENDFILTER)
4872                         /* top of stack is result of filter */
4873                         frame->retval = &sp [-1];
4874                         goto exit_frame;
4875                 MINT_IN_CASE(MINT_INITOBJ)
4876                         --sp;
4877                         memset (sp->data.vt, 0, READ32(ip + 1));
4878                         ip += 3;
4879                         MINT_IN_BREAK;
4880                 MINT_IN_CASE(MINT_CPBLK)
4881                         sp -= 3;
4882                         if (!sp [0].data.p || !sp [1].data.p)
4883                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
4884                         ++ip;
4885                         /* FIXME: value and size may be int64... */
4886                         memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
4887                         MINT_IN_BREAK;
4888 #if 0
4889                 MINT_IN_CASE(MINT_CONSTRAINED_) {
4890                         guint32 token;
4891                         /* FIXME: implement */
4892                         ++ip;
4893                         token = READ32 (ip);
4894                         ip += 2;
4895                         MINT_IN_BREAK;
4896                 }
4897 #endif
4898                 MINT_IN_CASE(MINT_INITBLK)
4899                         sp -= 3;
4900                         if (!sp [0].data.p)
4901                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
4902                         ++ip;
4903                         /* FIXME: value and size may be int64... */
4904                         memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
4905                         MINT_IN_BREAK;
4906 #if 0
4907                 MINT_IN_CASE(MINT_NO_)
4908                         /* FIXME: implement */
4909                         ip += 2;
4910                         MINT_IN_BREAK;
4911 #endif
4912            MINT_IN_CASE(MINT_RETHROW) {
4913                         /* 
4914                          * need to clarify what this should actually do:
4915                          * start the search from the last found handler in
4916                          * this method or continue in the caller or what.
4917                          * Also, do we need to run finally/fault handlers after a retrow?
4918                          * Well, this implementation will follow the usual search
4919                          * for an handler, considering the current ip as throw spot.
4920                          * We need to NULL frame->ex_handler for the later code to
4921                          * actually run the new found handler.
4922                          */
4923                         int exvar_offset = *(guint16*)(ip + 1);
4924                         frame->ex_handler = NULL;
4925                         THROW_EX_GENERAL (*(MonoException**)(frame->locals + exvar_offset), ip - 1, TRUE);
4926                         MINT_IN_BREAK;
4927            }
4928                 MINT_IN_DEFAULT
4929                         g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip, mono_interp_opname[*ip], ip-rtm->code);
4930                         THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip);
4931                 }
4932         }
4933
4934         g_assert_not_reached ();
4935         /*
4936          * Exception handling code.
4937          * The exception object is stored in frame->ex.
4938          */
4939
4940         handle_exception:
4941         {
4942                 int i;
4943                 guint32 ip_offset;
4944                 InterpFrame *inv;
4945                 MonoExceptionClause *clause;
4946                 /*char *message;*/
4947                 MonoObject *ex_obj;
4948
4949 #if DEBUG_INTERP
4950                 if (tracing)
4951                         g_print ("* Handling exception '%s' at IL_%04x\n", 
4952                                 frame->ex == NULL ? "** Unknown **" : mono_object_class (frame->ex)->name, 
4953                                 rtm == NULL ? 0 : frame->ip - rtm->code);
4954 #endif
4955                 if (die_on_exception)
4956                         goto die_on_ex;
4957
4958                 for (inv = frame; inv; inv = inv->parent) {
4959                         MonoMethod *method;
4960                         if (inv->imethod == NULL)
4961                                 continue;
4962                         method = inv->imethod->method;
4963                         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
4964                                 continue;
4965                         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
4966                                 continue;
4967                         if (inv->ip == NULL)
4968                                 continue;
4969                         ip_offset = inv->ip - inv->imethod->code;
4970                         inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one  - this one wins */
4971                         for (i = 0; i < inv->imethod->num_clauses; ++i) {
4972                                 clause = &inv->imethod->clauses [i];
4973 #if DEBUG_INTERP
4974                                 g_print ("* clause [%d]: %p\n", i, clause);
4975 #endif
4976                                 if (!MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
4977                                         continue;
4978                                 }
4979                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
4980 #if DEBUG_INTERP
4981                                         if (tracing)
4982                                                 g_print ("* Filter found at '%s'\n", method->name);
4983 #endif
4984                                         InterpFrame dup_frame;
4985                                         stackval retval;
4986                                         memcpy (&dup_frame, inv, sizeof (InterpFrame));
4987                                         dup_frame.retval = &retval;
4988                                         ves_exec_method_with_context (&dup_frame, context, inv->imethod->code + clause->data.filter_offset, frame->ex, -1);
4989                                         if (dup_frame.retval->data.i) {
4990 #if DEBUG_INTERP
4991                                                 if (tracing)
4992                                                         g_print ("* Matched Filter at '%s'\n", method->name);
4993 #endif
4994                                                 inv->ex_handler = clause;
4995                                                 *(MonoException**)(inv->locals + inv->imethod->exvar_offsets [i]) = frame->ex;
4996                                                 goto handle_finally;
4997                                         }
4998                                 } else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
4999                                         MonoObject *isinst_obj = mono_object_isinst_checked ((MonoObject*)frame->ex, clause->data.catch_class, &error);
5000                                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
5001                                         if (isinst_obj) {
5002                                                 /* 
5003                                                  * OK, we found an handler, now we need to execute the finally
5004                                                  * and fault blocks before branching to the handler code.
5005                                                  */
5006 #if DEBUG_INTERP
5007                                                 if (tracing)
5008                                                         g_print ("* Found handler at '%s'\n", method->name);
5009 #endif
5010                                                 inv->ex_handler = clause;
5011                                                 *(MonoException**)(inv->locals + inv->imethod->exvar_offsets [i]) = frame->ex;
5012                                                 goto handle_finally;
5013                                         }
5014                                 }
5015                         }
5016                 }
5017                 /*
5018                  * If we get here, no handler was found: print a stack trace.
5019                  */
5020                 for (inv = frame; inv; inv = inv->parent) {
5021                         if (inv->invoke_trap)
5022                                 goto handle_finally;
5023                 }
5024 die_on_ex:
5025                 ex_obj = (MonoObject *) frame->ex;
5026                 mono_unhandled_exception (ex_obj);
5027                 MonoJitTlsData *jit_tls = (MonoJitTlsData *) mono_tls_get_jit_tls ();
5028                 jit_tls->abort_func (ex_obj);
5029                 g_assert_not_reached ();
5030         }
5031         handle_finally:
5032         {
5033                 int i;
5034                 guint32 ip_offset;
5035                 MonoExceptionClause *clause;
5036                 GSList *old_list = finally_ips;
5037                 MonoMethod *method = frame->imethod->method;
5038                 MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
5039                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
5040                 
5041 #if DEBUG_INTERP
5042                 if (tracing)
5043                         g_print ("* Handle finally IL_%04x\n", endfinally_ip == NULL ? 0 : endfinally_ip - rtm->code);
5044 #endif
5045                 if (rtm == NULL || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
5046                                 || (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
5047                         goto exit_frame;
5048                 }
5049                 ip_offset = frame->ip - rtm->code;
5050
5051                 if (endfinally_ip != NULL)
5052                         finally_ips = g_slist_prepend(finally_ips, (void *)endfinally_ip);
5053                 for (i = 0; i < header->num_clauses; ++i)
5054                         if (frame->ex_handler == &rtm->clauses [i])
5055                                 break;
5056                 while (i > 0) {
5057                         --i;
5058                         clause = &rtm->clauses [i];
5059                         if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset) && (endfinally_ip == NULL || !(MONO_OFFSET_IN_CLAUSE (clause, endfinally_ip - rtm->code)))) {
5060                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
5061                                         ip = rtm->code + clause->handler_offset;
5062                                         finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
5063 #if DEBUG_INTERP
5064                                         if (tracing)
5065                                                 g_print ("* Found finally at IL_%04x with exception: %s\n", clause->handler_offset, frame->ex? "yes": "no");
5066 #endif
5067                                 }
5068                         }
5069                 }
5070
5071                 endfinally_ip = NULL;
5072
5073                 if (old_list != finally_ips && finally_ips) {
5074                         ip = finally_ips->data;
5075                         finally_ips = g_slist_remove (finally_ips, ip);
5076                         sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
5077                         goto main_loop;
5078                 }
5079
5080                 /*
5081                  * If an exception is set, we need to execute the fault handler, too,
5082                  * otherwise, we continue normally.
5083                  */
5084                 if (frame->ex)
5085                         goto handle_fault;
5086                 ves_abort();
5087         }
5088         handle_fault:
5089         {
5090                 int i;
5091                 guint32 ip_offset;
5092                 MonoExceptionClause *clause;
5093                 GSList *old_list = finally_ips;
5094                 MonoMethod *method = frame->imethod->method;
5095                 MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
5096                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
5097                 
5098 #if DEBUG_INTERP
5099                 if (tracing)
5100                         g_print ("* Handle fault\n");
5101 #endif
5102                 ip_offset = frame->ip - rtm->code;
5103                 for (i = 0; i < header->num_clauses; ++i) {
5104                         clause = &rtm->clauses [i];
5105                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
5106                                 ip = rtm->code + clause->handler_offset;
5107                                 finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
5108 #if DEBUG_INTERP
5109                                 if (tracing)
5110                                         g_print ("* Executing handler at IL_%04x\n", clause->handler_offset);
5111 #endif
5112                         }
5113                 }
5114
5115                 if (old_list != finally_ips && finally_ips) {
5116                         ip = finally_ips->data;
5117                         finally_ips = g_slist_remove (finally_ips, ip);
5118                         sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
5119                         goto main_loop;
5120                 }
5121         }
5122         handle_catch:
5123         {
5124                 /*
5125                  * If the handler for the exception was found in this method, we jump
5126                  * to it right away, otherwise we return and let the caller run
5127                  * the finally, fault and catch blocks.
5128                  * This same code should be present in the endfault opcode, but it
5129                  * is corrently not assigned in the ECMA specs: LAMESPEC.
5130                  */
5131                 if (frame->ex_handler) {
5132 #if DEBUG_INTERP
5133                         if (tracing)
5134                                 g_print ("* Executing handler at IL_%04x\n", frame->ex_handler->handler_offset);
5135 #endif
5136                         ip = rtm->code + frame->ex_handler->handler_offset;
5137                         sp = frame->stack;
5138                         vt_sp = (unsigned char *) sp + rtm->stack_size;
5139                         sp->data.p = frame->ex;
5140                         ++sp;
5141                         goto main_loop;
5142                 }
5143                 goto exit_frame;
5144         }
5145 exit_frame:
5146
5147         if (!frame->ex && MONO_PROFILER_ENABLED (method_leave) &&
5148             frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE) {
5149                 MonoProfilerCallContext *prof_ctx = NULL;
5150
5151                 if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE_CONTEXT) {
5152                         prof_ctx = g_new0 (MonoProfilerCallContext, 1);
5153                         prof_ctx->interp_frame = frame;
5154                         prof_ctx->method = frame->imethod->method;
5155
5156                         MonoType *rtype = mono_method_signature (frame->imethod->method)->ret;
5157
5158                         switch (rtype->type) {
5159                         case MONO_TYPE_VOID:
5160                                 break;
5161                         case MONO_TYPE_VALUETYPE:
5162                                 prof_ctx->return_value = frame->retval->data.p;
5163                                 break;
5164                         default:
5165                                 prof_ctx->return_value = frame->retval;
5166                                 break;
5167                         }
5168                 }
5169
5170                 MONO_PROFILER_RAISE (method_leave, (frame->imethod->method, prof_ctx));
5171
5172                 g_free (prof_ctx);
5173         } else if (frame->ex && frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE)
5174                 MONO_PROFILER_RAISE (method_exception_leave, (frame->imethod->method, &frame->ex->object));
5175
5176         DEBUG_LEAVE ();
5177 }
5178
5179 void
5180 ves_exec_method (InterpFrame *frame)
5181 {
5182         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
5183         ThreadContext context_struct;
5184         MonoDomain *domain = frame->imethod->domain;
5185         MonoError error;
5186         jmp_buf env;
5187
5188         frame->ex = NULL;
5189
5190         if (setjmp(env)) {
5191                 mono_unhandled_exception ((MonoObject*)frame->ex);
5192                 return;
5193         }
5194         if (context == NULL) {
5195                 context = &context_struct;
5196                 context_struct.base_frame = frame;
5197                 context_struct.current_frame = NULL;
5198                 context_struct.env_frame = frame;
5199                 context_struct.current_env = &env;
5200                 context_struct.search_for_handler = 0;
5201                 context_struct.managed_code = 0;
5202                 set_context (context);
5203         }
5204         frame->ip = NULL;
5205         frame->parent = context->current_frame;
5206         frame->imethod = mono_interp_get_imethod (domain, frame->method, &error);
5207         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
5208         context->managed_code = 1;
5209         ves_exec_method_with_context (frame, context, NULL, NULL, -1);
5210         context->managed_code = 0;
5211         if (frame->ex) {
5212                 if (context != &context_struct && context->current_env) {
5213                         context->env_frame->ex = frame->ex;
5214                         longjmp (*context->current_env, 1);
5215                 }
5216                 else
5217                         mono_unhandled_exception ((MonoObject*)frame->ex);
5218         }
5219         if (context->base_frame == frame)
5220                 set_context (NULL);
5221         else
5222                 context->current_frame = frame->parent;
5223 }
5224
5225 void
5226 mono_interp_parse_options (const char *options)
5227 {
5228         char **args, **ptr;
5229
5230         args = g_strsplit (options, ",", -1);
5231         for (ptr = args; ptr && *ptr; ptr ++) {
5232                 char *arg = *ptr;
5233
5234                 if (strncmp (arg, "jit=", 4) == 0)
5235                         jit_classes = g_slist_prepend (jit_classes, arg + 4);
5236         }
5237 }
5238
5239 void
5240 mono_interp_init ()
5241 {
5242         mono_native_tls_alloc (&thread_context_id, NULL);
5243         set_context (NULL);
5244
5245         mono_interp_transform_init ();
5246 }
5247
5248 typedef int (*TestMethod) (void);
5249
5250 static void
5251 interp_regression_step (MonoImage *image, int verbose, int *total_run, int *total, GTimer *timer, MonoDomain *domain)
5252 {
5253         int result, expected, failed, cfailed, run;
5254         double elapsed, transform_time;
5255         int i;
5256         MonoObject *result_obj;
5257         static gboolean filter_method_init = FALSE;
5258         static const char *filter_method = NULL;
5259
5260         g_print ("Test run: image=%s\n", mono_image_get_filename (image));
5261         cfailed = failed = run = 0;
5262         transform_time = elapsed = 0.0;
5263
5264         g_timer_start (timer);
5265         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
5266                 MonoObject *exc = NULL;
5267                 MonoError error;
5268                 MonoMethod *method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
5269                 if (!method) {
5270                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
5271                         continue;
5272                 }
5273
5274                 if (!filter_method_init) {
5275                         filter_method = g_getenv ("INTERP_FILTER_METHOD");
5276                         filter_method_init = TRUE;
5277                 }
5278                 gboolean filter = FALSE;
5279                 if (filter_method) {
5280                         const char *name = filter_method;
5281
5282                         if ((strchr (name, '.') > name) || strchr (name, ':')) {
5283                                 MonoMethodDesc *desc = mono_method_desc_new (name, TRUE);
5284                                 filter = mono_method_desc_full_match (desc, method);
5285                                 mono_method_desc_free (desc);
5286                         } else {
5287                                 filter = strcmp (method->name, name) == 0;
5288                         }
5289                 } else { /* no filter, check for `Category' attribute on method */
5290                         filter = TRUE;
5291                         MonoCustomAttrInfo* ainfo = mono_custom_attrs_from_method_checked (method, &error);
5292                         mono_error_cleanup (&error);
5293
5294                         if (ainfo) {
5295                                 int j;
5296                                 for (j = 0; j < ainfo->num_attrs && filter; ++j) {
5297                                         MonoCustomAttrEntry *centry = &ainfo->attrs [j];
5298                                         if (centry->ctor == NULL)
5299                                                 continue;
5300
5301                                         MonoClass *klass = centry->ctor->klass;
5302                                         if (strcmp (klass->name, "CategoryAttribute"))
5303                                                 continue;
5304
5305                                         MonoObject *obj = mono_custom_attrs_get_attr_checked (ainfo, klass, &error);
5306                                         /* FIXME: there is an ordering problem if there're multiple attributes, do this instead:
5307                                          * MonoObject *obj = create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, &error); */
5308                                         mono_error_cleanup (&error);
5309                                         MonoMethod *getter = mono_class_get_method_from_name (klass, "get_Category", -1);
5310                                         MonoObject *str = mono_interp_runtime_invoke (getter, obj, NULL, &exc, &error);
5311                                         mono_error_cleanup (&error);
5312                                         char *utf8_str = mono_string_to_utf8_checked ((MonoString *) str, &error);
5313                                         mono_error_cleanup (&error);
5314                                         if (!strcmp (utf8_str, "!INTERPRETER")) {
5315                                                 g_print ("skip %s...\n", method->name);
5316                                                 filter = FALSE;
5317                                         }
5318                                 }
5319                         }
5320                 }
5321                 if (strncmp (method->name, "test_", 5) == 0 && filter) {
5322                         MonoError interp_error;
5323                         MonoObject *exc = NULL;
5324
5325                         result_obj = mono_interp_runtime_invoke (method, NULL, NULL, &exc, &interp_error);
5326                         if (!mono_error_ok (&interp_error)) {
5327                                 cfailed++;
5328                                 g_print ("Test '%s' execution failed.\n", method->name);
5329                         } else if (exc != NULL) {
5330                                 g_print ("Exception in Test '%s' occured:\n", method->name);
5331                                 mono_object_describe (exc);
5332                                 run++;
5333                                 failed++;
5334                         } else {
5335                                 result = *(gint32 *) mono_object_unbox (result_obj);
5336                                 expected = atoi (method->name + 5);  // FIXME: oh no.
5337                                 run++;
5338
5339                                 if (result != expected) {
5340                                         failed++;
5341                                         g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
5342                                 }
5343                         }
5344                 }
5345         }
5346         g_timer_stop (timer);
5347         elapsed = g_timer_elapsed (timer, NULL);
5348         if (failed > 0 || cfailed > 0){
5349                 g_print ("Results: total tests: %d, failed: %d, cfailed: %d (pass: %.2f%%)\n",
5350                                 run, failed, cfailed, 100.0*(run-failed-cfailed)/run);
5351         } else {
5352                 g_print ("Results: total tests: %d, all pass \n",  run);
5353         }
5354
5355         g_print ("Elapsed time: %f secs (%f, %f)\n\n", elapsed,
5356                         elapsed - transform_time, transform_time);
5357         *total += failed + cfailed;
5358         *total_run += run;
5359 }
5360
5361 static int
5362 interp_regression (MonoImage *image, int verbose, int *total_run)
5363 {
5364         MonoMethod *method;
5365         GTimer *timer = g_timer_new ();
5366         MonoDomain *domain = mono_domain_get ();
5367         guint32 i;
5368         int total;
5369
5370         /* load the metadata */
5371         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
5372                 MonoError error;
5373                 method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
5374                 if (!method) {
5375                         mono_error_cleanup (&error);
5376                         continue;
5377                 }
5378                 mono_class_init (method->klass);
5379         }
5380
5381         total = 0;
5382         *total_run = 0;
5383         interp_regression_step (image, verbose, total_run, &total, timer, domain);
5384
5385         g_timer_destroy (timer);
5386         return total;
5387 }
5388
5389 int
5390 mono_interp_regression_list (int verbose, int count, char *images [])
5391 {
5392         int i, total, total_run, run;
5393         
5394         total_run = total = 0;
5395         for (i = 0; i < count; ++i) {
5396                 MonoAssembly *ass = mono_assembly_open_predicate (images [i], FALSE, FALSE, NULL, NULL, NULL);
5397                 if (!ass) {
5398                         g_warning ("failed to load assembly: %s", images [i]);
5399                         continue;
5400                 }
5401                 total += interp_regression (mono_assembly_get_image (ass), verbose, &run);
5402                 total_run += run;
5403         }
5404         if (total > 0) {
5405                 g_print ("Overall results: tests: %d, failed: %d (pass: %.2f%%)\n", total_run, total, 100.0*(total_run-total)/total_run);
5406         } else {
5407                 g_print ("Overall results: tests: %d, 100%% pass\n", total_run);
5408         }
5409         
5410         return total;
5411 }
5412
5413 /*
5414  * mono_interp_set_resume_state:
5415  *
5416  *   Set the state the interpeter will continue to execute from after execution returns to the interpreter.
5417  */
5418 void
5419 mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoInterpFrameHandle interp_frame, gpointer handler_ip)
5420 {
5421         ThreadContext *context;
5422
5423         g_assert (jit_tls);
5424         context = jit_tls->interp_context;
5425         g_assert (context);
5426
5427         context->has_resume_state = TRUE;
5428         context->handler_frame = interp_frame;
5429         /* This is on the stack, so it doesn't need a wbarrier */
5430         context->handler_frame->ex = ex;
5431         context->handler_ip = handler_ip;
5432 }
5433
5434 /*
5435  * mono_interp_run_finally:
5436  *
5437  *   Run the finally clause identified by CLAUSE_INDEX in the intepreter frame given by
5438  * frame->interp_frame.
5439  */
5440 void
5441 mono_interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip)
5442 {
5443        InterpFrame *iframe = frame->interp_frame;
5444        ThreadContext *context = mono_native_tls_get_value (thread_context_id);
5445
5446        ves_exec_method_with_context (iframe, context, handler_ip, NULL, clause_index);
5447 }
5448
5449 typedef struct {
5450         InterpFrame *current;
5451 } StackIter;
5452
5453 /*
5454  * mono_interp_frame_iter_init:
5455  *
5456  *   Initialize an iterator for iterating through interpreted frames.
5457  */
5458 void
5459 mono_interp_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_data)
5460 {
5461         StackIter *stack_iter = (StackIter*)iter;
5462
5463         stack_iter->current = (InterpFrame*)interp_exit_data;
5464 }
5465
5466 gboolean
5467 mono_interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame)
5468 {
5469         StackIter *stack_iter = (StackIter*)iter;
5470         InterpFrame *iframe = stack_iter->current;
5471
5472         memset (frame, 0, sizeof (StackFrameInfo));
5473         /* pinvoke frames doesn't have imethod set */
5474         while (iframe && !(iframe->imethod && iframe->imethod->code))
5475                 iframe = iframe->parent;
5476         if (!iframe)
5477                 return FALSE;
5478
5479         frame->type = FRAME_TYPE_INTERP;
5480         // FIXME:
5481         frame->domain = mono_domain_get ();
5482         frame->interp_frame = iframe;
5483         frame->method = iframe->imethod->method;
5484         frame->actual_method = frame->method;
5485         /* This is the offset in the interpreter IR */
5486         frame->native_offset = (guint8*)iframe->ip - (guint8*)iframe->imethod->code;
5487         frame->ji = iframe->imethod->jinfo;
5488
5489         stack_iter->current = iframe->parent;
5490
5491         return TRUE;
5492 }
5493
5494 MonoJitInfo*
5495 mono_interp_find_jit_info (MonoDomain *domain, MonoMethod *method)
5496 {
5497         InterpMethod* rtm;
5498
5499         rtm = lookup_imethod (domain, method);
5500         if (rtm)
5501                 return rtm->jinfo;
5502         else
5503                 return NULL;
5504 }
5505
5506 void
5507 mono_interp_set_breakpoint (MonoJitInfo *jinfo, gpointer ip)
5508 {
5509         guint16 *code = (guint16*)ip;
5510         g_assert (*code == MINT_SDB_SEQ_POINT);
5511         *code = MINT_SDB_BREAKPOINT;
5512 }
5513
5514 void
5515 mono_interp_clear_breakpoint (MonoJitInfo *jinfo, gpointer ip)
5516 {
5517         guint16 *code = (guint16*)ip;
5518         g_assert (*code == MINT_SDB_BREAKPOINT);
5519         *code = MINT_SDB_SEQ_POINT;
5520 }
5521
5522 MonoJitInfo*
5523 mono_interp_frame_get_jit_info (MonoInterpFrameHandle frame)
5524 {
5525         InterpFrame *iframe = (InterpFrame*)frame;
5526
5527         g_assert (iframe->imethod);
5528         return iframe->imethod->jinfo;
5529 }
5530
5531 gpointer
5532 mono_interp_frame_get_ip (MonoInterpFrameHandle frame)
5533 {
5534         InterpFrame *iframe = (InterpFrame*)frame;
5535
5536         g_assert (iframe->imethod);
5537         return (gpointer)iframe->ip;
5538 }
5539
5540 gpointer
5541 mono_interp_frame_get_arg (MonoInterpFrameHandle frame, int pos)
5542 {
5543         InterpFrame *iframe = (InterpFrame*)frame;
5544
5545         g_assert (iframe->imethod);
5546
5547         int arg_offset = iframe->imethod->arg_offsets [pos + (iframe->imethod->hasthis ? 1 : 0)];
5548
5549         return iframe->args + arg_offset;
5550 }
5551
5552 gpointer
5553 mono_interp_frame_get_local (MonoInterpFrameHandle frame, int pos)
5554 {
5555         InterpFrame *iframe = (InterpFrame*)frame;
5556
5557         g_assert (iframe->imethod);
5558
5559         return iframe->locals + iframe->imethod->local_offsets [pos];
5560 }
5561
5562 gpointer
5563 mono_interp_frame_get_this (MonoInterpFrameHandle frame)
5564 {
5565         InterpFrame *iframe = (InterpFrame*)frame;
5566
5567         g_assert (iframe->imethod);
5568         g_assert (iframe->imethod->hasthis);
5569
5570         int arg_offset = iframe->imethod->arg_offsets [0];
5571
5572         return iframe->args + arg_offset;
5573 }
5574
5575 void
5576 mono_interp_start_single_stepping (void)
5577 {
5578         ss_enabled = TRUE;
5579 }
5580
5581 void
5582 mono_interp_stop_single_stepping (void)
5583 {
5584         ss_enabled = FALSE;
5585 }