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