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