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